当前位置:网站首页>STM32串口寄存器库函数配置方法
STM32串口寄存器库函数配置方法
2022-07-07 06:26:00 【一只大喵咪1201】
作者:一只大喵咪1201
专栏:《STM32学习》
格言:你只管努力,剩下的交给时间!
描述
设备与设备之间需要进行通信,如单片机与单片机之间,单片机与电脑之间等等,通信又有两种方式,串行通信和并行通信。
串行通信和并行通信
本喵来说一下二者的区别
并行通信
- -传输原理:数据各个位同时传输。
- -优点:速度快
- -缺点:占用引脚资源多
假设两个设备之间传输的是一个8位的数据,上图就是两设备数据线的连接方式,需要八根线,两个设备各占八个IO口,每一个IO口对应数据的一位。
串行通信
- -传输原理:数据按位顺序传输。
- -优点:占用引脚资源少
- -缺点:速度相对较慢
同样还是传输8位的数据,只需要一根数据线就可以实现数据的传送。另一根是共地线。
串行通信通信方式
- 串行通信按照数据的传送方向也分为:
单工制式:
- 数据传输只支持数据在一个方向上传输
半双工制式:
- 允许数据在两个方向上传输,但是,在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信;
全双工制式:
- 允许数据同时在两个方向上传输,因此,全双工通信是两个单工通信方式的结合,它要求发送设备和接收设备都有独立的接收和发送能力。
2. 串行通信按照数据的传送方式又分为:
同步通信:带时钟同步信号传输。
- -SPI,IIC通信接口
异步通信:不带时钟同步信号。
- -UART(通用异步收发器),单总线
常用的串行通信接口:
在这里,本喵只讲解异步通信。
串行异步通信有以下特点:
全双工异步通信:
- 分数波特率发生器系统,提供精确的波特率。
-发送和接受共用的可编程波特率,最高可达4.5Mbits/s- 可编程的数据字长度(8位或者9位);
- 可配置的停止位(支持1或者2位停止位);
- 可配置的使用DMA多缓冲器通信。
- 单独的发送器和接收器使能位。
- 检测标志:① 接受缓冲器 ②发送缓冲器空 ③传输结束标志
- 多个带标志的中断源。触发中断。
- 其他:校验控制,四个错误检测标志。
在使用异步通信时,需要对参数进行设置:
- 起始位
- 数据位(8位或者9位)
- 奇偶校验位(第9位)
- 停止位(1,1.5,2位)
- 波特率设置
如下图这样
这样的数据格式被叫做帧格式。
串行通信的接线
大容量STM32F10x系列芯片,包含3个USART(通用同步异步收发器)和2个UART(通用异步收发器),也就是说,作为异步通信的串口可以有5个,它们的端口复用如下图:
RXD是接收端引脚,TXD是发送端引脚。
在接线的时候,一方的RXD要与另一方的TXD相连,并且TXD要与另一方的RXD相连。
串行通信结构框图
上图是串行通信的整个结构框图。
串行通信过程
框图中的红色框框部分是串行通信的数据接收和发生过程。
数据的发送:
- 当CPU要发送一个数据的时候,首先将数据写入发送数据寄存器(TDR)中,然后通过发送移位寄存器一位一位的发送出去,直到遇到停止位便结束发送。
数据的接收:
- 当外部有数据传送来时,CPU需要接收数据,此时数据一位一位的接收到了接收移位寄存器中,然后再传送到接收数据寄存器(RDR)中,CPU再从该寄存器中读取数据。
串行通信涉及到的寄存器(可略过)
结构框图中的蓝色框框中的就是串口所拥有的寄存器。
- 状态寄存器(USART_SR)
这是它32位的分布情况,该寄存器中只有0到9位在使用,其他位保留,使用到的位每一位都代表着串行通信的一个状态。
这是它用到的10个位具体代表意义的情况。
在使用过程中通常使用一些库函数来查询串行通信的状态。
- 数据寄存器(USART_DR)
这是它32位的分布情况,只使用到了低8位,其余位保留,着8位可以读可以写。无论是发送数据还是接收数据都是对这8位进行操作。
这是8位的具体情况。
- 控制寄存器 1(USART_CR1)
这是它32位的使用情况,只有低14位在使用,其他位保留。
这是它每一位的具体控制情况。
- 控制寄存器 2(USART_CR2)
这是它32位的使用情况,通用只使用了低14位,其他位保留。
这是它每一位的具体控制情况。
- 控制寄存器 3(USART_CR3)
这是它32位的使用情况,只使用到了第11位,其他位保留。
这是它每一位的具体控制情况。
- 波特比率寄存器(USART_BRR)
这是它32位的使用情况,只有低16位在使用,其他位保留。0到3位是波特率的小数部分,4到15位是波特率的整数部分。
这是它使用位的具体意义。
以上6个寄存器是我们经常使用的寄存器,当然还有其他的寄存器,在使用到的时候本喵再详细讲述。
波特率设置
串行接下结构框图中绿色的框框是用来设置串行通信的波特率的。
USART1使用的是fPCLK2,它一般的频率是72MHZ,而其他USART使用的是fPCLK1,一般频率是36MHZ。
波特率就是在fPCLKx的基础上除以USARTDIV(分频系数),再除以16到出来的。
USARTDIV是通过对寄存器USART_BRR设置得到的数值,可以是小数。
波特率的计算
这是波特率的计算公式。
下面我们来接收如何通过USARTDIV得到串口USART_BRR寄存器中的值。
假设我们的串口1要设置波特率的值为115200,而PCLK2的时钟为72MHZ。
- 根据上面的公式有:
USARTDIV=72000000/(115200*16)=39.0625那么得到:
- DIV_Fractino = 16*0.0625 = 1 = 0X01;(小数部分)
DIV_Mantissa = 39 = 0X27;(整数部分)这样我们就得到了USART_BRR寄存器中的值为0X271。只要设置串口1的BRR寄存器的值为0X271就可以得到115200的波特率。
这里要注意,小数部分要乘以16再放入USART_BRR寄存器的低4位中。
串口配置的一般步骤
- 串口时钟使能,GPIO时钟使能
在本喵的文章端口复用和重映像一文中曾详细讲解了串口的复用,这里我们直接使用。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//PA9和PA10是串口1的复用端口
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//串口1挂载在APB2总线上
- GPIO端口模式设置
由于使用的端口复用功能,所以需要进行配置,也就是对IO口进行初始化,同样在端口复用和重映像一文中曾详细讲解了串口的复用,这里我们直接使用。
GPIO_InitTypeDef GPIO_InitStructe;
GPIO_InitStructe.GPIO_Mode=GPIO_Mode_AF_PP;//推挽复用输出
GPIO_InitStructe.GPIO_Pin=GPIO_Pin_9;//PA9引脚复用为TX
GPIO_InitStructe.GPIO_Speed=GPIO_Speed_10MHz;//速度无所谓
GPIO_Init(GPIOA,&GPIO_InitStructe);//PA9引脚复用为USART1的TX引脚
GPIO_InitStructe.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_InitStructe.GPIO_Pin=GPIO_Pin_10;//PA10引脚复用为RX
GPIO_InitStructe.GPIO_Speed=GPIO_Speed_10MHz;//速度无所谓
GPIO_Init(GPIOA,&GPIO_InitStructe);//PA10引脚复用为USART1的RX引脚
以上代码就将USART1的TXD和RXD引脚复用到了PA9和PA10上。
- 串口参数初始化
USART_InitStructe.USART_BaudRate=115200;//波特率设置为115200
USART_InitStructe.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//无硬件流控制
USART_InitStructe.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;//USART1的发送和接受引脚
USART_InitStructe.USART_Parity=USART_Parity_No;//无校验位
USART_InitStructe.USART_StopBits=USART_StopBits_1;//停止位是1位
USART_InitStructe.USART_WordLength=USART_WordLength_8b;//数据位位8位,无校验位
USART_Init(USART1,&USART_InitStructe);//串口进行初始化
以上代码就完成了串口的初始化。
- 开启中断并且初始化NVIC(如果需要开启中断才需要这个步骤)
在本喵的文章NVIC中断优先级管理一文中层讲到过中断的分组以及使用。
首先需要在主函数中进行中断的分组
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断分组使用分组2
分组完成后我们需要对USART1中断使能,并且设置优先级
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//对USART1的接收中断使能
在上面的控制寄存器 1(USART_CR1) 介绍中有详细的介绍。
然后设置中断优先级
NVIC_InitTypeDef NVIC_InitStructe;
NVIC_InitStructe.NVIC_IRQChannel=USART1_IRQn;//中断类型是USART1中断
NVIC_InitStructe.NVIC_IRQChannelCmd=ENABLE;//使能
NVIC_InitStructe.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级设置为1
NVIC_InitStructe.NVIC_IRQChannelSubPriority=1;//响应优先级设置为1
NVIC_Init(&NVIC_InitStructe);//中断优先级初始化
- 使能串口
在所有的初始化设置完成后要使能串口,也就是将串口打开
USART_Cmd(USART1,ENABLE);//使能串口,也就是打开串口
- 编写中断处理函数
现在串口也已经打开了,我们要编写进入中断后的函数,也就是进入中断后让它干什么
void USART1_IRQHandler(void)
{
u8 ret = 0;
//判断是否是接收中断
if(USART_GetITStatus(USART1,USART_IT_RXNE))
{
ret = USART_ReceiveData(USART1);//发生接收中断后读取数据寄存器中的值
USART_SendData(USART1,ret);//将接收到的值再发送给电脑
}
}
中断处理函数的函数名的格式必须按照这个,因为在启动文件中已经有规定的,返回类型是空类型
进入中断以后,有可能是发送中断,也有可能是接收中断,所以需要用
USART_GetITStatus(USART1,USART_IT_RXNE)
这个函数判断一下中断是否是接收中断,如果是就返回1,如果返回值是0,说明就是发送中断,则不执行中断处理函数中的内容,继续等待。
接收到的值是我们在电脑上输入给单片机的值,然后再将这个这反馈给电脑。
- 等待中断发生
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断分组使用分组2
my_USART_Init();//进行串口的一系列初始化
while(1);//等待中断的发生
}
以上8个步骤就是整个串口异步通信的寄存器库函数配置过程,这样配置完成后就可以使用了
当然还有一些库函数是上面过程中没有提到的,比如串口传输状态获取
FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);
void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);
等等,这些函数在后面使用到的时候会详细的讲解。
效果展示
将代码烧录到STM32中后,打开串口调试助手
将波特率,停止位,数据位,校验位等信息和我们程序中所写的设置成一样。
在发送窗口发送信息
在接收窗口就对接收到对应的信息
下面是整个界面的图
由于单片机并没有现象,所以这里就不展示开发板的状态了。
总结
串口寄存器以及串行通信的配置主要就在于使用库函数的时候,要明确在什么时候使用什么库函数,它的作用是什么,至于具体操作的是哪个寄存器,在ST官方提供了对应的库函数后便对寄存器的了解没有那么重要了,只需要有个印象,万一用到的时候能够找的到。只要严格按照本喵上面所说的配置流程就会很容易配置出来,至于串行通信的具体使用,在后面的串行通信实验中会给大家说到。
边栏推荐
- Skills that testers must know: Selenium's three waiting ways are interpreted clearly
- [Nanjing University] - [software analysis] course learning notes (I) -introduction
- channel. Detailed explanation of queuedeclare parameters
- Count sort (diagram)
- 数字三角形模型 AcWing 275. 传纸条
- opencv 将16位图像数据转为8位、8转16
- mysql分区讲解及操作语句
- Explain Huawei's application market in detail, and gradually reduce 32-bit package applications and strategies in 2022
- LeetCode 715. Range module
- Greenplum6.x搭建_环境配置
猜你喜欢
随机推荐
Redis summary
Speaking of a software entrepreneurship project, is there anyone willing to invest?
Image segmentation in opencv
Several methods of calculating the average value of two numbers
Greenplum 6.x monitoring software setup
Nanjing commercial housing sales enabled electronic contracts, and Junzi sign assisted in the online signing and filing of housing transactions
Quick sorting (detailed illustration of single way, double way, three way)
Greenplum6.x搭建_安装
实现自定义内存分配器
Vagrant failed to mount directory mount: unknown filesystem type 'vboxsf'
Tronapi wave field interface - source code without encryption - can be opened twice - interface document attached - package based on thinkphp5 - detailed guidance of the author - July 6, 2022 - Novice
Personal deduction topic classification record
Test pits - what test points should be paid attention to when adding fields to existing interfaces (or database tables)?
阿里p8推荐,测试覆盖率工具—Jacoco,实用性极佳
个人力扣题目分类记录
数据库存储---表分区
MySQL partition explanation and operation statement
Recommended by Alibaba P8, the test coverage tool - Jacobo is very practical
Calculation s=1+12+123+1234+12345 C language
Golang etcdv3 reports an error. The attribute in grpc does not exist