前言:使用小华的HC32F460型号芯片(下文简称小华)与德州的280025单片机(下文简称德州)做串口通信时遇到了奇怪的bug。
问题概述:当小华与PC(windows)电脑进行串口通信时能够正常通讯收发消息,德州与PC串口通信同样正常工作。而后尝试将小华与德州的串口连接做通信时,发现小华能够收到德州TX发送的消息,但是德州的RX收不到小华TX发送的消息,德州的RX中断始终无法进入。
问题排查:
1、使用示波器测试小华串口通信时TX的波形,发现其默认状态处于低电平,进行通讯时拉高和拉低电平产生方波,结束通信时从高电平缓慢下降。正常状态下的串口通讯应当默认处于高电平,通讯结束后快速恢复高电平。由此判断小华的串口存在异常。
2、使用万用表测量电压,发现小华的RX和TX默认状态都处于低电平,而德州的TX默认高电平,RX默认低电平,PC设备的RX和TX则都处于高电平。
现象分析:
标准的串口协议RX和TX应当处于默认高电平的状态,由我们刚才测得的电平情况可以判断,小华和德州都能分别和PC都通信是因为PC的RX和TX都处于高电平,无论通讯另一方的电平高低,都能将其拉高。
而当小华和德州进行通信时,德州的TX默认高电平能将小华的RX拉高,从而小华能接收德州发送的消息,但是小华的TX和德州的RX都是默认低电平,小华发送消息时两者的电平无法拉高,因此德州无法接收到小华发送的消息。
代码排查:
最终排查小华的例子代码发现其设计模式如下:
默认状态下仅开启RX中断
USART_FuncCmd(USART_UNIT, (USART_RX | USART_INT_RX), ENABLE);
当需要发送数据时开启TX中断和TX寄存器空中断
USART_FuncCmd(USART_UNIT, (USART_TX | USART_INT_TX_EMPTY), ENABLE);
当数据发送完成后开启数据传输完成中断
USART_FuncCmd(USART_UNIT, USART_INT_TX_CPLT, ENABLE);
数据传输完成后关闭TX相关中断
USART_FuncCmd(USART_UNIT, (USART_TX | USART_INT_TX_CPLT | USART_INT_TX_EMPTY), DISABLE);
这样的设计导致了TX在不发送消息的时候是不运行的,因此默认处于低电平。
修改方案
通过上述的测试研究,我们可以判断只需要让小华的RX和TX默认处于高电平,即可使其和德州正常通信。由此我们只需要默认开启小华的TX中断,并将小华的TX数据发送方式从原来的中断发送改成轮询延迟发送即可。
USART_FuncCmd(USART_UNIT, (USART_RX | USART_INT_RX | USART_TX), ENABLE);
void Uart1SendAT(char *p, int pLen)
{
unsigned char *pU8 = (unsigned char*)p;
for(int i=0; i<pLen; i++)
{
USART_WriteData(USART_UNIT, (uint16_t)pU8[i]);
DDL_DelayUS(100);
}
}