在HAL库底层和MAIN应用层之间建立一个BSP中间层,HAL库底层由官方提供,BSP里用于各种外设硬件的初始化和基本功能函数编写,MAIN应用层编写程序的整个控制流程。
2.BSP模块使用STM32CubeMX初始化时钟和外设
变量别名定义:
typedef signed char int8_t;
typedef signed short int int16_t;
typedef signed int int32_t;
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
#define __IO volatile
__IO的作用(两根下划线) : 为了不让编译器进行优化,即每次读取或者修改值的时候,都必须重新从内存或者寄存器中读取或者修改
(1)系统时钟a.首先用STM32CubeMX在相应的位置建立一个Source_Project文件工程,配置RCC系统时钟,选择外部高速时钟:Crystall / Ceramic Resonator (晶振)
b.配置系统时钟来源和分频系数
选择高速外部时钟设置为24Mhz,然后经过 (/3) --> (x20) -->(/2),然后选择PLLCLK时钟源,最终得到SYSCLK,时钟频率80Mhz
(2)Key 和 LEDKey原理图:
由于按键连接了一个上拉电阻,所以默认高电平,当按下按键时,电路闭合,IO口电平从高电平到低电平,检测IO口电平的变化就是判断按键是否按下的依据。GPIO设置为浮空输入模式(默认输入值不确定,读取值唯一),并且不带上下拉
STM32CubeMX配置:
按键源码(必背要考!!!)
// 按键扫描
uint8_t Key_Scan(void)
{
uint8_t val=0;
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==0)
val = 1;
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==0)
val = 2;
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)==0)
val = 3;
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==0)
val = 4;
return val;
}
// 按键处理函数
// 在main中声明的全局变量
__IO uint32_t uwTick_Key_Set_Point = 0; //控制key_Pro执行速度
//按键变量
uint8_t ucKey_Val, unKey_Down, ucKey_Up, ucKey_Old;
//按键扫描子函数
void key_proc(void)
{
if(uwTick - key_uwTickChannel == HAL_TIM_ACTIVE_CHANNEL_2) // 通道2
{
PWM2_D_Count = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2)+1;
}
}
}
普通输入捕获:定时器通道2
采用定时器2的通道2作为信号的输入,必须将通道2设置为直接捕获模式并且上升沿触发,通道1间接捕获模式并且下降沿触发。注意:使能自动预载值。
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM2)
{
if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_2)
{
period_val= HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_2)+1; // arr值
duty_val = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_1)+1; // compare值
if(period_val)
{
__HAL_TIM_SET_COUNTER(&htim2,0); // 清0,为下一次捕获做准备
freq = 1000000/period_val; // 频率
duty = duty_val/period_val*100; // 占空比
}
}
HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_2);
HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
}
}
这里period_val,duty_val,freq,duty都建议采用float,以减小误差。
(9)输出比较模式(方波) 电平翻转模式输出通道有8种模式,这里采用的是比较输出模式(2),即电平翻转模式。当匹配时,引脚状态翻转。假设CCR寄存器里面的值设定为100 (注意这个不是控制波形的频率,只是一个初始值,波形频率的设置在中断里面设置),那么计数器从0开始计数,每隔100次,电平将会翻转一次,并且通过中断设置下次比较值,改变波形的频率( __HAL_TIM_SET_COMPARE(htim,TIM_CHANNEL_1,(__HAL_TIM_GetCounter(htim)+500)); //这里最好初始脉冲值设置为500,1Khz),这样就通过设定CCR寄存器里面的值就可以输出不同频率的方波
系统时钟经过分频得到1M作为计数时钟,计一个数需要t=1e-6s, 波的频率 1/[2*( 100*t)] =5khz,__HAL_TIM_SET_COMPARE(htim,TIM_CHANNEL_1,(__HAL_TIM_GetCounter(htim)+100));
STM32CubeMX配置: 设置系统时钟为1Mhz, 频率设置:Pulse脉冲值,一定要使能auto-reload preload,因为每一次中断里面要更改比较寄存器CCR的值
//*输出方波PA2引脚
HAL_TIM_OC_Start_IT(&htim15,TIM_CHANNEL_1);
// 方波输出中断回调函数
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM15) // 定时器判断
{
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) // 通道1
{
// 每次中断计数器的值加100 Pulse = 100
__HAL_TIM_SET_COMPARE(htim, TIM_CHANNEL_1, (__HAL_TIM_GetCounter(htim)+100)); // 5khz
}
else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2) // 通道2
{
// 每次中断计数器的值加500 Pulse = 500
__HAL_TIM_SET_COMPARE(htim, TIM_CHANNEL_2, (__HAL_TIM_GetCounter(htim)+500)); // 1khz
}
}
}
(10)输出比较模式(PWM) PWM模式
采用输出比较模式选择PWM模式,PWM(脉冲宽度调制)模式可以产生一个由TIMx_ARR寄存器确定频率(周期)、由TIMx_CCRx寄存器确定占空比的PWM信号
在递增计数模式下,CNT从 0 开始计数到ARR并生成计数器上溢事.,假设 ARR=999,CCR=300, CNT 从 0 开始计数,当 CNT
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?