STM32CubeMX——LED定时闪烁和输出PWM波

简介

通过学习STM32CubeMX软件,掌握配置各个部件的基本方法;了解外部中断,定时器中断,PWM波产生等功能的原理,编写程序代码,实现相应的功能。
程序预期结果:
LED初始设置间隔2秒闪烁一次,每按下一次按键,间隔时间减少0.5秒;
当间隔时间减少为0后,LED闪烁改变为呼吸灯,BEEP蜂鸣器开始播放音乐小星星。

STM32CubeMX前期准备

了解基本功能
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发出不同音调

各部分简述

  • STM32CubeMX配置部分: 利用STM32CubeMX软件完成各个硬件的初始化工作
  • 定时闪烁部分: 利用TIM3定时器控制LED实现定时闪烁
  • 外部中断部分: 利用EXTI0外部中断实现WK_UP按键功能
  • 呼吸灯部分: 利用TIM14控制输出PWM波,实现LED呼吸灯
  • 音乐部分: 利用TIM13控制输出PWM波,实现BEEP发出不同音调

详细设计说明

STM32CubeMX配置部分

新建工程 – > 选择相应的STM32芯片

RCC设置

High Speed Clock 选为 Crystal/Ceramic Resonator
Low Speed Clock 选为 Crystal/Ceramic Resonator
RCC设置

Clock Configuration

修改HCLK为168MHz
Clock配置

Project Manage

Project: 设置工程名及路径
Code Generator: 勾选Generated peripheral initialization as a pair of ‘.c/.h’ files per peripheral
Generate ch files

GPIO设置

  • PA0 WK_UP
    外部中断
    下拉
    PA0-GPIO

  • PF9 LED
    普通输出
    PF9-GPIO

  • PF8 BEEP
    TIM13_CH1输出PWM波
    PF9-GPIO

Timers设置

  • TIM3
    接在APB1时钟线上,APB1频率84MHz
    分频8400,TIM3频率10000Hz
    重载数值,20000
    每2s触发一次中断
    TIM3

  • TIM14
    通道1产生PWM波,
    分频8400,10000Hz
    重载数值,200
    PWM波周期0.02s,即20ms
    TIM14

  • TIM13
    通道1输出PWM波
    分频840,频率100KHz
    重装数值,20
    PWM波周期,0.0002s,0.2ms
    TIM13

NVIC设置

使能EXIT0外部中断
使能TIM3定时器中断
NVIC

生成代码
点击右上角 “ 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口
EXTI映射图

外部中断服务函数

按下按键WK_UP,执行中断函数
如果定时器的时间大于0.5s,那么减少定时器的时间0.5s,并重新初始化定时器
否则将PWM_OK标志设置为1,主函数可以进入PWM程序部分
interrupt
程序源码

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占空比 设置函数

通过修改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占空比逐渐变化

通过逐渐改变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

TIM13_PWM占空比 设置函数

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);
}

主程序main()函数

变量说明

  • 使用静态变量PWM_OK作为PWM开始标志
    PWM_OK=0,不能开始PWM输出
    PWM_OK=1,可以开始PWM输出

  • 使用变量start标志表示TIM13,TIM14是否已经初始化
    Start=0,未经过初始化
    Start=1,已经初始化

  • 使用二维数组Tone记录音乐曲谱

MAIN函数
程序源码

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蜂鸣器开始播放音乐小星星。

  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值