关于串口USART一些知识

**

中断

中断有中断标志位和中断使能位,当开启对应的中断使能时,若其中断标志位置1,则会进入对应的中断服务函数,需要注意的是标志位是否自动清0。
**
TC:发送完成标志位
RXNE:读数据寄存器非空 /接收数据寄存器非空
TXE:发送数据寄存器空标志位

TXEIE:发送缓冲区空中断使能 (TXE interrupt enable)
TCIE:发送完成中断使能 (Transmission complete interrupt enable)

USART_IT_TC:传输完成中断
USART_IT_TXE:DR移空后产生中断

中断标志:
在这里插入图片描述
中断使能:
在这里插入图片描述
USART中断服务函数:
在这里插入图片描述
在这里插入图片描述
正点原子的这个循环里面的代码并没有将TC标志置0,然后又进入下一次USART1->DR=USART_RX_BUF[t],虽然实验现象达到了,但是感觉以后用在较复杂的地方这种操作容易出问题的,参考了下面的资料:
USART_IT_TC,USART_IT_TXE中断标志位的区别

STM32的串口函数_库函数USART_SendData问题和解决方法–硬件复位导致第一个字节丢失

stm32串口通信的一个小总结(从底层进行理解)

实践环节:

**
发送数据的几种方式:
1)没有利用中断,两句就行,当DR为空就往里面写,不考虑TC标志置位与否。
在这里插入图片描述
在这里插入图片描述

这样理解:
1、USART1->DR=DateByte[t];,就是把数据发送到DR,然后DR会自动将数据传给移位寄存器,不用cpu参与
2、cpu直接进入下一句代码while((USART1->SR&0X80)==0);//等待发送结束,这个过程是:执行到这的时候,可能DR正在移,还未移空,一旦移空,则TXE置1,若使能了中断还会进入中断。
3、然后又进入下一个USART1->DR=DateByte[t];,因为上一次已经确定了DR为空,所以不会数据覆盖,而且标志位TXE会因这句“往DR写”的代码而自动清0 ,因为一写,则有数据,代表非空,即TXE为0.
4,因为等待的是DR为空,至于TC不管它置1与否,移位寄存器照样工作,不影响传输。
2)没有利用中断,想等每次发送完成(停止位发送完那刻),则写数据到DR
在这里插入图片描述
在这里插入图片描述
只用这两句会导致第一个数据丢失(第1次循环少了一个a,但是其他循环a为什么没少??),
1,猜测是因为初始化后,还没DR没有写入数据,移位寄存器也是空的,这就相当于发送完成的一种状态,TC被置1.所以第1个a,被s覆盖,过程是:USART1->DR=‘a’;然后本来想while((USART1->SR&0X40)==0);//TC,等待‘a’这个字符(8个位)发送结束,结果呢,因为初始化时,TC被置1.所以这句被执行完,跳到下一句USART1->DR=‘s’,没有起到等待的作用,当执行完USART1->DR=‘s’,准备下次等待,但是TC还是1,没被清0,为什么后面的字符能正常打印????
上面参考资料含下图的那篇文章也没说,,,,,,
在这里插入图片描述
2,猜测,既然后面的数据能正常,说明后面发送的字符TC被清0 过。
猜想原因1)由资料里被我画线的这句话,猜测,当停止位发送完,检测到当TXE为1,TC才能自动置1,即如果检测到TXE为0,TC还是0,也就是停止位发送完那刻,如果DR有数据,那TC就是0.
在这里插入图片描述
猜想原因2)还可能是AB的代码起到了读USART_SR的作用。先读USART_SR,然后写入USART_DR,能清零TC。
然后来理解一下,为什么只有第1个a被覆盖,其他正常?

