OpenEdv-开源电子网

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

STM32战舰版串口通信学习

[复制链接]

42

主题

171

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
448
金钱
448
注册时间
2016-3-8
在线时间
57 小时
发表于 2016-11-24 12:16:45 | 显示全部楼层 |阅读模式
3金钱
这几天一直在学习串口通信实验,实验例程我基本上弄明白了,但是还有些细节上的问题没有明白。
第一:帧到底是什么概念,是指从接受端存入缓冲器里面的所有数据吗?
第二:缓冲器指的是什么,在什么存储器里面,中文手册里面的USART_DR里面只是32位的寄存器,而且能够用到的位只有9位,看样子肯定不是缓冲器。
第三:USART_DR里面包含了两个寄存器TDR和RDR但是USART_DR只是一个32位的存储器,是不是TDR和RDR指得都是这同一个寄存器。
第四:例程中规定的缓冲器最大存储字节是200字节,但是接受或者发送一个数据却是8位或者9位的数据,其中还可能会有起始位、停止位、奇偶校验位等完全超过了一个字节的长度,存入到缓冲器时,怎么存储的?
第五:例程中缓冲器规定最大存储字节是200字节,按照一个汉字占两个字节来算应该可以存储100个汉字,我发现输入了很多字,但是只有前99个字被存储了,后面的全部被省了,为什么?
第六:关于中断的,例程用到的是接收中断,即读取缓冲器中数据不为0即产生中断,从它的中断使能解释是缓冲器非0即产生中断,中断使能的条件是RXNE被置1产生中断,但是RXNE被置1的条件是USART_DR非空才置1,按照这个推理那缓冲器就是USART_DR寄存器,但是这个寄存器只有9位比特位能用,完全不够存储一句话甚至一个汉字,怎么能做缓冲呢?导致中段产生的条件应该是缓冲器非0造成的,所以缓冲器不是USART_DR。
第七:例程中的中断使用是如何体现出来的?主函数的功能是检测到有换行符输入就从缓冲器发送数据,中断事件是接收到数据产生中断。但是这个中断在主程序中怎么体现出来的呢?如果中断产生的条件改为发送数据中断,效果和接收数据中断效果均是一样的呀,无论接收数据中断还是发送数据中断效果都是一样的。

DR寄存器

DR寄存器

RNX中断

RNX中断

发送数据

发送数据

中断事件

中断事件

最佳答案

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

可以看出,题主对这些深层相关的内容非常感兴趣,兹倍感欣慰。 可能由于中文翻译,或者原子哥的手册措辞不够严谨,导致题主可能有一些误会。 因此,建议题主拜读一下英文原版手册, 从题主的提问中可以看出,似乎对这些底层的东西比较陌生, 这样情况下学习STM32就比较吃力了,因为它更复杂,更让人望而生畏。 建议题主先学习简单的如51单片机,由浅入深,这样效率可能更高一些, 也建议题主学习微机原理,你的问题中有 ...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

6

主题

1097

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3571
金钱
3571
注册时间
2014-12-2
在线时间
365 小时
发表于 2016-11-24 12:16:46 | 显示全部楼层
可以看出,题主对这些深层相关的内容非常感兴趣,兹倍感欣慰。

可能由于中文翻译,或者原子哥的手册措辞不够严谨,导致题主可能有一些误会。

因此,建议题主拜读一下英文原版手册,
从题主的提问中可以看出,似乎对这些底层的东西比较陌生,
这样情况下学习STM32就比较吃力了,因为它更复杂,更让人望而生畏。
建议题主先学习简单的如51单片机,由浅入深,这样效率可能更高一些,
也建议题主学习微机原理,你的问题中有部分涉及到这些,,


下面我尝试着回答其中的部分问题:
第一:帧到底是什么概念

1.png

你指的应该是数据帧。串口传输数据以帧为单位,数据帧包括如下:
起始位:1bit,表现为TX引脚为低电平,持续时间1bit
数据位:8~9bit,可由寄存器配置选择一帧数据包含8位还是9位,低位先传
校验位:1bit,可由寄存器配置选择是否启用校验位or奇校验还是偶校验
停止位:1~2bit,可由寄存器配置选择1bit还是2bit
(上述中1bit持续时长就是波特率)


第二:缓冲器指的是什么,在什么存储器里面

根据你的上下文,推测你说的应该是存储200字节的那个缓冲器,它只是程序中定义的一个外部数组,用于存储从USARTx->DR中读过来的数据,因为USARTx->DR只能暂存一帧数据,所以要想连续接收,必须及时地把数据取下来,否则会丢失,这个200字节位于STM32的起始地址为0x2000_0000的RAM中,具体地址由keil编译时再分配。

3.png

第三:USART_DR里面包含了两个寄存器TDR和RDR但是USART_DR只是一个32位的存储器,是不是TDR和RDR指得都是这同一个寄存器。

2.png

如图,整个虚线框起来的灰色区域在逻辑上叫USARTx->DR,其中包含了TDR(只写)和RDR(只读),CPU通过使用不同的指令对应着不同的总线时序来访问。
因此USARTx->DR看起来像一个可读可写的寄存器,但实际并非如此。(准确来说,物理上并不存在USARTx->DR这样"一个"寄存器)

第四:例程中规定的缓冲器最大存储字节是200字节,但是接受或者发送一个数据却是8位或者9位的数据,其中还可能会有起始位、停止位、奇偶校验位等完全超过了一个字节的长度,存入到缓冲器时,怎么存储的?

