使用PIC18F蓝牙模块时getcUSART函数工作异常求助
排查PIC18F4520 + C18下getcUSART导致程序挂起的问题
我来帮你解决这个USART接收挂起的问题——这种情况在PIC18搭配蓝牙模块开发时太常见了,咱们先从你的代码和硬件配置两方面拆解:
首先看你提供的代码片段:
int input(char Arr[]) { Delay10KTCYx(400); // Delay between data transmissions while(BusyUSART()); // wait for user input while (!DataRdyUSART()); //get string from terminal Arr[0] = getcUSART(); //read a byte from USART Delay10KTCYx(400); // Delay between data transmissions while(BusyUSART()); // wait for user input while...
几个明显的问题点
- 无限等待
DataRdyUSART():如果蓝牙模块没发送数据、信号丢包或者USART配置错误,这个循环会一直卡住,直接导致程序挂起——没有任何退出机制是大忌。 - 误用
BusyUSART():这个函数是用来判断发送是否繁忙的(检查TXREG寄存器是否为空),在接收流程里调用它完全没用,纯属画蛇添足,赶紧删掉。 - 缺少超时机制:一旦蓝牙连接中断或者数据没传过来,你的程序会永远停在等待接收的循环里。
具体修复方案
1. 给接收循环添加超时逻辑
修改input函数,加入超时计数,避免无限挂起:
#define USART_TIMEOUT_COUNT 10000 // 根据你的系统时钟调整,比如8MHz下这个值大概对应几百ms int input(char Arr[]) { unsigned int timeout = 0; Delay10KTCYx(400); // 这个延时如果是为了等待蓝牙模块准备,可以保留,但建议用定时器更精准 // 等待接收数据,带超时 while(!DataRdyUSART()) { timeout++; if(timeout > USART_TIMEOUT_COUNT) { return -1; // 超时返回错误码,上层可以处理这种情况 } } Arr[0] = getcUSART(); // 读取接收到的字节 // 后续如果还有接收逻辑,同样要加超时 // ... return 0; // 接收成功返回0 }
2. 检查USART初始化是否正确
确保你的USART配置和蓝牙模块完全匹配(比如蓝牙常用9600波特率、8位数据位、1位停止位、无校验),而且必须开启连续接收:
void initUSART(void) { TRISCbits.TRISC7 = 1; // RC7是USART RX引脚,设为输入 TRISCbits.TRISC6 = 0; // RC6是USART TX引脚,设为输出 // 波特率配置:8MHz时钟下,9600波特率(高速模式) TXSTAbits.BRGH = 1; SPBRG = 0x19; RCSTAbits.SPEN = 1; // 启用USART TXSTAbits.TXEN = 1; // 启用发送 RCSTAbits.CREN = 1; // 启用连续接收(关键!不开启的话收不到数据) // 清除接收溢出标志(如果有的话) if(RCSTAbits.OERR) { RCSTAbits.CREN = 0; RCSTAbits.CREN = 1; } }
3. 硬件排查
- 确认蓝牙模块的接线:蓝牙TX接PIC RX,蓝牙RX接PIC TX(交叉接线,别接反了)。
- 检查蓝牙模块电源:确保供电稳定(一般3.3V,部分模块支持5V,但要注意电平兼容)。
- 观察蓝牙模块指示灯:正常配对后指示灯应该是慢闪,发送数据时快闪,以此判断模块是否正常工作。
调试技巧
如果还是有问题,用逻辑分析仪或者示波器测PIC的RX引脚:
- 如果能看到蓝牙发来的电平信号(比如9600波特率下每个bit大概104us),说明硬件没问题,问题出在USART配置或者代码逻辑。
- 如果看不到信号,先排查蓝牙模块是否正常发送、接线是否松动。
内容的提问来源于stack exchange,提问作者Briget
相关产品推荐
相关产品推荐

