通过学习STM32CubeMX软件,掌握配置各个部件的基本方法;了解外部中断,定时器中断,PWM波产生等功能的原理,编写程序代码,实现相应的功能。
程序预期结果:
LED初始设置间隔2秒闪烁一次,每按下一次按键,间隔时间减少0.5秒;
当间隔时间减少为0后,LED闪烁改变为呼吸灯,BEEP蜂鸣器开始播放音乐小星星。
了解基本功能
STM32CubeMX可以生成硬件的初始化代码,可视化的界面使配置更便捷。
Cube安装及配置
安装Java环境 ->> 安装STM32CubeMX软件 ->> 安装STM32CubeMX库文件
安装Java环境
官方网站下载,STM32CubeMX软件运行需要java环境1.8.0_45(64-bit)以上
安装STM32CubeMX软件
官网下载链接https://www.st.com/content/st_com/en/products/development-tools/software-development-tools/stm32-software-development-tools/stm32-configurators-and-code-generators/stm32cubemx.html
选择合适版本的软件进行下载并安装
点击get software – > 选择版本 – > 点击get software – > 提示注册账号,开始下载
安装库文件
(依据芯片型号选择相应库文件)
方法一 在线安装
打开STM32CubeMX软件 – > Help – > Manage embedded software packages – > 在弹出的列表中,勾选需要的库文件版本 – > 点击下侧 " Install Now " – > 开始下载库,直至安装成功
方法二 导入本地包
提前在官网下载好库文件(软件与库在同一网址下)
打开STM32CubeMX软件 – > Help – > Manage embedded software packages – > 在弹出的窗口中,点击左下角 “From Local” – > 在弹出的窗口中找到已经下载好的库文件 – > 选中并点击 “Open” – > 开始解压文件包,直至解压成功
首先使用TIM3定时器,初始时间间隔为2s,在中断服务函数中点亮一次LED,完成闪烁
使用WK_UP按键EXTI0外部中断,在中断服务函数中判断时间间隔是否为0,若不为0,则修改TIM3定时器装载的值,时间间隔减少0.5s;若为0,修改标识PWM_OK的值为1,表示主程序可以进入PWM波控制部分
主函数不断检测标识PWM_OK的值,当PWM_OK非零,进入PWM波部分,先将TIM13,TIM14初始化为PWM模式,关闭TIM3,之后不断修改PWM的占空比,实现LED呼吸灯和BEEP发出不同音调
新建工程 – > 选择相应的STM32芯片
High Speed Clock 选为 Crystal/Ceramic Resonator
Low Speed Clock 选为 Crystal/Ceramic Resonator
Project: 设置工程名及路径
Code Generator: 勾选Generated peripheral initialization as a pair of ‘.c/.h’ files per peripheral
生成代码
点击右上角 “ GENERATE CODE ”
中断程序简述
中断服务函数–>中断处理函数–>中断回调函数
中断服务函数 :MDK中已经确定,发生中断后执行
中断处理函数 :由中断服务函数调用;作用,判断状态,清除中断标识位,然后调用中断回调函数
中断回调函数 :由用户编写程序,即中断后用户希望执行的操作
用户只需修改中断回调函数中的内容即可
利用定时器中断,定时器溢出后触发中断,执行中断服务函数
TIM3初始值设置为2s溢出触发中断
修改定时器中断回调函数的内容
程序源码:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) //TIM3
{
if (htim->Instance == htim3.Instance)
{
HAL_GPIO_WritePin(GPIOF,GPIO_PIN_9,GPIO_PIN_RESET);//LED亮
HAL_Delay(100);//持续点亮
HAL_GPIO_WritePin(GPIOF,GPIO_PIN_9,GPIO_PIN_SET);//LED灭,闪烁完成
}
}
外部中断简述
外部中断的0~15线,每条线对应一个EXTI寄存器,每个寄存器对应9个IO口
0线–>EXTI0–>PA0,PB0,PC0,PD0,PE0,PF0,PG0,PH0,PI0
1线–>EXTI1–>PA1,PB1,PC1,PD1,PE1,PF1,PG1,PH1,PI1
…
15线–>EXTI15–>PA15,PB15,PC15,PD15,PE15,PF15,PG15,PH15
每条线每次只能连接一个IO口
按下按键WK_UP,执行中断函数
如果定时器的时间大于0.5s,那么减少定时器的时间0.5s,并重新初始化定时器
否则将PWM_OK标志设置为1,主函数可以进入PWM程序部分
程序源码
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
HAL_Delay(100);
if(htim3.Init.Period >5000)//判断定时器时间是否大于0.5s
{
htim3.Init.Period =htim3.Init.Period-2500 ;//重新设置定时器时间
HAL_TIM_Base_Init(&htim3);//重新初始化TIM3
HAL_TIM_Base_Start_IT(&htim3);//启动TIM3
}
else
{
PWM_OK=1;//PWM_OK 1标志main()可以执行PWM程序
}
HAL_Delay(100);
}
PWM波重要参数
设置PWM波输出
将TIM14的PWM波输出到PF9,对PF9进行初始化
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF9_TIM14;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
通过修改TIM14的PWM波的占空比,改变输出电压,从而改变LED的发光亮度
程序源码
void user_pwm_setvalue(uint16_t value)//TIM14_PWM占空比 设置函数
{
TIM_OC_InitTypeDef sConfigOC;//定义结构体变量,PWM初始化时使用
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = value;//将传入的数据设置为PWM新的占空比
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
HAL_TIM_PWM_ConfigChannel(&htim14, &sConfigOC, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim14, TIM_CHANNEL_1);
}
通过逐渐改变PWM的占空比,实现LED亮度渐变
程序源码
//使用pwm_value step两个变量
//在main()函数while循环中,令pwm_value在0~300之间不断变化
if(pwm_value == 0) step = 10;
// pwm_value到达最小值,step设为正值,使pwm_value增加
if(pwm_value == 300) step = -10;
// pwm_value到达最大值,step设为负值,使pwm_value减少
pwm_value += step;//修改pwm_value值
user_pwm_setvalue(pwm_value);
// 将逐渐变化的pwm_value值传入PWM占空比设置函数,逐渐改变PWM占空比
HAL_Delay(100);
TIM13_PWM控制蜂鸣器的声音强度
用7个不同的占空比控制PWM波,分别产生不同强度的声音,对应Do,Re,Mi,Fa,So,La,Xi,7种声音
程序源码
#define Do 6
#define Re 9
#define Mi 11
#define Fa 13
#define So 15
#define La 19
#define Xi 20
void user_pwm_time13(uint16_t tone)//TIM13_PWM占空比 设置函数
{
TIM_OC_InitTypeDef sConfigOC = {
0};
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = tone;//将传入的数据设置为新的占空比
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
HAL_TIM_PWM_ConfigChannel(&htim13, &sConfigOC, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim13, TIM_CHANNEL_1);
}
变量说明
使用静态变量PWM_OK作为PWM开始标志
PWM_OK=0,不能开始PWM输出
PWM_OK=1,可以开始PWM输出
使用变量start标志表示TIM13,TIM14是否已经初始化
Start=0,未经过初始化
Start=1,已经初始化
使用二维数组Tone记录音乐曲谱
static int PWM_OK=0;
//使用静态变量PWM_OK作为PWM开始标志
//PWM_OK=0,不能开始PWM输出
//PWM_OK=1,可以开始PWM输出
int main(void)
{
void user_pwm_setvalue(uint16_t value);//声明TIM14_PWM占空比 设置函数
uint16_t pwm_value=0;//占空比变化所用变量
uint16_t step=0;
uint16_t start=0;
//使用变量start标志表示TIM13,TIM14是否已经初始化
//Start=0,未经过初始化
//Start=1,已经初始化
uint16_t i,j,k;
//使用二维数组Tone记录音乐曲谱
uint16_t Tone[6][7]={
{
Do,Do,So,So,La,La,So},
{
Fa,Fa,Mi,Mi,Re,Re,Do},
{
So,So,Fa,Fa,Mi,Mi,Re},
{
So,So,Fa,Fa,Mi,Mi,Re},
{
Do,Do,So,So,La,La,So},
{
Fa,Fa,Mi,Mi,Re,Re,Do}
};
void user_pwm_time13(uint16_t tone); //声明TIM13_PWM占空比 设置函数
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM3_Init();
HAL_TIM_Base_Start_IT(&htim3);
while (1)
{
if(PWM_OK)
//PWM_OK=0,一直执行判断PWM_OK的值
//PWM_OK=1,开始执行以下语句,产生PWM波
{
if(start==0)
//Start=0,未经过初始化,执行定时器初始化程序
//Start=1,已经初始化,跳过初始化程序
{
HAL_TIM_Base_DeInit(&htim3);
MX_TIM14_Init();
MX_TIM13_Init();
start=1;
}
HAL_TIM_PWM_Start(&htim14, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim13, TIM_CHANNEL_1);
for(i=0;i<6;i++)//一次循环,播放整首乐曲
{
for(j=0;j<7;j++)//一次循环,播放一个小节乐谱
{
for(k=0;k<5;k++)//同一音调延续五拍
{
user_pwm_time13(Tone[i][j]);//产生对应的音调
if(pwm_value == 0) step = 10;//呼吸灯
if(pwm_value == 300) step = -10;
pwm_value += step;
user_pwm_setvalue(pwm_value);
HAL_Delay(100);
}
for(k=0;k<1;k++)//每个音调结束后,暂停一拍
{
user_pwm_time13(0);//蜂鸣器停止发声
if(pwm_value == 0) step = 10;//呼吸灯继续
if(pwm_value == 300) step = -10;
pwm_value += step;
user_pwm_setvalue(pwm_value);
HAL_Delay(100);
}
}
for(k=0;k<2;k++)//每一小节播放完成后,暂停两拍
{
user_pwm_time13(0);//蜂鸣器停止发声
if(pwm_value == 0) step = 10;//呼吸灯继续
if(pwm_value == 300) step = -10;
pwm_value += step;
user_pwm_setvalue(pwm_value);
HAL_Delay(100);
}
}
}
}
}
LED初始设置间隔2秒闪烁一次,每按下一次按键,间隔时间减少0.5秒;
当间隔时间减少为0后,LED闪烁改变为呼吸灯,BEEP蜂鸣器开始播放音乐小星星。