OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 6728|回复: 11

关于USART_FLAG_TC位的疑问

[复制链接]

94

主题

369

帖子

0

精华

高级会员

Rank: 4

积分
865
金钱
865
注册时间
2016-8-25
在线时间
485 小时
发表于 2016-8-28 16:52:08 | 显示全部楼层 |阅读模式
1金钱
大家好,在学习USART通信实验时,看到  
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);
于是就在中文参考手册中参考了TC的清零方法:
“该位由软件序列清零(读取 USART_SR 寄存器,然后写入USART_DR 寄存器)。TC 位也可以通过向该位写入‘0’来清零”
可见,可以采用先读SR,再写DR的方式清零;或直接向TC位写0.
现在有一个小小的疑问:
例如,USART_RX_BUF数组中有三个数据,123.
当t=0时,通过USART_SendData()发送第一个数据1;接着执行while语句,若没有发送完成,则while等待;若发送完成,此时,
USART_GetFlagStatus()返回SET,这时,TC位为1.
接着执行t=1,通过USART_SendData()发送第二个数据2;接着执行while语言,那么问题来了,t=0时的TC位是怎么清零的呢?

QQ截图20160828165146.jpg

最佳答案

查看完整内容[请看2#楼]

你自己不是说了嘛,写USART->DR会清零TC。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

6

主题

1097

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3571
金钱
3571
注册时间
2014-12-2
在线时间
365 小时
发表于 2016-8-28 16:52:09 | 显示全部楼层
你自己不是说了嘛,写USART->DR会清零TC。
回复

使用道具 举报

94

主题

369

帖子

0

精华

高级会员

Rank: 4

积分
865
金钱
865
注册时间
2016-8-25
在线时间
485 小时
 楼主| 发表于 2016-8-28 17:16:05 | 显示全部楼层
xkwy 发表于 2016-8-28 17:09
你自己不是说了嘛,写USART->DR会清零TC。

您好,我看到手册上说“先读SR,再写DR”,那么读SR发生在哪里呢?
回复

使用道具 举报

94

主题

369

帖子

0

精华

高级会员

Rank: 4

积分
865
金钱
865
注册时间
2016-8-25
在线时间
485 小时
 楼主| 发表于 2016-8-28 17:38:10 | 显示全部楼层
xkwy 发表于 2016-8-28 17:09
你自己不是说了嘛,写USART->DR会清零TC。

是这样的过程吗?
t=0,USART_SendData()函数写DR,再在while中判断TC,实际发生了读SR;
t=1,继续执行USART_SendData(),即写DR;这时,上一步骤的读SR与这一步骤的写DR恰好组合在一起构成了清零TC的条件。
回复

使用道具 举报

6

主题

1097

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3571
金钱
3571
注册时间
2014-12-2
在线时间
365 小时
发表于 2016-8-29 07:23:53 | 显示全部楼层
本帖最后由 xkwy 于 2016-8-29 07:26 编辑


首先,不读SR,直接写DR也会将SR[TC]清零。

如果按照你自己的解释,那么SR复位值是0x00C0,为什么单片机复位后第一字节发送之前并没有任何读SR,依然正常。

最后,如果你真有疑问,不妨做个小实验来验证一下(自己想)。这,要比我直接告诉你强一万倍。

再最后,我留意到手册里还有一句话不知道你看到没有:
1.png

This clearing sequence is recommended only for multibuffer communication.

最最后,对这种“小”问题(其实并不小)抱有热心非常值得肯定。
但学习,除了要提出问题,最好还要能解决问题。

坚决不用寄存器,拒绝重复造轮子。
回复

使用道具 举报

94

主题

369

帖子

0

精华

高级会员

Rank: 4

积分
865
金钱
865
注册时间
2016-8-25
在线时间
485 小时
 楼主| 发表于 2016-8-29 17:40:27 | 显示全部楼层
本帖最后由 学习stm32f4 于 2016-8-29 20:23 编辑
xkwy 发表于 2016-8-29 07:23
首先,不读SR,直接写DR也会将SR[TC]清零。

如果按照你自己的解释,那么SR复位值是0x00C0,为什么单片 ...

您好,非常感谢您的指点。
今天早上按照您的指点在原子哥的程序的基础上写了一个测试,花了一天的时间来理解程序的执行过程,此时终于明白了(但愿理解的是对的),您有空审读一下吗?
对于图1中while(1)内的运行过程是这样的:
当if条件满足后,运行到printf("\r\nThe massage:\r\n");时,由于USART_SR寄存器中的TC位在芯片初始化后为1,故在调用该printf时,导致写DR寄存器,这就导致TC位清零。
接着进入for语句,在第二个prinf语句中,先运行USART_GetFlagStatus函数,由于第一个printf函数导致的TC位为0,故在第二个printf函数中,USART_GetFlagStatus返回TC位的值0.即打印出0.
接着执行for语句中的第一个while,直到printf中写DR完成(由fputc实现),完成传输后,TC位置1.这时,运行完该while后,TC为1.
接着执行第三个printf,先执行USART_GetFlagStatus函数,该函数返回1,将1压入堆栈。printf调用参数时,从堆栈中调取1,打印到串口,即打印出1.但是,在打印出1时,由于执行了写DR,故打印完1后,TC位变为0.
接着执行第四个printf,由于此时TC位为0,故打印出0.
接着执行while,执行完while后,TC位为1.
接着执行USART_SendData函数,由于执行了写DR寄存器,故执行完该语句后,TC位为0.
接着执行第五个printf,显然,打印出0.
接着执行while,执行完while后,TC位变为1.
接着执行第六个printf,先调用USART_GetFlagStatus函数,该函数返回TC位的值1,将1压入堆栈,调用printf函数,从堆栈中取出1并打印出来。在调用该printf时,由于执行了写DR寄存器,故本句执行完毕后,TC值为0.
执行第七个printf,显然,打印出0.
例如,若用串口调试助手发送2,则返回如图2所示,返回值与上述分析相符。
1.JPG
2.JPG
回复

使用道具 举报

5

主题

277

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1522
金钱
1522
注册时间
2014-5-16
在线时间
217 小时
发表于 2016-8-29 18:19:29 | 显示全部楼层
学习stm32f4 发表于 2016-8-29 17:40
您好,非常感谢您的指点。
今天早上按照您的指点在原子哥的程序的基础上写了一个测试,花了一天的时间来 ...

建议你跟到USART_GetFlagStatus和USART_SendData这两个函数中去看一眼,GetFlagStatus()这个函数就是在读SR,SendData()这个函数就是在写DR,所以清除TC的序列就满足了,有那么费劲么.
回复

使用道具 举报

6

主题

1097

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3571
金钱
3571
注册时间
2014-12-2
在线时间
365 小时
发表于 2016-8-29 19:50:33 | 显示全部楼层
学习stm32f4 发表于 2016-8-29 17:40
您好,非常感谢您的指点。
今天早上按照您的指点在原子哥的程序的基础上写了一个测试,花了一天的时间来 ...

自己给自己找麻烦,看着我都凌乱了,,,你这个实验无关变量干预了实验对象本身。

因为任意一个printf会调用甚至多次调用fputc,即会有SR和DR的读写操作。


建议做这个实验再另一个无关printf的串口上,直接操作DR和SR的寄存器(推荐)或者库函数
否则干扰下也不知道究竟是哪方面的原因
坚决不用寄存器,拒绝重复造轮子。
回复

使用道具 举报

6

主题

1097

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3571
金钱
3571
注册时间
2014-12-2
在线时间
365 小时
发表于 2016-8-29 19:58:27 | 显示全部楼层
再说一遍,我本人对你的这份探索之心是非常肯定的,这也是我一直在做的事情
我认为学习,就是在做哪些看起来无意义的东西,
而不是像公司里那样,拿钱,出效果,时间长了,自己内心对技术的那份热心也消磨完了。
时刻记着你是在学习,不是在完成任务,这种方式固然可能慢些,但收获的,都是干货

某些人不中肯的话亦可不必理会。

共勉。
坚决不用寄存器,拒绝重复造轮子。
回复

使用道具 举报

94

主题

369

帖子

0

精华

高级会员

Rank: 4

积分
865
金钱
865
注册时间
2016-8-25
在线时间
485 小时
 楼主| 发表于 2016-8-29 20:13:39 | 显示全部楼层
本帖最后由 学习stm32f4 于 2016-8-29 20:50 编辑
xkwy 发表于 2016-8-29 19:58
再说一遍,我本人对你的这份探索之心是非常肯定的,这也是我一直在做的事情
我认为学习,就是在做哪些看起 ...

非常感谢!
感觉学习stm32真不容易,特别是对我这种白板来说。
但是世上哪有随随便便成功的事情啊,共同努力学习!
回复

使用道具 举报

0

主题

1

帖子

0

精华

初级会员

Rank: 2

积分
64
金钱
64
注册时间
2020-4-19
在线时间
16 小时
发表于 2020-5-29 23:28:28 | 显示全部楼层
zmingwang 发表于 2016-8-29 18:19
建议你跟到USART_GetFlagStatus和USART_SendData这两个函数中去看一眼,GetFlagStatus()这个函数就是在读S ...

言简意赅!
回复

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
5
金钱
5
注册时间
2020-5-22
在线时间
0 小时
发表于 2020-6-5 23:51:45 | 显示全部楼层
你的程序中有printf函数,你的for循环中的TC位并非为初始状态的1,而是在经过printf函数的发送数据过程中就将TC置0了。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-9 20:37

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表