Preface
最近在搞基于esp8266的服务器框架,发现在进行串口通信的时候出现了丢失第一个字符的现象,最后发现,竟然是stm32自身的问题,特此记录一下。
解决办法
static void myprintf1(char *str)//这是串口发送函数
{
USART_ClearFlag(USART1, USART_FLAG_TC); //防止出现stm32第一个字符丢失的现象,添加这一句
while (*str)
{
USART1->DR = (u8)*str;
while ((USART1->SR & 0X40) == 0)
; //循环发送,直到发送完毕
str++;
}
}
问题本质
背景
我们都知道,从编程人员的角度,对外设的控制就是对外设寄存器进行读写。
外设的寄存器无非就三种:
- 数据寄存器
- 控制寄存器
- 状态寄存器
因此,要解决串口发送时丢失第一帧数据,那就是对这三类寄存器的监视。
而我们可以从上面的代码中可以看出,就是状态寄存器的问题。
寄存器
上图就是stm32的状态寄存器:
它这个是stm32参考手册给出的,那是它这个写错了,实际上是:
复位值:0x0000 00C0
还可以从这个地方可以看出来。
有的东西参考手册也是不对的。
如果你不相信,很简单,通过程序验证一下不久可以了。
答案
从上面那幅图我们可以看到,cpu上电复位后的TC状态标志位是1.
static void myprintf1(char *str)//这是串口发送函数
{
USART_ClearFlag(USART1, USART_FLAG_TC); //防止出现stm32第一个字符丢失的现象,添加这一句
while (*str)
{
USART1->DR = (u8)*str;
while ((USART1->SR & 0X40) == 0)
; //特别需要注意的是这个地方
str++;
}
}
我们再来看下我们的程序。
当我们向串口发送完第一字符,这个时候由于TC标志位为1,那么程序此时将会直接发送第二个字符,由于cpu的运行频率远大于外设的运行频率,因此上一次发送的数据将回被这一次发送的数据所覆盖。
因此,为了解决这个问题,在每次需要发送数据的时候,将串口状态寄存器的TC状态标志位给清零,这样就不会出现问题了。