基于HAL库的STM32嵌入式学习记录(持续更新中,若内容有误欢迎评论指正)

本文主要是介绍基于HAL库的STM32嵌入式学习记录(持续更新中,若内容有误欢迎评论指正),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

KEY(按键触发)


扫描触发

void KEY_work(void)
{if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == RESET)//检测按键电平变化{HAL_Delay(50);//延时,避免抖动if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == RESET)//再次检测电平{HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_1);//翻转PA0电平}}
}

中断触发

选择IO口中断模式

在STM32单片机中针对IO口中断总共有十五个,其中GPIO_EXIT_0中断对应每组IO口的0接口,与此对应的是PA0和PB0的中断不能同时开启

选择触发方式(上升沿、下降沿、上升或下降沿)

 重写中断回调虚函数     HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)

在IO口中断中传递参数uint16_t GPIO_PinGPIO_PIN_X,当开启多个IO口中断时为区分触发中断的IO口,重写回调函数时要进行判断

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{if(GPIO_Pin == GPIO_PIN_0)//判断触发串口(如开启中断串口不止一个则采用不同的if判断条件){HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_2);//翻转PA2串口电平while(HAL_GPIO_ReadPin(GPIOB,GPIO_0 == 0));//恢复高电平后退出(针对下降沿触发,避免多次触发中断,可忽略)}
}

点灯!!!


点灯原理:给led灯对应IO口输出相应电平

以蓝桥杯嵌入式比赛板(STM32G431RBT6)为例:

LED灯非引脚段为高电平,当引脚输出低电平时LED二极管接通发光。IO口输出间与LED以锁存器连接 ,其中引脚PD2输出高电平时使能:Q=D,通过控制锁存器的使能与否可以实现控制LED灯的同时实现引脚的复用。

void LED_work(void)
{HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_RESET);//PC2输出低电平,灯亮HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);//锁存器使能(使能最好在输出赋值之后)HAL_Delay(5);//延时(视情况可不加)HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);//寄存器输出锁存
}

定时器(TIM)


STM32定时器基础

时钟树设置(时钟频率):

 PS:此方法对于大部分情况已经完全够用。想深入学习stm32时钟树的知识建议移步其他大佬博客,这里不再赘述。

定时器频率计算:定时频率=时钟频率/(预分频器(Prescaler)*计数周期(Counter Period)预分频器)

预分频器与计数周期设置

 预分频器和计数周期都含0,在设置时应减一。以上截图中设置的定时器频率为80000000/(80*1000)=1Khz

定时触发:

在设置好定时频率后,我们可以让单片机间隔一段时间重复执行某些任务。例如每隔0.1秒翻转LED灯电平实现闪灯操作:

使能TIM4中断
HAL_TIM_Base_Start_IT(&htim4);//主函数中开启定时器4中断
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//重写中断回调虚函数
{if(htim->Instance == TIM4)//判断触发定时器(在有多个不同中断触发时间的任务执行时在同一个回调函数里编写,编写时注意改变if判断条件){HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_8);//翻转电平HAL_GPIO_WritePin(GPIOD,GPIO_PIN_10,GPIO_PIN_RESET);//使能锁存器HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);//关闭锁存器(避免引脚复用干扰)}
}

PWM波输出 :

占空比:一个脉冲时间内,高电平占一个脉冲周期的时间。

占空比计算:脉冲数(Pulse)/计数周期(Counter Period)*100%

AD/DA模数转换(引脚输出电压获取)

cubemx配置:

转换函数:

HAL_ADC_Start(&hadc1);//开启ADC通道
if(HAL_ADC_PollForConversion(&hadc2,10) == HAL_OK)//检测是否有数据输入
{adc = HAL_ADC_GetValue(&hadc2);//获取数据sprintf(&adc_im,"       V2=%1.2f          ",adc*3.3/4096);//显示数据(ADC分辨率为十二位,即4096,而引脚输出电压最高为3.3V,所以需要进行变换)LCD_DisplayStringLine(Line6,(uint8_t *)&adc_im);//LCD显示
}

输入捕获

 cubemx配置:

捕获函数:

HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_2);    //开启相应通道IC捕获中断//重写捕获中断函数
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{if(htim->Instance == TIM3)                //确认信号输入通道{count = HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_2);//获取计数值__HAL_TIM_SetCounter(&htim3,0);       //计数值清零f = (80000000/80)/(count+2);          //计算频率HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_2);        //重新开启IC捕获中断}
}

 I2C通讯


I2C通讯原理:

cubemx配置:

由于蓝桥杯竞赛板中采用的是软件I2C,所以这里复用这两个引脚为输出态即可 。

 收发函数:

void IIC_send(unsigned char text,unsigned char locad)//发送内容|储存地址(这里储存地址为从机寄存器地址,一般情况下为数字)
{I2CStart();//开启I2CI2CSendByte(0xa0);//发送从机地址和写数据请求I2CWaitAck();//等待响应I2CSendByte(locad);//发送从机寄存器储存地址I2CWaitAck();//等待响应I2CSendByte(text);//发送存储内容I2CWaitAck();//等待响应I2CStop();//关闭I2C
}//发送函数
//一般情况下发送内容限定为八个字节,所以发送大容量内容时要将数据截多段八字节内容,可采用左移符号'<<'和右移符号'>>'结合实现字节截断
unsigned char IIC_receive(unsigned char locad)//接收数据所在的寄存器地址
{unsigned text;//无符号型变量I2CStart();//开启I2CI2CSendByte(0xa0);//指定从机和发送写数据请求I2CWaitAck();//等待响应I2CSendByte(locad);//发送从机寄存器地址I2CWaitAck();//等待响应I2CStop();//关闭I2CI2CStart();//开启I2CI2CSendByte(0xa1);//发送从机地址和读数据请求I2CWaitAck();//等待响应text = I2CReceiveByte();//接收并储存数据I2CWaitAck();//等待响应I2CStop();//关闭I2Creturn text;//返回接收数据
}//接收函数

