STM32库函数USART_SendData问题和解决方法
1. 问题及现象
使用USART_SendData()函数非连续发送单个字符是没有问题的;当连续发送字符时(两个字符间没有延时),就会发现发送缓冲区有溢出现象。若发送的数据量很小时,此时串口发送的只是最后一个字符,当发送数据量大时,就会导致发送的数据莫名其妙的丢失。
如:
1 2 | for(TxCounter = 0;TxCounter < RxCounter; TxCounter++) USART_SendData(USART1, RxBuffer[TxCounter]); |
2. 原因
此API函数不完善,函数体内部没有一个判断一个字符是否发送完毕的语句,而是把数据直接放入发送缓冲区,当连续发送数据时,由于发送移位寄存器的速度限制(与通信波特率有关),导致发送缓冲区的数据溢出,老的数据还未及时发送出去,新的数据又把发送缓冲区的老数据覆盖了。
3. 解决方法
发送后等待一段时间延迟的方法就不说了,等待时间不确定,此为下下策。提供下面2种方案:
方案1. 在每一个字符发送后检测状态位
USART_SendData(USART1, RxBuffer[TxCounter]);
while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET){} //等待发送缓冲区空才能发送下一个字符
方案2. 修改库函数
修改USART_SendData()函数,在其内部加入发送缓冲区的USART_FLAG_TXE状态检测语句,确保一个字符完全发送出去,才进行下一个字符的发送。
实现方法:每发送一个字符都检测状态寄存器,确保数据已经发送完毕。具体操作步骤如下所示。
修改前的函数定义体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | void USART_SendData(USART_TypeDef* USARTx, u16 Data) { assert_param(IS_USART_ALL_PERIPH(USARTx)); assert_param(IS_USART_DATA(Data)); USARTx->DR = (Data & (u16)0x01FF); } |
修改后的函数定义体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | void USART_SendData(USART_TypeDef* USARTx, u16 Data) { assert_param(IS_USART_ALL_PERIPH(USARTx)); assert_param(IS_USART_DATA(Data)); USARTx->DR = (Data & (u16)0x01FF); while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET){} //等待发送缓冲区空才能发送下一个字符 } |
可能有人认为,为什么不预先在库函数中处理这个问题,而把解决方法抛给用户。个人认为ST这么做的原因是:使用发送中断功能。
STM32库函数USART_SendData问题和解决方法 | 小谢的小站 http://blog.xieyc.com/stm32-lib-function-usart-send-data-problem-and-solution/
STM32库函 相关文章:
- STM32库函数配置(12-02)
- STM32库函数void USART_SendData()的缺陷和解决方法(11-28)
- STM32库函数之断言(11-26)
- STM32 V3.4库函数使用建立工程方法(11-25)
- STM32 基于库函数控制按键 蜂鸣器 LED显示(11-25)
- STM32库函数EXTI_GetFlagStatus和EXTI_GetIT(11-24)