基于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

相关文章

Python将博客内容html导出为Markdown格式

《Python将博客内容html导出为Markdown格式》Python将博客内容html导出为Markdown格式,通过博客url地址抓取文章,分析并提取出文章标题和内容,将内容构建成html,再转... 目录一、为什么要搞?二、准备如何搞?三、说搞咱就搞!抓取文章提取内容构建html转存markdown

Python获取中国节假日数据记录入JSON文件

《Python获取中国节假日数据记录入JSON文件》项目系统内置的日历应用为了提升用户体验,特别设置了在调休日期显示“休”的UI图标功能,那么问题是这些调休数据从哪里来呢?我尝试一种更为智能的方法:P... 目录节假日数据获取存入jsON文件节假日数据读取封装完整代码项目系统内置的日历应用为了提升用户体验,

Spring Boot 配置文件之类型、加载顺序与最佳实践记录

《SpringBoot配置文件之类型、加载顺序与最佳实践记录》SpringBoot的配置文件是灵活且强大的工具,通过合理的配置管理,可以让应用开发和部署更加高效,无论是简单的属性配置,还是复杂... 目录Spring Boot 配置文件详解一、Spring Boot 配置文件类型1.1 applicatio

MySQL INSERT语句实现当记录不存在时插入的几种方法

《MySQLINSERT语句实现当记录不存在时插入的几种方法》MySQL的INSERT语句是用于向数据库表中插入新记录的关键命令,下面:本文主要介绍MySQLINSERT语句实现当记录不存在时... 目录使用 INSERT IGNORE使用 ON DUPLICATE KEY UPDATE使用 REPLACE

Python 中的异步与同步深度解析(实践记录)

《Python中的异步与同步深度解析(实践记录)》在Python编程世界里,异步和同步的概念是理解程序执行流程和性能优化的关键,这篇文章将带你深入了解它们的差异,以及阻塞和非阻塞的特性,同时通过实际... 目录python中的异步与同步:深度解析与实践异步与同步的定义异步同步阻塞与非阻塞的概念阻塞非阻塞同步

Python Dash框架在数据可视化仪表板中的应用与实践记录

《PythonDash框架在数据可视化仪表板中的应用与实践记录》Python的PlotlyDash库提供了一种简便且强大的方式来构建和展示互动式数据仪表板,本篇文章将深入探讨如何使用Dash设计一... 目录python Dash框架在数据可视化仪表板中的应用与实践1. 什么是Plotly Dash?1.1

MySQL新增字段后Java实体未更新的潜在问题与解决方案

《MySQL新增字段后Java实体未更新的潜在问题与解决方案》在Java+MySQL的开发中,我们通常使用ORM框架来映射数据库表与Java对象,但有时候,数据库表结构变更(如新增字段)后,开发人员可... 目录引言1. 问题背景:数据库与 Java 实体不同步1.1 常见场景1.2 示例代码2. 不同操作

使用Python实现获取网页指定内容

《使用Python实现获取网页指定内容》在当今互联网时代,网页数据抓取是一项非常重要的技能,本文将带你从零开始学习如何使用Python获取网页中的指定内容,希望对大家有所帮助... 目录引言1. 网页抓取的基本概念2. python中的网页抓取库3. 安装必要的库4. 发送HTTP请求并获取网页内容5. 解

Python实现常用文本内容提取

《Python实现常用文本内容提取》在日常工作和学习中,我们经常需要从PDF、Word文档中提取文本,本文将介绍如何使用Python编写一个文本内容提取工具,有需要的小伙伴可以参考下... 目录一、引言二、文本内容提取的原理三、文本内容提取的设计四、文本内容提取的实现五、完整代码示例一、引言在日常工作和学

一文详解SQL Server如何跟踪自动统计信息更新

《一文详解SQLServer如何跟踪自动统计信息更新》SQLServer数据库中,我们都清楚统计信息对于优化器来说非常重要,所以本文就来和大家简单聊一聊SQLServer如何跟踪自动统计信息更新吧... SQL Server数据库中,我们都清楚统计信息对于优化器来说非常重要。一般情况下,我们会开启"自动更新