UART串口收发 

cubemx配置:

 

 串口发送:

char Rx[7];            //要发送的数据
HAL_UART_Transmit(&huart1,(uint8_t *)Rx,sizeof(Rx),50);
//参数意义分别为:通道编号,预发送数据,发送长度,超时重传

串口接收:

uint8_t rx,r_len;
char Rx[7];HAL_UART_Receive_IT(&huart1,&rx,1);    //开启接收中断//重写接收中断服务函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{if(huart->Instance == USART1)                 //确定中断源{Rx[r_len ++] = rx;                        //接收数据写入HAL_UART_Receive_IT(&huart1,&rx,1);       //重新开启接收中断if(r_len == 7){HAL_UART_Transmit(&huart1,(uint8_t *)Rx,sizeof(Rx),50);r_len = 0;                            //接收位置复位,发送接收的数据}}
}

这篇关于基于HAL库的STM32嵌入式学习记录(持续更新中,若内容有误欢迎评论指正)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/804199

相关文章

使用docker搭建嵌入式Linux开发环境

《使用docker搭建嵌入式Linux开发环境》本文主要介绍了使用docker搭建嵌入式Linux开发环境,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录1、前言2、安装docker3、编写容器管理脚本4、创建容器1、前言在日常开发全志、rk等不同

Java使用正则提取字符串中的内容的详细步骤

《Java使用正则提取字符串中的内容的详细步骤》:本文主要介绍Java中使用正则表达式提取字符串内容的方法,通过Pattern和Matcher类实现,涵盖编译正则、查找匹配、分组捕获、数字与邮箱提... 目录1. 基础流程2. 关键方法说明3. 常见场景示例场景1:提取所有数字场景2:提取邮箱地址4. 高级

Unity新手入门学习殿堂级知识详细讲解(图文)

《Unity新手入门学习殿堂级知识详细讲解(图文)》Unity是一款跨平台游戏引擎,支持2D/3D及VR/AR开发,核心功能模块包括图形、音频、物理等,通过可视化编辑器与脚本扩展实现开发,项目结构含A... 目录入门概述什么是 UnityUnity引擎基础认知编辑器核心操作Unity 编辑器项目模式分类工程

C#高效实现Word文档内容查找与替换的6种方法

《C#高效实现Word文档内容查找与替换的6种方法》在日常文档处理工作中,尤其是面对大型Word文档时,手动查找、替换文本往往既耗时又容易出错,本文整理了C#查找与替换Word内容的6种方法,大家可以... 目录环境准备方法一:查找文本并替换为新文本方法二:使用正则表达式查找并替换文本方法三:将文本替换为图

MySQL 数据库表操作完全指南:创建、读取、更新与删除实战

《MySQL数据库表操作完全指南:创建、读取、更新与删除实战》本文系统讲解MySQL表的增删查改(CURD)操作,涵盖创建、更新、查询、删除及插入查询结果,也是贯穿各类项目开发全流程的基础数据交互原... 目录mysql系列前言一、Create(创建)并插入数据1.1 单行数据 + 全列插入1.2 多行数据

linux安装、更新、卸载anaconda实践

《linux安装、更新、卸载anaconda实践》Anaconda是基于conda的科学计算环境,集成1400+包及依赖,安装需下载脚本、接受协议、设置路径、配置环境变量,更新与卸载通过conda命令... 目录随意找一个目录下载安装脚本检查许可证协议,ENTER就可以安装完毕之后激活anaconda安装更

Python学习笔记之getattr和hasattr用法示例详解

《Python学习笔记之getattr和hasattr用法示例详解》在Python中,hasattr()、getattr()和setattr()是一组内置函数,用于对对象的属性进行操作和查询,这篇文章... 目录1.getattr用法详解1.1 基本作用1.2 示例1.3 原理2.hasattr用法详解2.

Linux从文件中提取特定内容的实用技巧分享

《Linux从文件中提取特定内容的实用技巧分享》在日常数据处理和配置文件管理中,我们经常需要从大型文件中提取特定内容,本文介绍的提取特定行技术正是这些高级操作的基础,以提取含有1的简单需求为例,我们可... 目录引言1、方法一:使用 grep 命令1.1 grep 命令基础1.2 命令详解1.3 高级用法2

基于Spring Boot 的小区人脸识别与出入记录管理系统功能

《基于SpringBoot的小区人脸识别与出入记录管理系统功能》文章介绍基于SpringBoot框架与百度AI人脸识别API的小区出入管理系统,实现自动识别、记录及查询功能,涵盖技术选型、数据模型... 目录系统功能概述技术栈选择核心依赖配置数据模型设计出入记录实体类出入记录查询表单出入记录 VO 类(用于

Nginx进行平滑升级的实战指南(不中断服务版本更新)

《Nginx进行平滑升级的实战指南(不中断服务版本更新)》Nginx的平滑升级(也称为热升级)是一种在不停止服务的情况下更新Nginx版本或添加模块的方法,这种升级方式确保了服务的高可用性,避免了因升... 目录一.下载并编译新版Nginx1.下载解压2.编译二.替换可执行文件,并平滑升级1.替换可执行文件