IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 2、寄存器版——stm32的system文件夹(usart文件夹) -> 正文阅读

[嵌入式]2、寄存器版——stm32的system文件夹(usart文件夹)

1、介绍

该文件夹有 usart.c 和 usart.h 两个文件。
作用:件用于串口的初始化和中断接收。
usart.c里面包含了2个函数:void USART1_IRQHandler(void);和void uart_init(u32pclk2,u32 bound);
里面还有一段对串口 printf 的支持代码。如果去掉,则会导致 printf 无法使用,虽然软件编译不会报错,但是硬件上 STM32F4 是无法启动的,这段代码不要去修改。

2、USART1_IRQHandler 函数

void USART1_IRQHandler(void)函数是串口1的中断响应函数,当串口1发生了相应的中断后,就会跳到该函数执行。
这里有一个小小的接收协议:通过这个函数,配合一个数组USART_RX_BUF[],一个接收状态寄存器, USART_RX_STA(这个寄存器就是一个全局变量,由程序员自己添加。只是它起到了一个类似寄存器的功能,才暂且将他称呼为寄存器)。实现对串口数据的接收管理。
USART_RX_BUF 的大小由 USART_REC_LEN 定义,也就是一次接收的数据
最大不能超过 USART_REC_LEN 个字节。USART_RX_STA 是一个接收状态寄存器其各的定义如下表:

设计思路:
当接收到电脑发过来的数据,把接收到的数据保存在USART_RX_BUF中,同时在接收状态寄存器(USART_RX_STA)中计数接收到的有效数据个数,当收到回车(回车的表示有两个字节:0x0D和0x0A)的第一个字节0x0D时,计数器就不会增加,等待0x0A的到来。但是如果没有0x0A没有到来,就认为这一次接收失败,重新开始下一轮的接收。如果接收到0x0A,则标记记 USART_RX_STA的第15位,这样就完成了一次接收,并等待该位被其他程序清除,从而开始新一轮的接收。而如果迟迟没有收到0x0D,那么在接收数据超过USART_REC_LEN时,就会丢弃前面的数据,重新接收。
代码如下:

#if EN_USART1_RX //如果使能了接收
//串口 1 中断服务程序
//注意,读取 USARTx->SR 能避免莫名其妙的错误
u8 USART_RX_BUF[USART_REC_LEN];//接收缓冲,最大 USART_REC_LEN 个字节.
//接收状态
//bit15, 接收完成标志
//bit14, 接收到 0x0d
//bit13~0,接收到的有效字节数目
u16 USART_RX_STA=0; //接收状态标记
void USART1_IRQHandler(void)
{
	u8 res;
#if SYSTEM_SUPPORT_OS //如果 SYSTEM_SUPPORT_OS 为真,则需要支持 OS.
	OSIntEnter();
#endif
	if(USART1->SR&(1<<5))//接收到数据
	{
		res=USART1->DR;
		if((USART_RX_STA&0x8000)==0)//接收未完成
		{
			if(USART_RX_STA&0x4000)//接收到了 0x0d
			{
				if(res!=0x0a)
					USART_RX_STA=0;//接收错误,重新开始
				else 
					USART_RX_STA|=0x8000; //接收完成了
			}
			else //还没收到 0X0D
			{
				if(res==0x0d)
					USART_RX_STA|=0x4000;
				else
				{
					USART_RX_BUF[USART_RX_STA&0X3FFF]=res;
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-1))
						USART_RX_STA=0;//接收数据错误,重新开始接收
				}
			}
		}
	}
#if SYSTEM_SUPPORT_OS //如果 SYSTEM_SUPPORT_OS 为真,则需要支持 OS.
	OSIntExit();
#endif
}

EN_USART1_RX 和 USART_REC_LEN 都是在 usart.h 文件里面定义的。
当需要使用串口接收的时候,只要在 usart.h 里面设置EN_USART1_RX 为 1 就可以了。不使用的时候,设置,
EN_USART1_RX 为 0 即可。这样可以省出部分 sram 和 flash。
我们默认是设置 EN_USART1_RX为 1,也就是开启串口接收的。

SYSTEM_SUPPORT_OS,则是用来判断是否使用操作系统(OS),如果使用了 OS,则调用 OSIntEnter 和 OSIntExit 函数,如果没有使用 OS,则不调用这两个函数(这两个函数用于实现中断嵌套处理,由 UCOS 提供,这里我们先不理会)。

