在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(); //接受处理函数
}
}