STM32F103 HAL库SYSTEM文件夹介绍(二) 您所在的位置:网站首页 systemui在哪个文件夹 STM32F103 HAL库SYSTEM文件夹介绍(二)

STM32F103 HAL库SYSTEM文件夹介绍(二)

2023-09-15 03:42| 来源: 网络整理| 查看: 265

SYSTEM文件夹 1、delay1.1 、delay 延时思路1.2 、延时函数的使用1.3、HAL库自带延时函数 2、sys3、usart

HAL库基本使用系列的 全部博客是我重新学习HAL库的学习记录,仅作为学习记录。其中使用了正点原子Mini开发板和正点原子HAL库Demo,详细的资料请观看正点原子官网

  相信使用过正点原子工程模板的小伙伴,对于SYSTEM文件夹并不陌生,里面包含了delay、sys、usart(默认的串口0)的代码。 在这里插入图片描述

1、delay

delay 文件夹内包含了 delay.c 和 delay.h 两个文件,包含7个函数:

void delay_osschedlock(void); void delay_osschedunlock(void); void delay_ostimedly(u32 ticks); void SysTick_Handler(void); void delay_init(u8 SYSCLK); void delay_ms(u16 nms); void delay_us(u32 nus);

  前面 4 个函数,仅在支持操作系统(OS)的时候,需要用到比如RTOS,但是操作系统一般会有自己的延时函数,也可以使用操作系统的延时函数,时间片,而后面三个函数,则不论是否支持 OS 都需要用到。

1.1 、delay 延时思路

  利用SysTick 定时器,SysTick 定时器是一个 24 位的倒计数定时器,当计数到 0 时,将从RELOAD 寄存器中自动重装载定时初值,开始新一轮计数。这样既不占用中断,也不占用系统定时器。如果使用STM32 CUBE IDE去配置STM32 的时钟是可以很清楚地看到时钟选择。   对于us级别的延时实现,利用时钟摘取法,即算好要函数的时间内SysTick 计数次数,假设系统时钟为 72Mhz,那么 SysTick 每增加 1,就是 1/72us,一直统计SysTick 的计数变化,直到达到设定的值,就说明延时到了。

1.2 、延时函数的使用

延时函数的使用,利用宏定义作为选择。常用的延时函数如下所示:

void delay_init(u8 SYSCLK);//初始化延时函数 void delay_ms(u16 nms); // ms级别延时 void delay_us(u32 nus);// us级别延时

延时函数初始化调用,传入系统时钟频率值: 在这里插入图片描述

//初始化延迟函数 //当使用 OS 的时候,此函数会初始化 OS 的时钟节拍 //SYSTICK 的时钟固定为 HCLK 时钟 //SYSCLK:系统时钟频率 void delay_init(u8 SYSCLK) { #if SYSTEM_SUPPORT_OS //如果需要支持 OS. u32 reload; #endif HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); //SysTick 频率为 HCLK fac_us=SYSCLK; //不论是否使用 OS,fac_us 都需要使用 #if SYSTEM_SUPPORT_OS //如果需要支持 OS. reload=SYSCLK; //每秒钟的计数次数 单位为 K reload*=1000000/delay_ostickspersec; //根据 delay_ostickspersec 设定溢出时间 //reload 为 24 位寄存器,最大值:16777216,在 72M 下,约合 0.233s 左右 fac_ms=1000/delay_ostickspersec; //代表 OS 可以延时的最少单位 SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;//开启 SYSTICK 中断 SysTick->LOAD=reload; //每 1/OS_TICKS_PER_SEC 秒中断一次 SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启 SYSTICK #else #endif } 1.3、HAL库自带延时函数

HAL库自带延时函数,可以实现ms级别的延时。文件 stm32f1xx_hal.c 中定义。 在这里插入图片描述 可以看到这是一个弱函数,可以被重新定义,也可以直接使用。 在这里插入图片描述   HAL 库实现延时功能非常简单,首先定义了一个 32 位全局变量 uwTick,在 Systick 中断服务函数 SysTick_Handler 中通过调用 HAL_IncTick 实现uwTick 值不断增加,也就是每隔 1ms增加 1。而 HAL_Delay 函数在进入函数之后先记录当前 uwTick 的值,然后不断在循环中读取uwTick 当前值,进行减运算,得出的就是延时的毫秒数。

2、sys

  sys 文件夹内包含了 sys.c 和 sys.h 两个文件。在 sys.h 里面定义了 STM32F1 的 IO 口位操作输入读取宏定义和输出宏定义以及类型别名。 在这里插入图片描述 通过计算地址,达到位操作。 在这里插入图片描述 在这里插入图片描述 在PAout(6)=1位操作过程中,实质上是是计算GPIO 的某个 io 口对应的位带区的地址,设置了寄存器的值。

3、usart

  该文件夹下面有 usart.c 和 usarts.h 两个文件,默认串口1配置了printf 函数支持。关于串口寄存器的操作,请查看官方手册。 关于串口printf函数的其它定义方式,可以查看这篇博客,STM32 CubeIDE printf的重定向解决方法,输出小数 串口设置的一般步骤可以总结为如下几个步骤:

