Pic16F15313与ESP8266通信:发送AT指令仅返回错误响应求助
ESP8266 AT指令返回ERROR故障排查与解决
问题描述
向ESP8266发送简单AT指令时,仅能收到ERROR响应(表现为LED闪烁两次)。已确认:
- 波特率按文档设置为115200
- 采用3.3V供电
- Rx与Tx连接正确(能收到响应)
相关代码如下:
时钟设置
// CONFIG1 #pragma config FEXTOSC = OFF // 外部振荡器模式选择位(未启用振荡器) #pragma config RSTOSC = HFINT32 // COSC位上电默认值(HFINTOSC,OSCFRQ=32MHz,CDIV=1:1) #include <xc.h> #include <stdio.h> #include <string.h> #define RX_BUFFER_SIZE 100 volatile char connection_successful = 0; volatile char rx_buffer[RX_BUFFER_SIZE]; volatile int rx_index = 0; #define _XTAL_FREQ 32000000
I/O与波特率设置
void setup(void){ //I/O配置 TRISAbits.TRISA0 = 0; //A0 输出 TRISAbits.TRISA1 = 1; //A1 输入 TRISAbits.TRISA2 = 0; //A2 输出 TRISAbits.TRISA4 = 1; //A4 输入 TRISAbits.TRISA5 = 0; //A5 输出 //A3 仅为输入 WPUAbits.WPUA0 = 0; // 弱上拉禁用 WPUAbits.WPUA1 = 0; // 弱上拉禁用 RX1DTPPS = 0x1; //RA1->EUSART1:RX1; RA0PPS = 0x0F; //RA0->EUSART1:TX1; //ABDEN 禁用; WUE 禁用; BRG16 16位发生器; SCKP 非反转; BAUD1CON = 0x48; //ADDEN 禁用; CREN 启用; SREN 禁用; RX9 8位; SPEN 启用; RC1STA = 0x90; //TX9D 0x0; BRGH 高速; SENDB 同步中断完成; SYNC 异步; TXEN 启用; TX9 8位; CSRC 客户端; TX1STA = 0x26; //SPBRGL SP1BRGL = 0x44; //SPBRGH SP1BRGH = 0x00; }
启用UART
RC1STAbits.SPEN = 1; TX1STAbits.TXEN = 1; RC1STAbits.CREN = 1;
向ESP8266发送数据
void UART_Write(char data) { while (!TX1STAbits.TRMT); // 等待发送缓冲区为空 TXREG = data; } void UART_Write_String(const char *str) { while (*str) { UART_Write(*str++); } }
读取ESP8266响应
void ReadUART(void) { if (PIR3bits.RC1IF) { rx_buffer[rx_index++] = RC1REG; if (rx_index >= RX_BUFFER_SIZE - 1) { rx_index = 0; // 重置缓冲区索引 } PIR3bits.RC1IF = 0; // 清除RX中断标志 } }
根据响应闪烁LED
void report(void){ if (rx_index > 0) { if (strcmp(rx_buffer, "OK") == 0) { flash_code_1(); }else if(strcmp(rx_buffer, "ERROR")){ flash_code_2(); }else{ // 闪烁4次表示未知响应 flash_code_4(); } rx_index = 0; }else{ // 闪烁5次表示无响应 flash_code_5(); UART_Write_String("AT\r\n"); rx_index = 0; } }
主程序代码
void main(void) { setup(); __delay_ms(5000); UART_Write_String("AT\r\n"); __delay_ms(5000); while(1){ ReadUART(); report(); __delay_ms(5000); } return; }
故障原因分析与解决方法
1. 响应判断逻辑错误
- 问题点:
report函数中else if(strcmp(rx_buffer, "ERROR"))的条件判断错误。strcmp返回0时表示字符串相等,当前写法只要返回非0(即不是"OK"也不是"ERROR"的情况)就会触发flash_code_2,导致误判。 - 解决方法:修正条件判断,改为:
else if(strcmp(rx_buffer, "ERROR") == 0)
2. 接收缓冲区未添加字符串终止符
- 问题点:
rx_buffer是字符数组,但接收数据时未添加'\0'字符串终止符,strcmp会读取缓冲区后的随机内存内容,导致比较结果错误。 - 解决方法:
- 方式一:在
report函数判断响应前添加终止符:rx_buffer[rx_index] = '\0'; - 方式二:在
ReadUART中检测响应结束符(如'\n'),收到后立即添加终止符:void ReadUART(void) { if (PIR3bits.RC1IF) { char received = RC1REG; rx_buffer[rx_index++] = received; if (received == '\n' || rx_index >= RX_BUFFER_SIZE - 1) { rx_buffer[rx_index] = '\0'; rx_index = 0; } PIR3bits.RC1IF = 0; } }
- 方式一:在
3. 轮询接收导致数据丢失或不完整
- 问题点:主循环中每5秒才调用一次
ReadUART,ESP8266的响应可能在__delay_ms(5000)期间到来,导致接收标志位被置位但未及时处理,部分数据丢失,造成响应字符串不完整。 - 解决方法:
- 改用UART中断接收:配置RC1中断,在中断服务函数中处理字节接收,确保所有响应字节都被捕获。
- 缩短主循环延迟时间,增加
ReadUART调用频率,例如将__delay_ms(5000)改为__delay_ms(10),同时调整report的触发逻辑(仅收到结束符时判断响应)。
4. 波特率误差导致通信异常
- 问题点:当前配置的波特率计算值为≈115942bps,与目标115200bps存在约0.6%的误差,部分ESP8266模块对波特率误差敏感,导致通信异常。
- 解决方法:
- 微调SPBRG值:将
SP1BRGL改为0x45(69),重新计算波特率为≈114492bps,误差缩小至-0.6%。 - 先切换到9600bps测试:计算对应SPBRG值为
(32000000/(4*9600))-1≈832,即SP1BRGL=0x20,SP1BRGH=0x03,确认通信正常后再改回115200bps。
- 微调SPBRG值:将
5. 响应字符串匹配不精准
- 问题点:ESP8266返回的ERROR响应实际为
ERROR\r\n,当前代码仅匹配"ERROR",导致strcmp不相等,进而触发错误判断。 - 解决方法:修改匹配逻辑,检查缓冲区中是否包含"ERROR"子串:
else if(strstr(rx_buffer, "ERROR") != NULL)
内容的提问来源于stack exchange,提问作者234Mike432
相关产品推荐
相关产品推荐

