/******************** 鑫盛电子工作室 ******************** * 文件名 :main.c * 描述 :通过串口调试软件,向板子发送数据,板子接收到数据后,立即回传给电脑。 * 实验平台:MINI STM32开发板 基于STM32F103C8T6 * 库版本 :ST3.0.0 * 淘宝店:http://shop66177872.taobao.com *********************************************************/ #include "stm32f10x.h" #include "usart1.h" #include "led.h" #include "Time_test.h" #include "sys_lamp.h" #include "can.h" #include "uart_str.h" SYS_DATA_TYPE sys_data; void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; /* Set the Vector Table base location at 0x08000000 */ NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); /* 2 bit for pre-emption priority, 2 bits for subpriority */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); /* Enable the Ethernet global Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } volatile u32 time; // ms 计时变量 ////////////////////////////////////////////////////////////// //485 modbus //Modbus 通讯数据报文 // 下行 01 03 00 00 00 01 84 0A//查询动作次数 // 上行 01 03 02 00 01 79 84 //上报数 // 下行 01 06 00 00 00 00 89 CA//清零计数 // 下行 01 06 00 01 00 01 19 CA//设置运行方式 ////////////////////////////////////////////////////////////// ////////////////////////////////crc 校验//////////////////////////////////// #define U16 unsigned int #define U8 unsigned char static U16 Get_CRC16(U8 *value, U8 length) { U16 crc16 = 0xFFFF;/* 设置十六位的寄存器,初值为0xFFFF */ U8 i; U8 j; for(j = 0; j < length; j++)/* 数组中的每个字节依次循环进入 */ { crc16 = crc16 ^ value[j];/* 寄存器的值与数组值异或 */ for(i = 0; i < 8; i++)/* 8次移位操作 */ { if(crc16 & 1)/* CRC寄存器的值最低位判断 */ { crc16 >>= 1;/* CRC寄存器的值右移一位 */ crc16 ^= 0xA001;/* CRC寄存器的值与预存值异或 */ } else { crc16 >>= 1;/* CRC寄存器的值右移一位 */ } } } crc16=(crc16/256)+((crc16%256)<<8); return crc16;/* 返回CRC校验值 */ } unsigned char buff_send[20]={0xff,0xff}; unsigned char buff_get[20]={0xff,0xff}; unsigned char cnt_get=0; void buff_send_init(void) { unsigned char i; unsigned int crc_result; // for(i=0;i<16;i++) // { // buff_send[i]=0x55; // } buff_send[0]=0x01; buff_send[1]=0x03; buff_send[2]=0x02; buff_send[3]=0x00; buff_send[4]=0x01; crc_result= Get_CRC16(buff_send, 5); buff_send[5]=crc_result/256; buff_send[6]=crc_result%256; } void buff_send_init_100(void) { unsigned char i; unsigned int crc_result; // for(i=0;i<16;i++) // { // buff_send[i]=0x55; // } for(i=0;i<6;i++) { sys_data.lamp_sw[i]=0x20; } buff_send[0]=0x01; buff_send[1]=0x03; buff_send[2]=0x0C; buff_send[3]=0x00; buff_send[4]=0x01; buff_send[5]=0x00; buff_send[6]=0x01; buff_send[7]=0x00; buff_send[8]=0x01; buff_send[9]=0x00; buff_send[10]=0x01; buff_send[11]=0x00; buff_send[12]=0x01; buff_send[13]=0x00; buff_send[14]=0x01; for(i=0;i<6;i++) { buff_send[4+i*2]=sys_data.lamp_sw[i]; } crc_result= Get_CRC16(buff_send, 15); buff_send[15]=crc_result/256; buff_send[16]=crc_result%256; } void buff_send_init_200(void) { unsigned char i; unsigned int crc_result; // for(i=0;i<16;i++) // { // buff_send[i]=0x55; // } // for(i=0;i<6;i++) // { // sys_data.lamp_sw[i]=0x20; // } buff_send[0]=0x01; buff_send[1]=0x03; buff_send[2]=0x0C; buff_send[3]=0x00; buff_send[4]=0x01; buff_send[5]=0x00; buff_send[6]=0x01; buff_send[7]=0x00; buff_send[8]=0x01; buff_send[9]=0x00; buff_send[10]=0x01; buff_send[11]=0x00; buff_send[12]=0x01; buff_send[13]=0x00; buff_send[14]=0x01; for(i=0;i<6;i++) { buff_send[4+i*2]=sys_data.lamp_sw[i]; } crc_result= Get_CRC16(buff_send, 15); buff_send[15]=crc_result/256; buff_send[16]=crc_result%256; } void buff_get_clear(void) { int i; for(i=0;i<16;i++) { buff_get[i]=0xff; } } #define TRUE 1 #define FALSE 0 unsigned char flag_frame=FALSE; unsigned int cnt_frame=0; void modbus_echo(void) { if((flag_frame==TRUE) &&(buff_get[0]==0x01)&&(buff_get[1]==0x03)) { //buff_get_clear(); flag_frame=FALSE; time=0; while(time<10); RS485_Send_Data(buff_send,17); //将接收到的数据发送出去 cnt_get=0; buff_get_clear(); } } extern void main_can(void); extern void GetKey(void); //检测是否有按键按下 void LED_test(void) { LED1(ON);LED2(ON); __nop(); LED1(OFF);LED2(OFF); __nop(); } ///////////////////////////////控制io初始化///////////////////////////////////////// //#define LAMP_MODE void lamp_id_io_init(void) { //PB1 PB5 //PA4 PA5 PA6 PA7 // #ifdef LAMP_MODE //port b GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE); // 使能PB端口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1| GPIO_Pin_5; #ifdef LAMP_MODE GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; #else GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; #endif GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PB端口 GPIO_ResetBits(GPIOB, GPIO_Pin_1 | GPIO_Pin_5); // 关闭所有LED __nop(); GPIO_SetBits(GPIOB, GPIO_Pin_1 | GPIO_Pin_5); // 关闭所有LED __nop(); //port a // GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能外设时钟 //RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE); // 使能PB端口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4| GPIO_Pin_5 |GPIO_Pin_6| GPIO_Pin_7; #ifdef LAMP_MODE GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; #else GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; #endif GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA端口 GPIO_ResetBits(GPIOA, GPIO_Pin_4| GPIO_Pin_5 |GPIO_Pin_6| GPIO_Pin_7); // 关闭所有LED __nop(); GPIO_SetBits(GPIOA, GPIO_Pin_4| GPIO_Pin_5 |GPIO_Pin_6| GPIO_Pin_7); // 关闭所有LED __nop(); // #else // #endif } //////////////////////////////////////////////////////////////////////////////////// void sensor_io_init(void) { GPIO_InitTypeDef GPIO_InitStructure; //PA0 init //port a // GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能外设时钟 //RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE); // 使能PB端口时钟 GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0;// GPIO_Pin_4| GPIO_Pin_5 |GPIO_Pin_6| GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // #ifdef LAMP_MODE // GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // #else // GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // #endif GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA端口 // GPIO_ResetBits(GPIOA, GPIO_Pin_4| GPIO_Pin_5 |GPIO_Pin_6| GPIO_Pin_7); // 关闭所有LED // __nop(); // GPIO_SetBits(GPIOA, GPIO_Pin_4| GPIO_Pin_5 |GPIO_Pin_6| GPIO_Pin_7); // 关闭所有LED // __nop(); } extern unsigned char flag_20ms;//=FALSE; void sensor_read_again(void) { static int cnt=0; cnt++; if(cnt>5) {cnt=0; if((Bit_RESET == GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0))) { //state=2; //can send data //void can_tx3(u8 Data1,u8 Data2,u8 Data3) //can_tx3(0x0f,0x0f,0x40); can_tx3(sys_data.group_id,sys_data.sensor_id,0xff); //cnt++; //if(cnt>) } if(Bit_SET == GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)) { //cnt=0; can_tx3(sys_data.group_id,sys_data.sensor_id,0x00); } } } void sensor_state_read(void) { // if(Bit_SET == GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)) // { // //SYS_ID|=(1<<0); // sys_data.sensor_state=1; // //can_tx3(sys_data.group_id,sys_data.sensor_id,0x20); // __nop(); // } // // else // { // sys_data.sensor_state=0; // //can_tx3(sys_data.group_id,sys_data.sensor_id,0x20); // __nop(); // } static char state=0; int i=0; if(flag_20ms==TRUE) { flag_20ms=FALSE; switch(state) { case 0://wait falling edge if(Bit_RESET == GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)) { state=1; } break; case 1://if valid if(Bit_RESET == GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)) { state=2; //can send data //void can_tx3(u8 Data1,u8 Data2,u8 Data3) //can_tx3(0x0f,0x0f,0x40); can_tx3(sys_data.group_id,sys_data.sensor_id,0xff); for(i=0;i<5000;i++); can_tx3(sys_data.group_id,sys_data.sensor_id,0xff); for(i=0;i<5000;i++); can_tx3(sys_data.group_id,sys_data.sensor_id,0xff); for(i=0;i<5000;i++); } break; case 2://wait up edge if(Bit_SET == GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)) { state=0; //can send data //void can_tx3(u8 Data1,u8 Data2,u8 Data3) //can_tx3(0x0f,0x0f,0x00); can_tx3(sys_data.group_id,sys_data.sensor_id,0x00); for(i=0;i<5000;i++); can_tx3(sys_data.group_id,sys_data.sensor_id,0x00); for(i=0;i<5000;i++); can_tx3(sys_data.group_id,sys_data.sensor_id,0x00); for(i=0;i<5000;i++); } break; defalut: state=0;break; } } } void f_50Hz_io_init(void) { //IO PA11 GPIO_InitTypeDef GPIO_InitStructure; //PA0 init //port a // GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能外设时钟 //RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE); // 使能PB端口时钟 GPIO_InitStructure.GPIO_Pin =GPIO_Pin_11;// GPIO_Pin_4| GPIO_Pin_5 |GPIO_Pin_6| GPIO_Pin_7; // GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // #ifdef LAMP_MODE // GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // #else // GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // #endif GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA端口 GPIO_ResetBits(GPIOA, GPIO_Pin_11); // 关闭所有LED __nop(); GPIO_SetBits(GPIOA, GPIO_Pin_11); // 关闭所有LED __nop(); } ///////////////////////////////////////////////// void group_io_init(void) { //PB6 PB7 PA12 PC13 GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//使能外设时钟 GPIO_InitStructure.GPIO_Pin =GPIO_Pin_6| GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PA端口 //GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能外设时钟 GPIO_InitStructure.GPIO_Pin =GPIO_Pin_12; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA端口 //GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);//使能外设时钟 GPIO_InitStructure.GPIO_Pin =GPIO_Pin_13; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA端口 } void group_io_read(void) { //PB6 PB7 PA12 PC13 // sys_data.group_id=0; unsigned char temp=0; if(Bit_RESET == GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_6)) { //SYS_ID|=(1<<0); //sys_data.sensor_state=1; temp|=(1<<1); __nop(); } if(Bit_RESET == GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_7)) { //SYS_ID|=(1<<0); //sys_data.sensor_state=1; temp|=(1<<0); __nop(); } if(Bit_RESET == GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_12)) { //SYS_ID|=(1<<0); //sys_data.sensor_state=1; temp|=(1<<2); __nop(); } if(Bit_RESET == GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_13)) { //SYS_ID|=(1<<0); //sys_data.sensor_state=1; temp|=(1<<3); __nop(); } if(Bit_RESET == GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_12)) { //SYS_ID|=(1<<0); //sys_data.sensor_state=1; temp|=(1<<4); __nop(); } if(Bit_RESET == GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13)) { //SYS_ID|=(1<<0); //sys_data.sensor_state=1; temp|=(1<<5); __nop(); } sys_data.group_id=temp; __nop(); } // } ///////////////////////////////////////////////// void sensor_id_io_init(void) { //PB1 PB5 //PA4 PA5 PA6 PA7 //port b GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE); // 使能PB端口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1| GPIO_Pin_5; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PB端口 // GPIO_ResetBits(GPIOB, GPIO_Pin_1 | GPIO_Pin_5); // 关闭所有LED // __nop(); // GPIO_SetBits(GPIOB, GPIO_Pin_1 | GPIO_Pin_5); // 关闭所有LED // __nop(); // //port a RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能外设时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4| GPIO_Pin_5 |GPIO_Pin_6| GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA端口 // GPIO_ResetBits(GPIOA, GPIO_Pin_4| GPIO_Pin_5 |GPIO_Pin_6| GPIO_Pin_7); // 关闭所有LED // __nop(); // GPIO_SetBits(GPIOA, GPIO_Pin_4| GPIO_Pin_5 |GPIO_Pin_6| GPIO_Pin_7); // 关闭所有LED // __nop(); } void sensor_id_read(void) { //unsigned char sensor_id; //PB1 PA4 PA5 PA7 PA6 PB5 unsigned char temp=0; //bit0 if(Bit_RESET == GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1)) { //SYS_ID|=(1<<0); //sys_data.sensor_state=1; temp|=(1<<0); __nop(); } //bit1 if(Bit_RESET == GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_4)) { //SYS_ID|=(1<<0); //sys_data.sensor_state=1; temp|=(1<<1); __nop(); } //bit2 if(Bit_RESET == GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_5)) { //SYS_ID|=(1<<0); //sys_data.sensor_state=1; temp|=(1<<2); __nop(); } //bit3 if(Bit_RESET == GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_7)) { //SYS_ID|=(1<<0); //sys_data.sensor_state=1; temp|=(1<<3); __nop(); } //bit4 if(Bit_RESET == GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6)) { //SYS_ID|=(1<<0); //sys_data.sensor_state=1; temp|=(1<<4); __nop(); } //bit5 if(Bit_RESET == GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_5)) { //SYS_ID|=(1<<0); //sys_data.sensor_state=1; temp|=(1<<5); __nop(); } // if(temp>47) // {temp=47;} sys_data.sensor_id=temp; __nop(); } ///////////////////////////////////////////////// extern unsigned int cnt_1ms;//=0; extern unsigned char flag_20s;//=FALSE; extern void can_heart(u8 Data1,u8 Data2,u8 Data3); extern void can_boot(u8 Data1,u8 Data2,u8 Data3); int cnt_id=0; int main(void) { int i; SystemInit(); //配置系统时钟为 72M NVIC_Configuration(); //中断优先级设置 USART_Configuration(); //串口配置 RS_485_RX_EN; //RS485接收使能 LED_GPIO_Config();/* led 端口配置 */ TIM2_NVIC_Configuration(); /* TIM2 定时配置 */ TIM2_Configuration(); START_TIME; /* TIM2 开始计时 */ //buff_send_init(); buff_send_init_100(); main_can(); //LED_test(); lamp_id_io_init(); sensor_io_init(); f_50Hz_io_init(); group_io_init(); sensor_id_io_init(); for(i=0;i<3;i++) { group_io_read(); sensor_id_read(); can_boot(sys_data.group_id,sys_data.sensor_id,0xff); } //uart_class_test(); UartRx_Create(&uart1); /* 相当于“构造对象” */ while (1) { // if(flag_20s==TRUE) // { // flag_20s=FALSE; // main_can(); // } buff_send_init_200(); if(RS485_REC_Flag == 1)//判断是否接收到了数据 { RS485_REC_Flag = 0;//清除接收标志 RS485_Send_Data(RS485_buff,RS485_rec_counter); //将接收到的数据发送出去 RS485_rec_counter = 0; //接收计数器清零 RS485_Send_Data(buff_send,7); //将接收到的数据发送出去 GPIO_WriteBit(GPIOB, GPIO_Pin_15, (BitAction)((1-GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_15)))); /* LED1 取反 */ } modbus_echo(); // GetKey(); sensor_state_read(); group_io_read(); sensor_id_read(); if (uart1.complete == TRUE) { // printf("收到一帧: %s\n", uart1.getString(&uart1)); uart1.reset(&uart1); } // if(cnt_1ms>100) // { // cnt_1ms=0; // can_tx3(sys_data.group_id,sys_data.sensor_id,0); // } // if ( time >500 ) /* 500ms 时间到 */ { time = 0; // sensor_read_again(); //can_heart(sys_data.group_id,sys_data.sensor_id,0xff); GPIO_WriteBit(GPIOB, GPIO_Pin_15, (BitAction)((1-GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_15)))); /* LED1 取反 */ RS485_Send_Data(buff_send,7); //将接收到的数据发送出去 cnt_id++; if(cnt_id>10) { cnt_id=0; can_tx3(sys_data.group_id,sys_data.sensor_id,0); } } } }51单片机电力载波应用开发(六)数据链
张小明
前端开发工程师
Nuclei 实战入门:从 YAML 模板到同类型漏洞的批量排查
一、工具定位:为什么是 Nuclei?它是一款基于 YAML 语法模板的定制化快速漏洞扫描器,用 Go 语言开发,核心优势在于可配置、可扩展、易用。简单来说,它的价值在于把“某处漏洞的验证逻辑”变成了一个可以共享、复用、批量…
STM32解析GPS模块NMEA0183数据:从串口字节流到经纬度转换完整指南
拿到STM32和GPS模块,第一件事就是接上串口看输出。如果你用USB转TTL直接接GPS模块,打开串口助手,会看到一行行以$开头的字符串,比如$GPRMC,083559.00,A,3958.7888,N,11625.5624,E,0.047,66.05,080724,,,D*68。很多人到这一步就开始…
AI编程工作流实战:从提示词到代码生成、调试与测试的完整落地
最近后台私信里频率最高的一个问题,就是“AI 编程到底怎么落地”。大家普遍的感觉是:让大模型写个简单函数挺快的,但一放到真实项目里就变味了——要么上下文太长,要么生成的代码风格和项目完全对不上,要么改三遍还带着…
小样本医学图像分割实战:U-Net+SVM纹理后处理方案
简介:本资源为第七届泰迪杯数据挖掘挑战赛B题「直肠癌肿瘤分割」的完整参赛方案包,面向高校医学影像AI方向的学生团队与初阶算法实践者,聚焦医学图像语义分割任务中的数据预处理、模型训练与结果可视化全流程。压缩包共24个文件,含…
AI编程工作流实战:三段式起稿、遗留代码改造与批量生成
1. 为什么“能立刻复用”比“功能强大”更重要我见过太多人收藏了几百个AI编程工具,从代码补全到全自动Agent,硬盘里塞满了各种配置文件,结果日常写代码时还是一个Tab一个Tab地敲。问题不在于工具不好,而在于那些工作流要么配置太…
Superpowers:让AI编程从“快而不稳”到“可靠可控”的实践指南
Superpowers这个词,在AI编程圈里现在越来越常被提起。我第一次看到这名字,以为又是一个主打生成速度的工具,真正用下来才发现,它瞄准的根本不是“快”的问题,而是“快完之后代码能不能用”的问题。AI编程提示词写得再花…