目录:
1.串口通信的基本概念
关于串口通信的基本概念,我在原来的博客中有写到过,这里就不再赘述,需要了解的,可以看下面这篇博客。
链接: https://blog.csdn.net/nbbskk/article/details/127852125
stm32中串口介绍:
- usart是stm32内部集成的硬件外设,可根据数据寄存器的一个字节数据自动生成数据帧格式,从TX引脚发送出去,也可自动接收RX引脚的数据帧格式,拼接为一个字节数据,存放在数据寄存器里。
- 自带波特率发生器,最高达4.5Mbits/s
- 可配置数据位长度(8/9)停止位长度(0.5/1/1.5/2)
- 支持同步模式、硬件流控制、DMA、智能卡、IRDA、LIN
在stm32中最长用的模式就是使用usart的异步收发功能。
- 其中的同步模式是指usart中可以引出引脚来使两个设备处于同步通信的模式,但是这种方法一般不用。
- 硬件流控制就是指有时候接收设备来不及接收数据,但是发送设备在源源不断发送数据,这样就容易导致数据的丢失,为了防止这一现象的产生,就会通过两个引脚RTS和CTS来进行硬件流控制,当接收设备未准备好接收数据的时候,硬件流线上就会置高电平,当接收设备准备好接收数据的时候,硬件流线上就会置低电平,通知发送设备可以进行数据的发送,这种方式一般也不常见。
- DMA的功能是进行数据的搬运,这个功能我们以后会详细介绍。
- 而向智能卡、IRDA、LIN等功能我们都基本不会用到,所以不需要掌握。
2.串口的基本结构
2.1.串口的硬件结构
串口的基本结构其实主要包含三个部分。
- 第一部分是接受部分,主要包含接收移位寄存器、接收数据寄存器等寄存器组成。
- 第二部分是发送部分,主要包含发送移位寄存器、发送数据寄存器等寄存器组成。
- 第三部分是波特率发生器部分,主要是用来产生波特率,由波特率发生寄存器组成。
- 其余部分就包括一些控制寄存器,使能位等等。
现在分析上图中的具体部分
-
这个部分是串口的引脚部分,其中最重要的是TX引脚和RX引脚,上面方块的引脚其他引脚都是和IRDA、LIN等有关的,我们平时一般用不到;然后下面块中的nRTS和nCTS主要就是上面讲的硬件流控制有关,用来通知发送设备是否可以发送数据。
-
第二个部分就是发送控制块,这个控制块主要是由发送数据寄存器和发送移位寄存器构成,用于数据的发送。通过发送数据寄存器和发送移位寄存器来配合,使数据发送到TX数据线上。
- 首先CPU会将数据传输到发送数据寄存器,当检测到发送移位寄存器将所有的数据都移出去以后,TDR就会将数据一次性发送到移位寄存器,这时候,标志位TXE(TX Empty)会置位,表示TDR为空,CPU可以将新的数据传送到TDR中。
- 然后移位寄存器会将数据一位一位的移动到数据发送端TX上,是从低位开始进行移动的,当数据移位寄存器将数据都移动出去以后,就会将TC这个标志位置位,表示数据移动完成。
- 这样就通过数据发送寄存器和数据移位寄存器的配合,就能高效实现数据的发送操作。
-
第三个部分就是接收控制块,接收控制块的工作机制是和发送控制块相反的操作,但是需要注意的是,其实TDR和RDR在硬件上是同一个寄存器,只是,在串口配置成发送模式的时候就变成了TDR,当配置成接收模式的时候就变成了RDR。这一部分也是通过RDR和接收移位寄存器进行配合来实现数据的接收。过程和发送过程相反,但是当数据从RX引脚移动到接收移位寄存器的时候,是没有标志位的,但是当从接收移位寄存器移动到RDR的时候,就会使得标志位RXNE(RX Not Empty)置位,通知CPU可以读取数据。
-
第四个部分就是波特率发生器,波特率就是通过这个地方的一个计算公式来计算出波特率的,但是,由于计算公式比较麻烦,然后我们平常配置波特率用库函数的方式来配置是十分方便的,所以我们不需要了解太多这部分的知识。
-
第五个部分就是具体的每个寄存器的配置,其中包括串口使能,各个标志位使能,中断发生等内容,等后续中具体的寄存器介绍的时候我们再具体介绍。
这五个部分就构成了串口的硬件结构,这也是串口能够正常运行的保障。
2.2.串口的数据帧
串口的数据帧格式在发送和接收时是相同的,我们以发送时为例,下图就是显示的发送时的数据帧格式。
这个数据帧格式就是用来配置发送时的帧格式,选择8位或者9位字长中,都是包含校验位的。当选择9位字长的时候,最好加上校验位,当选择8位字长的时候最好不加校验位,这样就能使发送的数据和接收的数据都变成一个字节,方便接收和发送。其中下面的空闲帧和断开帧都是和局域网协议有关的,串口中用不到,所以就不过多介绍。
2.3.接收器中的起始帧侦测
在一个数据位中有16个采样时钟。在空闲状态下,信号线置高电平,如果信号线突然检测到有低电平存在,接收器就会进行起始帧检测,在检测到下降沿以后,会在之后的第3、5、7次采样点再次进行第一次采样,在第8、9、10次采样点再次进行第二次采样。
- 如果三次采样中信号全都是为0,那表明进入起始帧,之后数据接收全部都在第8/9/10次来完成(这样可以保证采样是在信号正中间来进行的)。
- 如果两次采样中有两个‘0’,一个‘1’,那么也会表示起始位有效,但是会将噪声标志位NE置‘1’,提醒用户有噪声。
- 如果两次采样有大于一个‘1’存在,那么就会重新回到起始帧侦测的状态。
2.4.接收器中的信号接收
当进行完起始帧侦测后,就会进行信号的采集,具体采集的方法如下。
每个位也会有16个采样值,一般采样值都是在第8/9/10次进行采样,这样可以保证采样信号正好在正中间,一般情况下,采样信号会保证全‘0’或者全‘1’,但是,当出现噪声的时候,噪声标志位NE也会置‘1’。具体的格式如下图所示:
3.USART发送代码实现
3.1.cubemx配置
其他的配置都和原来相同。
3.2.串口的具体代码实现
我们平常主要就是用到的这四个函数,首先我们先来测试一下串口发送函数
接下来我们测试接收函数,由于接收函数没有办法在单片机上清晰的显示,所以我们接收到函数以后,立马进行发送出来,然后再显示在串口调试助手上。
这个接收中断和发送中断我们具体在第四章讲。
3.3.串口重定向(printf)
我们在C语言中打印信息的时候一般都是使用printf来输出信息,C库中使用的<stdio.h>是标准输入输出库,默认输入设备为键盘,默认输出设备为电脑屏幕,因此我们在C库中使用printf的时候不需要考虑其他的因素,只需要调用printf函数语句就可以输出相关信息了。
那么我们能否在stm32的串口中使用printf来打印相关的调试信息呢,答案是肯定的,而一般的做法是通过重定向的方法来讲printf的输出定向到串口中。
keil5中有C库的裁剪库microLib库,可以支持使用printf函数,但是我们需要进行重定向的配置。
首先需要勾选microLib库,
然后我们需要重写fputc函数,从而将printf的输出输出到串口中
首先我们需要在头文件出引入标准输入输出库<stdio.h>
然后编写fputc函数进行输出重定向,具体的格式如下:
最后我们需要对我们的代码进行测试:
我们可以看出现象,printf函数可以正常使用。
4.USART的中断发送与接收
在使用USART的时候,如果我们要是使能相关中断寄存器的话,那么USART就可以在发送结束或者接收结束的时候产生中断,这样就可以进行一系列的操作了。所有关于中断的函数一般都是在stm32f1xx_it.c这个c文件中包含,所以我们只需要在这个c文件中找一下就好了。.但是我们开启串口中断以后,在这个c文件中也只会表示为一个中断入口,我们需要进入这个函数来寻找相关的发送中断和接收中断函数。
4.1.USART中断发送
我们可以在stm32f1xx_it.c顺利找到串口1中断入口,然后我们追进串口中断中寻找。
我们往下找,可以发现一个EndTransmit_IT的函数,这个函数就是发送中断完成的函数。
然后我们继续往下追
可以发现下面有个回调函数,这个回调函数就是实现中断函数最后的功能了,我们需要重写这个回调函数。
我在usart.c中重写了这个回调函数,并用printf输出打印调试信息,别忘了这个c库也要包含stdio.h这个头文件
下面是具体的现象
当我们发送完成一串数据以后,会立即进入中断函数中,然后打印出我们设定好的内容。
4.2.USART中断接收
usart的中断接收和中断发送都是差不多的,因此我们不再进行赘述。
5.有关USART的相关寄存器(有关USART的相关寄存器只需了解即可)
stm32有关USART的相关寄存器如下:
- 状态寄存器(USART_SR)
- 数据寄存器(USART_DR)
- 波特比率寄存器(USART_BRR)
- 控制寄存器1(USART_CR1)
- 控制寄存器2(USART_CR2)
- 控制寄存器3(USART_CR3)
- 保护时间和预分频寄存器(USART_GTPR)
-
状态寄存器
状态寄存器主要就是用来显示串口的相关状态,主要是通过各种标志位来进行显示的,其中比较常用的标志位有TXE、TC、RXNE等标志位来用于发送和接收时状态的表示。
可以通过读取状态寄存器里面的各个状态来使USART进入中断或者执行其他功能。 -
数据寄存器
数据寄存器就是接收和发送过程中的TDR和RDR这两个寄存器,这两个寄存器在物理地址上其实是一个寄存器,当配置为发送模式的时候就变成了TDR,当配置为接收模式的时候就变成了RDR。这个寄存器的主要作用就是用来存放发送和接收的数据的。由于数据可以配置为8位或者9位,所以这个寄存器就只有位0到位8有效。
-
波特比率寄存器
波特比率寄存器就是用来产生波特率的,一般我们用库函数配置的时候系统直接默认帮我们配置好了波特率,因此我们不需要直接使用波特比率寄存器来直接配置波特率,所以这个寄存器我们大概率不需要了解。
-
控制寄存器1
控制寄存器1是串口寄存器中非常重要的控制器,包括对串口的使能,对字长的设置等内容,其中还有一些中断的设置,这就是控制寄存器主要的作用。
其中最重要的就是位13、位12用于使能USART并且定义数据字的长度。 -
控制寄存器2、控制寄存器3和保护时间和预分频寄存器
这三个寄存器主要和USART的其他功能有关,和DMA、LIN、IREN、智能卡等功能有关,这里就不过多介绍了,感兴趣的可以去看看stm32中文参考手册第25.6节。