UART:universal asynchronous receiver and transmitter通用异步收发器
USART:universal synchronous asynchronous receiver and transmitter通用同步异步收发器
上图是利用寄存器配置的步骤,下面我用官方库函数配置USART1
1、要配置串口usart1,先查看数据手册以及开发板原理图的芯片管脚
根据上图可以看出USART1的发送线USART_TX连在芯片的PA9管脚,接收线USART_RX连在芯片的PA10管脚
再根据上图可以看出USART的时钟和GPIOA的时钟都挂在APB2总线上,有了这两条信息我们就可以开始配置的第一步了。
一、首先我们开启PA9和PA10两个IO口的时钟
1、查询开启APB2线上外设时钟的库函数,下图为查询到的结果
由上图可以看出,此函数的作用是开启或关闭APB2指定线上外设的时钟,那么这两个参数必然包括指定外设和让他使能或失能的标志,使能为ENABLE、失能为DISABLE,剩余的一个参数我们在下面找到外设时钟的标志
由上图我们看到我们要开启的GPIOA的时钟参数为:RCC_APB2Periph_GPIOA
调用函数并将对应的参数填入
毛病有不了一点儿。
2、接下来初始化管脚PA9和PA10
同样查询库函数
上图函数是用来初始化管脚的属性的,两个参数分别是GPIOX,和一个结构体,往下翻可以看到结构体里面要配置的属性,下图示
这个结构体中要配置管脚的属性有,GPIOX的管脚号、管脚输出速率、管脚的输入输出模式。
看了上图我们思考一下管脚各自对应的属性,先看PA9(USART_TX串口1的发送管脚),(1)我们自然要选择GPIO_Pin_9这个参数了(2)输出速率我们选择最高速率(3)我们站在单片机的角度来看,发送管脚自然是输出模式了,再有我们需要输出高电平1(3.3V)、低电平0(0V),那么开漏输出模式自然无法满足,因为开漏是无法给出高电平的,具体可以搜索一下CMOS管的开漏,那么为什么要复用呢?看下图可知这个管脚USART还要用到所以要复用一下
到此初始化PA9管脚的三个参数分别为GPIO_Pin_9、GPIO_Speed_50MHz、GPIO_Mode_AF_PP。知道了这些参数后我们定义一个GPIO_InitTypeDef结构体来容纳这些参数
将参数填入,调用GPIO_Init函数初始化IO口得到下图
同样的思路,PA10作为串口输入管脚,GPIO_Pin参数选择GPIO_Pin_10,因为是输入模式不需要输出速度,输入模式没有硬性要求,选择浮空输入模式GPIO_Mode_IN_FLOATING
同样的步骤初始化PA10管脚,不再赘述
二、我们开启USART1的时钟并初始化它
(1)由前面的时钟树可以看出,USART1的时钟也挂在APB2总线上,那么开启时钟
(2)接着我们要初始化USART1,查询库函数得到下图
我们要初始化的串口是USART1那么第一个参数当然是USART1,第二个参数是它的一些属性,那么我们看看有哪些属性,下图
我们看第一个参数,波特率,波特率描述的是一秒钟发送的位数(bit),可以自己设定,但是最终要选择和串口软件一样的波特率,这里我就选择115200了
数据长度就是你要发送一次数据的位数了,这里我选择8位;停止位类似与两个人打电话最后说我挂了啊,然后结束通信,这里我选择1位;硬件流控制选择不使用;模式我们既要接收还要发送,所以选择USART_Mode_Rx | USART_Mode_Tx;不使用校验位USART_Parity_No;最后同样初始化一个结构体然后填入对应参数初始化。
到这里只需要查询到对应功能的函数即可,参数根据库函数手册选择你需要的就行。
上面就是初始化工作,接下来我们开启串口使能(打开串口的开关)。
要开启的串口是USART1,那么参数选择USART1、ENABLE.
到此基本的串口配置工作完成。接下来我们要进行收发数据操作,那么仅仅配置串口是不行满足这两个操作的。
我们先看一下串口收发数据的操作示意图
可以看出数据收发利用的是同一个数据寄存器(DR)如下图,单片机是从TX口向外发送数据,所以首先可以看出图左为外、图右为内
1)发送数据流程:
我们需要判断一下发送数据寄存器(TDR)是否为空,如果为空那么我们将数据赋给DR(相当于写入TDR),为什么要判断?这是因为TDR位数有限,满了再写会把数据挤掉导致数据出错。下一步TDR会判断发送移位寄存器是否有数据,如果有数据会等待数据被移走,然后自动将自己的数据写入发送移位寄存器,最后数据通过tx口发送。
2)读取数据流程
外界数据通过RX口进入移位寄存器,移位寄存器将数据进行移位,当寄存器满时移位寄存器自动将数据写入接收数据寄存器(DRD),我们只需要读DR里的内容即可。
明白了这两个流程我们就可以构建自己的读写数据函数了,先写发送数据函数
根据流程,我们需要先判断发送数据寄存器是否为空,怎么判断呢?状态寄存器看下图通过判断状态寄存器的TXE位得出发送寄存器是否为空,也就是TXE=1时可以写入DR
这里我直接判断寄存器的TXD位是否为0,是0代表还有之前的数据没有移入发送移位寄存器,在此阻塞。其实还可以使用库函数,库函数很方便且可读性较强
while((USART->SR&(0x1<<6))==0);//寄存器方式
while(USART_ GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);//RESET宏定义为0
可以看到下图的两个信号,TXE和TC这里谈一下这两个信号的区别,翻到图248 USART框图看到DR寄存器写入发送数据寄存器,寄存器通过TX口发出数据,那么这两个信号的区别就在TXE是判断发送数据寄存器是否为空,也就是你现在能不能写入DR寄存器,另一个TC是判断发送移位寄存器是否为空(之前的数据发送完毕没有,硬件判断是否能将发送数据寄存器放到发送移位寄存器)
最后调用发送数据库函数USART_ SendData完成自定的发送数据函数
接下来测试一下发送数据函数
调用函数并打开串口软件连接,注意串口软件右侧的波特率、停止位等信息选择正确。复位后发送一个w,测试结果如下
接下来写接收函数,那么接收函数的条件是什么?就像传球一样,1、对方手里有球才能传给你2、你得知道对方什么时候会传给你。我们先只考虑第一个条件,现在你只需要盯着他手里的球一直等他就行。
那么如何判断第一个条件,翻看USART_SR状态寄存器可知,我们需要判断的位为RXNE,当它为1是我们可以读出数据
上代码
当然也可以换成库函数来写
文章来源:https://www.toymoban.com/news/detail-755253.html
while((USART_GetFlagStatus(USART1,USART_FLAG_RXNE))==RESET);
data=USART_ReceiveData(USART1);
USART1_SendData(data);
验证一下
此处有一个问题,如果while(1)里面接收代码下有大量代码的话,会造成数据丢失,因为发送一位数据需要1/波特率秒,这个速度是很快的,但是你接收一位之后还要运行大量代码,这时候后续的数据已经过来了,过来的数据无法接收造成丢失。但是我们一个工程不可能只接受数据,这是不允许的,所以要用到中断来接收。中断在其他文章中再叙述。文章来源地址https://www.toymoban.com/news/detail-755253.html
到了这里,关于STM32 串口通信USART1的配置和使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!