当前位置:网站首页>STM32串口寄存器库函数配置方法

STM32串口寄存器库函数配置方法

2022-07-07 06:26:00 一只大喵咪1201

作者:一只大喵咪1201
专栏:《STM32学习》
格言:你只管努力,剩下的交给时间!
请添加图片描述

描述

设备与设备之间需要进行通信,如单片机与单片机之间,单片机与电脑之间等等,通信又有两种方式,串行通信和并行通信。

串行通信和并行通信

本喵来说一下二者的区别

并行通信

  • -传输原理:数据各个位同时传输。
  • -优点:速度快
  • -缺点:占用引脚资源多

图
假设两个设备之间传输的是一个8位的数据,上图就是两设备数据线的连接方式,需要八根线,两个设备各占八个IO口,每一个IO口对应数据的一位。

串行通信

  • -传输原理:数据按位顺序传输。
  • -优点:占用引脚资源少
  • -缺点:速度相对较慢

图
同样还是传输8位的数据,只需要一根数据线就可以实现数据的传送。另一根是共地线。

‍串行通信通信方式

  1. 串行通信按照数据的传送方向也分为:

单工制式:

  • 数据传输只支持数据在一个方向上传输

半双工制式:

  • 允许数据在两个方向上传输,但是,在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信;

全双工制式:

  • 允许数据同时在两个方向上传输,因此,全双工通信是两个单工通信方式的结合,它要求发送设备和接收设备都有独立的接收和发送能力。

图
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再从该寄存器中读取数据。

串行通信涉及到的寄存器(可略过)

结构框图中的蓝色框框中的就是串口所拥有的寄存器。

  1. 状态寄存器(USART_SR)

图
这是它32位的分布情况,该寄存器中只有0到9位在使用,其他位保留,使用到的位每一位都代表着串行通信的一个状态。
图
这是它用到的10个位具体代表意义的情况。
在使用过程中通常使用一些库函数来查询串行通信的状态。

  1. 数据寄存器(USART_DR)

图
这是它32位的分布情况,只使用到了低8位,其余位保留,着8位可以读可以写。无论是发送数据还是接收数据都是对这8位进行操作。

图
这是8位的具体情况。

  1. 控制寄存器 1(USART_CR1)

图
这是它32位的使用情况,只有低14位在使用,其他位保留。
图
这是它每一位的具体控制情况。

  1. 控制寄存器 2(USART_CR2)

图
这是它32位的使用情况,通用只使用了低14位,其他位保留。
图
这是它每一位的具体控制情况。

  1. 控制寄存器 3(USART_CR3)

图
这是它32位的使用情况,只使用到了第11位,其他位保留。
图
这是它每一位的具体控制情况。

  1. 波特比率寄存器(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位中。

串口配置的一般步骤

  1. 串口时钟使能,GPIO时钟使能

在本喵的文章端口复用和重映像一文中曾详细讲解了串口的复用,这里我们直接使用。

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//PA9和PA10是串口1的复用端口
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//串口1挂载在APB2总线上
  1. 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上。

  1. 串口参数初始化
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);//串口进行初始化

以上代码就完成了串口的初始化。

  1. 开启中断并且初始化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);//中断优先级初始化
  1. 使能串口

在所有的初始化设置完成后要使能串口,也就是将串口打开

USART_Cmd(USART1,ENABLE);//使能串口,也就是打开串口
  1. 编写中断处理函数

现在串口也已经打开了,我们要编写进入中断后的函数,也就是进入中断后让它干什么

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,说明就是发送中断,则不执行中断处理函数中的内容,继续等待。
接收到的值是我们在电脑上输入给单片机的值,然后再将这个这反馈给电脑。

  1. 等待中断发生
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官方提供了对应的库函数后便对寄存器的了解没有那么重要了,只需要有个印象,万一用到的时候能够找的到。只要严格按照本喵上面所说的配置流程就会很容易配置出来,至于串行通信的具体使用,在后面的串行通信实验中会给大家说到。

原网站

版权声明
本文为[一只大喵咪1201]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_63726869/article/details/125280985