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

相关文章

如何解决Pycharm编辑内容时有光标的问题

《如何解决Pycharm编辑内容时有光标的问题》文章介绍了如何在PyCharm中配置VimEmulator插件,包括检查插件是否已安装、下载插件以及安装IdeaVim插件的步骤... 目录Pycharm编辑内容时有光标1.如果Vim Emulator前面有对勾2.www.chinasem.cn如果tools工

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

关于Spring @Bean 相同加载顺序不同结果不同的问题记录

《关于Spring@Bean相同加载顺序不同结果不同的问题记录》本文主要探讨了在Spring5.1.3.RELEASE版本下,当有两个全注解类定义相同类型的Bean时,由于加载顺序不同,最终生成的... 目录问题说明测试输出1测试输出2@Bean注解的BeanDefiChina编程nition加入时机总结问题说明

C#比较两个List集合内容是否相同的几种方法

《C#比较两个List集合内容是否相同的几种方法》本文详细介绍了在C#中比较两个List集合内容是否相同的方法,包括非自定义类和自定义类的元素比较,对于非自定义类,可以使用SequenceEqual、... 目录 一、非自定义类的元素比较1. 使用 SequenceEqual 方法(顺序和内容都相等)2.

将sqlserver数据迁移到mysql的详细步骤记录

《将sqlserver数据迁移到mysql的详细步骤记录》:本文主要介绍将SQLServer数据迁移到MySQL的步骤,包括导出数据、转换数据格式和导入数据,通过示例和工具说明,帮助大家顺利完成... 目录前言一、导出SQL Server 数据二、转换数据格式为mysql兼容格式三、导入数据到MySQL数据

关于rpc长连接与短连接的思考记录

《关于rpc长连接与短连接的思考记录》文章总结了RPC项目中长连接和短连接的处理方式,包括RPC和HTTP的长连接与短连接的区别、TCP的保活机制、客户端与服务器的连接模式及其利弊分析,文章强调了在实... 目录rpc项目中的长连接与短连接的思考什么是rpc项目中的长连接和短连接与tcp和http的长连接短

Oracle查询优化之高效实现仅查询前10条记录的方法与实践

《Oracle查询优化之高效实现仅查询前10条记录的方法与实践》:本文主要介绍Oracle查询优化之高效实现仅查询前10条记录的相关资料,包括使用ROWNUM、ROW_NUMBER()函数、FET... 目录1. 使用 ROWNUM 查询2. 使用 ROW_NUMBER() 函数3. 使用 FETCH FI

Python MySQL如何通过Binlog获取变更记录恢复数据

《PythonMySQL如何通过Binlog获取变更记录恢复数据》本文介绍了如何使用Python和pymysqlreplication库通过MySQL的二进制日志(Binlog)获取数据库的变更记录... 目录python mysql通过Binlog获取变更记录恢复数据1.安装pymysqlreplicat

Redis缓存问题与缓存更新机制详解

《Redis缓存问题与缓存更新机制详解》本文主要介绍了缓存问题及其解决方案,包括缓存穿透、缓存击穿、缓存雪崩等问题的成因以及相应的预防和解决方法,同时,还详细探讨了缓存更新机制,包括不同情况下的缓存更... 目录一、缓存问题1.1 缓存穿透1.1.1 问题来源1.1.2 解决方案1.2 缓存击穿1.2.1

Linux Mint Xia 22.1重磅发布: 重要更新一览

《LinuxMintXia22.1重磅发布:重要更新一览》Beta版LinuxMint“Xia”22.1发布,新版本基于Ubuntu24.04,内核版本为Linux6.8,这... linux Mint 22.1「Xia」正式发布啦!这次更新带来了诸多优化和改进,进一步巩固了 Mint 在 Linux 桌面