本文共 1507 字,大约阅读时间需要 5 分钟。
在USART的发送端有2个寄存器,一个是程序可以看到的USART_DR寄存器,另一个是程序看不到的移位寄存器,对应USART数据发送有两个标志,一个是TXE=发送数据寄存器空,另一个是TC=发送结束。
XE--写寄存器DR清零
RXNE--读寄存器DR清零,也可软件手动清零
TC-- 读/写寄存器DR清零,也可软件手动清零
先说TC。即Transmission Complete。发送一个字节后才进入中断,这里称为“发送后中断”。
再说判断TXE。即Tx DR Empty,发送寄存器空。当使能TXEIE后,只要Tx DR空了,就会产生中断,所以,发送完字符串后必须关掉,否则会导致重复进入中断。
我的失败经历是在串口初始化是 USART_ITConfig(USART1, USART_IT_TXE, ENABLE);结果在串口中断中没有关闭txe,所以你上电后什么也不做,系统就会一直进中断,也就是发送为空,但是也进中断。所以串口初始化函数中就不用打开TXE的中断了。
1,用串口连续发送一串数字时, 第一个数总是发不出去
这个问题的根本原因是复位后,TC和TXE标志位默认都是1,很多人喜欢这样写:
USART_SendData(USART1, (u8) ch); while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) while在发送第一个字节时没有起到应有作用,直接跳出,接着写第二个字节,这时第一个字节还未发出,数据被破坏了.看看datasheet,果然复位以后, SR=0x00c0;TC=TXE=1;
有人是在串口中断处理函数void USARTx_IRQHandler(void)最后加上下面的来解决第一个字节发布出去的问题。
if(USART_GetITStatus(USART2, USART_IT_TXE) != RESET) /
{ USART_ITConfig(USART2, USART_IT_TXE, DISABLE); }
其中TC判断的是一帧数据,而TXE是当TDR数据传到移位寄存器就被置位了,所以TC的时间比较长,很容易被下一次数据覆盖~~~所以一般喜欢判断TXE,数据写到DR就可以了 ,剩下的工作就交给硬件了,一般的用TXE就可以了, TC一般用于需要延时的场合,比如说是232/485转换器,需要得到TC后,才能将发送改变成接收,否则 最后一个字节发送不完全。
2.其实可以不用TC,也不用初始化使能USART_ITConfig(USART1, USART_IT_TXE, ENABLE);发送函数这样写:发送函数可以这样写
void USART_OUT(USART_TypeDef* USARTx, uint8_t *Data,uint16_t Len)
{ uint16_t i; for(i=0; i<Len; i++) { USART_SendData(USARTx, Data[i]); //while(tx_flag==0) //{} //tx_flag=0; while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE)==RESET); //判断是否发送完成。 USART_FLAG_TC } } 中断处理函数这样写:void USARTx_IRQHandler(void) { if(USART_GetITStatus(USARTx, USART_IT_RXNE) != RESET) { uartx_recv(); //接受处理函数 }
}
转载地址:http://uursi.baihongyu.com/