问题和现象
在GD32单片机中,首先进行初始化串口1,使能接收中断,然后进入while死循环进行,循环中只有看门狗喂狗操作。在串口1接收中断中增加打印语句,打印串口接收到的数据。
上位机发送5个字节,串口只进入了两次中断(只接受了两个字节)。一开始总觉得是串口初始化配置有问题,检查和修改了几遍,结果还是一样,串口无法完整接收5个字节的数据。
分析和解决
网上查找资料发现,说是串口溢出这里可能会影响接收,继续检查中断代码。原有的中断代码中有一个ORERR标志位的判断被注释掉了。查阅GD32芯片手册介绍,ORERR标志位是用于溢出错误的,打开ORERR标志位判断代码,在判断中加入打印语句。再次验证后,发现接收一个字节的数据后就进入了溢出错误标志判断,第二个字节也是如此。
考虑有没有可能是串口接收溢出错误了导致只接受两个字节的??GD32芯片手册表示,ORERR标志位需要软件清0,手册中表面需要先清零SR,再清零DR寄存器。
usart_data_receive(UART1); //内部实现中只读取了DR寄存器
但是上面这个函数中只是读取了DR寄存器(内部实现是返回该串口的DR寄存器值),没有把该溢出错误标志位清楚成功。 溢出错误后,没有成功清零导致后续无法正常接收。
修改后:
(GET_BITS(USART_STAT0(UART1), 0U, 8U)); //先读取SR
(GET_BITS(USART_DATA(UART1), 0U, 8U)); //再读取DR
我这里调用的函数值的0U,8U参数表示读取0~8位,DR和SR寄存器都是32位的。实际上只需要读一下SR和DR的寄存器地址的数据,该位就可以清零。这里8U不影响,运行后,能够成功接收完上位机发送的5个字节。