3)
在2)的基础上,在for循环外部加一句
USART_ClearFlag(USART1,USART_FLAG_TC);清除TC
在这里插入图片描述
在这里插入图片描述
结果正常,没有丢失第一个a,其他数据也正常
4)
在2)的基础上,在while循环外部加一句,也就是最开始的时候就将TC清0;后面也不对其清0;
在这里插入图片描述
在这里插入图片描述
结果还是正常,和4)一样。
5)
把4)while循环外部的USART_ClearFlag(USART1,USART_FLAG_TC);换成USART_GetITStatus(USART1,USART_FLAG_TC);//读SR寄存器
在这里插入图片描述
也能正常发送
在这里插入图片描述
6)
把5)while循环外部的USART_GetITStatus(USART1,USART_FLAG_TC);//读SR寄存器,分别放到for循环内部和or循环外部while循环内部
在这里插入图片描述
在这里插入图片描述
USART_GetITStatus第二个参数应该是USART_IT_TC ,即:USART_GetITStatus(USART1,USART_IT_TC);
结果都还是正常。进入函数内部,发现“读SR寄存器”的语句
在这里插入图片描述
还有一个“错误”是函数都调错了。。。。
本来想调用:
USART_GetFlagStatus(USART1,USART_FLAG_TC);
其实也是对的,因为它也有“读SR寄存器”的语句
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
汇总分析:
实验1)逻辑没毛病,结果也如意。
实验2)有点不明白为什么后续的可以正常发送,
实验3)每发送完一个字符串,清0一次TC,这样每串的第一个字符不会被覆盖
实验4)只在主函数中清0一次TC,结果第一个也不覆盖
实验5)把清0一次TC换成读USART_SR,也正常,第一个也不覆盖
实验6)的两种测试方法本质一致,清零TC的第一种方式,即都是读SR,再写数据到DR,前面是每发一个字符清0一次TC,后面是发送完一个字符串清0一次TC,
得出结论是:
只是第一个字符会被覆盖,后续发的字符不会被覆盖,解决第一个字符会被覆盖的问题就好,不纠结那么多,
以上给自己挖了个坑,,还是不用管好,记者while等待的是哪个条件,是TC就要注意清0,,

补充:
串口传输过程与TXE标志位、TC标志位、TXEIE使能标志位、TCIE使能标志位的关系:
1、当初始化usart后,还没进行任何传输,TXE标志位和TC标志位为0,如果使能了发送完成中断TCIE和发送缓冲区空中断TXEIE,TXEIE使能标志位和TCIE使能标志位就为1。当想通过串口发送数据时,将数据写入TDR寄存器(如下图):
在这里插入图片描述
2、USART1->DR=一个字节大小的数据;,然后TDR寄存器将数据传送到移位寄存器,传输完成后,TDR寄存器就空了(发送缓冲区空),TXE被设置1,如果使能了TXEIE(初始化的时候TXEIE被设置为1),则会产生中断,进入 中断服务函数USARTx_IRQHandler,在中断服务函数里面再判断是不是这个TXEIE产生的中断:
if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET),如果没有使能TXEIE,则不会触发中断,不会进入中断服务函数。
3、此时移位寄存器开始向TX信号线按位传输数据,如果传输完成,又使能了TCIE标志位,则产生中断,也会进入中断服务函数USARTx_IRQHandler,
4、 然后也是在里面判断是否是传输完成中断if(USART_GetITStatus(USART_IT_TC),再进行一下操作,
5、 操作完,最后要清除TXE标志位、TC标志位,如果不清除,可能下次传输,会误认为DR寄存器为空或已经传输完成,只有当DR真的为空的时候,向其发送数据,才不会出错,否则会使得前面的数据被后面覆盖。
总结:
发送缓冲区空时TXE被置1和发送发送完成TC被置1,会不会中断还得看有没有开启中断,如果开启了中断,TXE、TC还是0,那也不产生中断。

对SR操作的函数:

     1. USART_ClearITPendingBit(USART2, USART_IT_TC)  //清除待处理的发送完成中断标志位
     2. USART_ClearFlag(USART3,USART_FLAG_TC);      //清除发送完成标志位
     3. USART_ClearITPendingBit(USART2, USART_IT_RXNE) //清除待处理的接收完成中断标志位
     4. USART_ClearFlag(USART3,USART_FLAG_ RXNE);    //清除接收完成标志位

注意:1和2 , 3和4的作用完全一样;只是名称不同,在不同场合中应用更加明确。
应该这样:
在这里插入图片描述
**

**
在这里插入图片描述
利用中断的方式

空闲中断

**
STM32串口之空闲中断

  • 9
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值