串口时钟使能,GPIO 时钟使能。设置引脚复用器映射:调用 GPIO_PinAFConfig 函数。GPIO 初始化设置:要设置模式为复用功能。串口参数初始化:设置波特率,字长,奇偶校验等参数。开启中断并且初始化 NVIC,使能中断(如果需要开启中断才需要这个步骤)。使能串口。编写中断处理函数:函数名格式为 USARTxIRQHandler(x 对应串口号)。

串口相关的函数和定义主要在文件 stm32f1xx_hal_uart.c 和 stm32f1xx_hal_uart.h 中,查看相关的串口函数。 在这里插入图片描述

串口参数初始化(波特率/停止位等),并使能串口。 串口初始化函数 HAL_UART_Init: HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart)

该函数只有一个入口参数 huart,为 UART_HandleTypeDef 结构体指针类型。 在这里插入图片描述 一般情况下载调用函数 HAL_UART_Init 对串口进行初始化的时候,我们只需要先设置 Instance 和 Init 两个成员变量的值。 Init 是 UART_InitTypeDef 结构体类型变量,它是用来设置串口的各个参数,包括波特率,停止位等。`

在这里插入图片描述

typedef struct { uint32_t BaudRate; //波特率 uint32_t WordLength; //字长 uint32_t StopBits; //停止位 uint32_t Parity; //奇偶校验 uint32_t Mode; //收/发模式设置 uint32_t HwFlowCtl; //硬件流设置 uint32_t OverSampling; //过采样设置 }UART_InitTypeDef

参数BaudRate 为串口波特率,它用来确定串口通信的速率。 参数 WordLength 为字长,可以设置为 8 位字长或者 9 位字长。 参数 StopBits 为停止位设置,可以设置为 1 个停止位或者 2 个停止位。 参数 Parity 设定是否需要奇偶校验,我们设定为无奇偶校验位。 参数 Mode 为串口模式,可以设置为只收模式,只发模式,或者收发模式。 参数 HwFlowCtl 为是否支持硬件流控制,我们设置为无硬件流控制。 参数OverSampling 用来设置过采样为 16 倍还是 8 倍。

函数 HAL_UART_Init 使用的一般格式为:

UART_HandleTypeDef UART1_Handler; //UART 句柄 UART1_Handler.Instance=USART1; //USART1 UART1_Handler.Init.BaudRate=115200; //波特率 UART1_Handler.Init.WordLength=UART_WORDLENGTH_8B; //字长为 8 位格式 UART1_Handler.Init.StopBits=UART_STOPBITS_1; //一个停止位 UART1_Handler.Init.Parity=UART_PARITY_NONE; //无奇偶校验位 UART1_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE; //无硬件流控 UART1_Handler.Init.Mode=UART_MODE_TX_RX; //收发模式 HAL_UART_Init(&UART1_Handler); //HAL_UART_Init()会使能 UART1

函数 HAL_UART_Init 内部会调用串口使能函数使能相应串口,所以调用了该函数之后我们就不需要重复使能串口了。HAL 库也提供了具体的串口使能 和关闭方法,具体使用方法如下:

__HAL_UART_ENABLE(handler); //使能句柄 handler 指定的串口 __HAL_UART_DISABLE(handler); //关闭句柄 handler 指定的串口

在调用的初始化函数 HAL_UART_Init 内部,会先调用 MSP 初始化回调函数进行 MCU 相关的初始化,MSP是指和MCU相关的初始化,函数为:

void HAL_UART_MspInit(UART_HandleTypeDef *huart);

HAL驱动方式的初始化流程就是:HAL_USART_Init() ------>HAL_USART_MSP_Init() 先初始化协议,再初始化MCU的引脚。在STM32的HAL驱动中MSP_Init()是做为回调,包含在PPP_Init()中的。

2)使能串口和 GPIO 口时钟 使能串口时钟和使用到的 GPIO 口时钟。串口 1 时钟和 GPIOA 时钟(串口 1 使用的是 PA9 和 PA10)。

__HAL_RCC_USART1_CLK_ENABLE(); //使能 USART1 时钟 __HAL_RCC_GPIOA_CLK_ENABLE(); //使能 GPIOA 时钟

3)GPIO 口初始化设置(速度,上下拉等)以及复用映射配置 在这里插入图片描述

4) 开启串口相关中断,配置串口中断优先级

HAL_NVIC_EnableIRQ(USART1_IRQn); //使能USART1中断通道 HAL_NVIC_SetPriority(USART1_IRQn,3,3); //抢占优先级3,子优先级3

5) 编写中断服务函数 串口 1 中断服务函数为:

void USART1_IRQHandler(void) ;

当发生中断的时候,程序就会执行中断服务函数。

6) 串口数据接收和发送 通过数据寄存器 USART_DR 来实现的,这是一个双寄存器,包 含了 TDR 和 RDR。当向该寄存器写数据的时候,串口就会自动发送,当收到数据的时候,也是存在该寄存器内。HAL 库操作 USART_DR 寄存器发送数据的函数是:

HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);

通过该函数向串口寄存器 USART_DR 写入一个数据。

HAL 库操作 USART_DR 寄存器读取串口接收到的数据的函数是:

HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);

通过该函数可以读取串口接受到的数据。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有