起始位,停止位,校验位等这些都是固定的(或者通过寄存器事先配置好不变的),而数据位也配置为8-bit,所以缓冲器只需保存这8-bit就可以。我们的目的也仅仅是传输这8-bit而已,其他的位是为了确保传输正确可靠而加上去的。
比如你收发一个快递,仓库里只会放真正的货物,而快递用的箱子胶带等都由快递公司包了,或者收到货拆包后那些箱子都扔了不会占用宝贵的仓库空间。

第五:例程中缓冲器规定最大存储字节是200字节,按照一个汉字占两个字节来算应该可以存储100个汉字,我发现输入了很多字,但是只有前99个字被存储了,后面的全部被省了,为什么?

首先,缓冲器设计上一定要大于实际可能会遇到的最大字节数,而且要防止溢出。
你要是想输入很多字,建议把缓冲器改的更大(一般至少会取1.5~2倍)
你还提到只有99字,我想问你是否知道字符串有结束符?或者回车换行符?它也会占用字节空间的

4.png

第六:关于中断的,例程用到的是接收中断,即读取缓冲器中数据不为0即产生中断,从它的中断使能解释是缓冲器非0即产生中断,中断使能的条件是RXNE被置1产生中断,但是RXNE被置1的条件是USART_DR非空才置1,按照这个推理那缓冲器就是USART_DR寄存器,但是这个寄存器只有9位比特位能用,完全不够存储一句话甚至一个汉字,怎么能做缓冲呢?导致中段产生的条件应该是缓冲器非0造成的,所以缓冲器不是USART_DR。

这里理解的缓冲器和刚才的应该不是同一个概念。
前面提到的200字节缓冲器,它的作用是把USARTx->DR的内容及时地读取出来,以便连续地接收数据。
而USART模块本身的寄存器是也带有缓冲的,具体运行如下:


发送:CPU通过写USARTx->DR,即把数据送到TDR中,如果USART模块当前没有发送任务则会把它立即送到Transmit Shift Register,否则等待当前发送任务接收后再把TDR的数据送到Transmit Shift Register,Transmit Shift Register由TRANSMIT CONTROL来管理,用于一位一位地把数据移位送到TX引脚上,在这过程中TDR的作用是暂存。
注:CPU把数据写入USARTx->DR后,瞬间USARTx->SR[TXE]会被清零,当USART模块把TDR的数据送到Transmit Shift Register后,USARTx->SR[TXE]会置位(同时可触发一个中断),当Transmit Shift Register里的数据全部移位出去到TX引脚并且校验位停止位等都发送出去了,则USARTx->SR[TC]会置位(同时可触发一个中断)。
接收:当USART模块从RX引脚侦测到起始信号后,会开始着手把RX引脚上的信号按照预定波特率一位一位地移入Receive Shift Register,当这个数据帧接收完毕后,会把Receive Shift Register的内容送到RDR中,此后USART模块又可以接收新的数据帧了,在这过程中RDR的作用是暂存接收到的数据(试想一下没有RDR会怎样?)
注:USART把Receive Shift Register的内容送到RDR的同时USARTx->SR[ RXNE]会置位(同时可触发一个中断),如果CPU读取USARTx->DR,则RDR的数据会被取走,同时USARTx->SR[ RXNE]会清零,如果USART模块又接收到了一个数据帧准备把Receive Shift Register的内容送到RDR时,之前的RDR内容还没取走,则可能会丢失一个数据,所以,需要在程序里开辟一个数组,用于及时地把RDR的数据取走。
综上所述,USARTx->DR的确是一个缓冲器

第七:例程中的中断使用是如何体现出来的?主函数的功能是检测到有换行符输入就从缓冲器发送数据,中断事件是接收到数据产生中断。但是这个中断在主程序中怎么体现出来的呢?如果中断产生的条件改为发送数据中断,效果和接收数据中断效果均是一样的呀,无论接收数据中断还是发送数据中断效果都是一样的。

例程中用到了接收中断,当串口接收到数据后会触发该中断,这样软件可以立即把数据读到缓冲里,同时,在中断里加入了一些换行/溢出/出错等判断。
接收中断是接收到数据触发,发送中断是发送完成触发,并没有任何关联性,你说它俩一样,不知道你怎么理解的。
中断的意义在于减少CPU的负载,使之不必一直查询等待USARTx->SR[ RXNE]这个标志位,因而变被动为主动,从而不会错失任何数据。
在这个例程里,使用中断还是查询法没有太大的区别,也肯不出有何优越性,
但是如果是一个复杂的工程,有很多任务的场景下,如果不用中断就难保CPU能及时地侦测到标志位及时地读出数据。
但是,使用中断的话,如在这个例程里,主函数主循环是一直在检测USART_RX_STA标志位,它可以改为10ms检测一次,乃至不定时地检测一次,都不会影响数据的接收的,因为数据已经由中断里的服务函数把它存到RAM里了,稍晚些读取没有什么问题,但是如果是USART的标志位,如果晚了,正如前面说的,可能数据就被覆盖了,结果是致命的。




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

使用道具 举报

42

主题

171

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
448
金钱
448
注册时间
2016-3-8
在线时间
57 小时
 楼主| 发表于 2016-11-24 15:13:36 | 显示全部楼层
xkwy 发表于 2016-11-24 14:09
可以看出,题主对这些深层相关的内容非常感兴趣,兹倍感欣慰。

可能由于中文翻译,或者原子哥的手册措辞 ...

这位老师对我的问题耐心细致认真的讲解,让我很感动,您的讲解让我对USART工作原理有了更清晰的认识,非常感激这位老师能花宝贵时间为我解答每一道问题。
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-3-1 16:53

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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