问题描述

使用正点原子STM32F103的开发板例程,电脑端使用来自Microsoft store的“串口调试助手”应用,发现电脑可以正常收到开发板的来信,但是向开发板发送时没有收到应有的回应。

代码分析

main()函数中的主循环:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  while(1)
{

if(USART_RX_STA&0x8000)
{
len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
printf("\r\nreceived:\r\n");
HAL_UART_Transmit(&UART1_Handler,(uint8_t*)USART_RX_BUF,len,1000); //发送接收到的数据
while(__HAL_UART_GET_FLAG(&UART1_Handler,UART_FLAG_TC)!=SET); //等待发送结束
printf("\r\n\r\n");//插入换行
USART_RX_STA=0;
}else
{
times++;
if(times%500==0)
{
printf("\r\nUSART COM TEST\r\n");
}
if(times%30==0)LED0=!LED0;//闪烁LED,提示系统正在运行.
delay_ms(10);
}
}

这里我们可以看到,判断接收是否完成的标志是USART_RX_STA&0x8000,而这个USART_RX_STA又是从哪来的呢?使用F12跳转,可以寻找到usart.c中:

1
2
3
4
5
6
7
8
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误
u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15, 接收完成标志
//bit14, 接收到0x0d
//bit13~0, 接收到的有效字节数目
u16 USART_RX_STA=0; //接收状态标记

也就是谁这是一个2byte的变量,我们找到对这个变量值做出了修改的函数(也就是USART1的接收回调函数):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance==USART1)//如果是串口1
{
if((USART_RX_STA&0x8000)==0)//接收未完成
{
if(USART_RX_STA&0x4000)//接收到了0x0d
{
if(aRxBuffer[0]!=0x0a)USART_RX_STA=0;//接收错误,重新开始
else USART_RX_STA|=0x8000; //接收完成了
}
else //还没收到0X0D
{
if(aRxBuffer[0]==0x0d || aRxBuffer[0]=='.')USART_RX_STA|=0x4000;
else
{
USART_RX_BUF[USART_RX_STA&0X3FFF]=aRxBuffer[0] ;
USART_RX_STA++;
if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收
}
}
}

}
}

简单理一下这个代码的逻辑,其实是以有没有收到0x0D这个byte作为判断依据的。根据ASCII表可以查到,0x0D对应的是控制字符CR

这时候就豁然开朗了:回到串口调试软件,给发送的信息最后加上一个换行符号,问题就解决了。