3、uart_init函数

串口1初始化函数:void uart_init(u32 pclk2,u32 bound)。其中的参数pclk是APB2总线的时钟频率;bound设置需要的波特率,比如9600,921600等。
这个函数的重点就是在波特率的设置。由于stm32F4采用了分数波特率,所以STM32F4 的串口波特率设置范围很宽,而且误差很小。
stm32f4的每一个串口都有一个自己独立的波特率寄存器USART_BRR,通过设置该寄存器就可以配置不同的波特率。

STM32F4 有一个接收器过采样设置位:OVER8 位。该位是在USART_CR1寄存器中设置。当OVER8=0时,采用16倍过采样率,可以增加接收器对时钟的容差。当OVER8=1时,可以得到更高的速度。简单总结就是:OVER8=0时,精度高,容错性好;OVER8=1时,容错性差,但是速度快。
我们一般是设置OVER8=0,以得到更好的容错性。后面都是在OVER8=0时进行介绍。
前面提到 STM32F4 的分数波特率概念,其实就是在这个寄存器(USART_BRR)里面体现的。USART_BRR 的最低 4 位(位[3:0],当 OVER8=0 时)用来存放小数部分DIV_Fraction,
紧接着的 12 位(位[15:4])用来存放整数部分 DIV_Mantissa,最高 16 位未使用。
stm32f4波特率的计算公式:
在这里插入图片描述
上式中,fPCLKx是给串口的时钟(PCLK1用于串口2~5,PCLK2用于串口1和6);USARTDIV是一个无符号定点数。只要得到USARTDIV的值,就可以得到串口波特率寄存器 USART1->BRR 的值,反过来,只要得到 USART1->BRR 的值,就可以推导出USARTDIV的值。一般我们知道的是波特率,和 PCLKx 的时钟,要求的就是USART_BRR 的值:
假设我们的串口1要设置为115200的波特率,而PCLK2的时钟(即APB2总线时钟频率)是84M。这样我们就有计算:USARTDIV=84000000/(11520016)=45.572
即:
DIV_Fraction=16
0.572=9=0X09;
DIV_Mantissa=45=0X2D;
这样,我们就得到了了 USART1->BRR 的值为 0X2D9。只要设置串口1的BRR寄存器值为0X2D9就可以得到115200的波特率。
当然在某些波特率和PCLK2频率下,还是有误差,可以参考芯片中文手册。
下面初始化串口:(8位数据格式,1位停止位,无奇偶校验)

//初始化 IO 串口 1
//pclk2:PCLK2 时钟频率(Mhz)
//bound:波特率
void uart_init(u32 pclk2,u32 bound)
{
	float temp;
	u16 mantissa;
	u16 fraction;
	temp=(float)(pclk2*1000000)/(bound*16);//得到 USARTDIV@OVER8=0
	mantissa=temp; //得到整数部分
	fraction=(temp-mantissa)*16; //得到小数部分@OVER8=0
 	mantissa<<=4;
	mantissa+=fraction;
	RCC->AHB1ENR|=1<<0; //使能 PORTA 口时钟
	RCC->APB2ENR|=1<<4; //使能串口 1 时钟
	GPIO_Set(GPIOA,PIN9|PIN10,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_50M,
GPIO_PUPD_PU);//PA9,PA10,复用功能,上拉输出
	GPIO_AF_Set(GPIOA,9,7); //PA9,AF7
	GPIO_AF_Set(GPIOA,10,7);//PA10,AF7
	//波特率设置
	USART1->BRR=mantissa; //波特率设置
	USART1->CR1&=~(1<<15); //设置 OVER8=0
	USART1->CR1|=1<<3; //串口发送使能
#if EN_USART1_RX //如果使能了接收
//使能接收中断
	USART1->CR1|=1<<2; //串口接收使能
	USART1->CR1|=1<<5; //接收缓冲区非空中断使能
	MY_NVIC_Init(3,3,USART1_IRQn,2);//组 2,最低优先级
#endif
	USART1->CR1|=1<<13; //串口使能
}
  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-10-29 13:13:03  更:2021-10-29 13:14:37 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 8:47:36-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码