【STM32学习】PWM学习,(二)驱动LED呼吸灯

        上文学习了PWM的基本概述,和PWM的各种参数,本文 学习使用PWM信号去驱动LED实现呼吸灯的效果。

 1、PWM驱动LED呼吸灯

1.1介绍

目标:单片机输出一个PWM信号,驱动LED呼吸亮灭。PWM占空比高,则LED更亮;PWM占空比低,则LED更暗;

如下图为实物连接图,在PA0引脚输出PWM信号。

1.2程序运行思路分析:

1)打开时钟(TIM和GPIO的时钟)

2)初始化GPIO(指定某个引脚输出PWM信号)

3)初始化定时器时基单元,(为了设置定时器参数,如频率,计数模式,ARR自动重装值,PSC预分频器等)

4)初始化定时器输出比较,(配置某个定时器的某个通道,模式,极性,使能,和CCR捕获比较寄存器)

5)开启定时器

6)函数调用

1.3程序

下图的程序为输出50%占空比PWM 信号。使用时,直接在主函数,调用PWM_Init ();

void PWM_Init (void)
{
	RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM2,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;//
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式
	TIM_TimeBaseInitStruct.TIM_Period = 100-1;      //ARR
	TIM_TimeBaseInitStruct.TIM_Prescaler = 720-1;    //PSC
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);	
	
	TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_OCStructInit(&TIM_OCInitStructure);
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_Pulse = 50;   //CCR   ,ARR,PSC,CCR,共同设置PWM的占空比
	TIM_OC1Init(TIM2,&TIM_OCInitStructure);
	
	TIM_Cmd(TIM1,ENABLE);
}

若要设置不断更改PWM占空比,则需要调用更改CCR的函数TIM_SetCompare1,

然后再在主函数中调用函数,写入自己想要的值,

如:在主函数中调用,功能为,更改CCR 的值从小变大,再从大变小,不断循环。

运行LED效果:变亮变暗不断循环,实现呼吸灯效果

void PWM_SetCompare(uint16_t Compare1)
{
	TIM_SetCompare1(TIM2,Compare1);
}

//以上是调用的函数
//下面可以在主函数中调用,功能为,更改CCR 的值从小变大,再从大变小,不断循环
while(1)
	{
		
		for (i=0;i <= 100;i++)
		{
			PWM_SetCompare(i);
			Delay_ms(10);
		}
		for (i=0;i <= 100;i++)
		{
			PWM_SetCompare(100-i);
			Delay_ms(10);
		}
		
	}

2、程序功能解释

2.1、PWM输出流程图

系统时钟频率出来,经过预分频器和自动重装器,可输出固定频率的信号,

设计计数模式,如图中的向上计数模式,从0计数到ARR,再自动重装为0,不断循环。

当经过比较器的时候,比较计数值CNT与CCR的值,选择比较的模式(PWM1和PWM2),如PWM1模式:CNT<CCR,则输出高电平。

如此经过比较器后,就输出高低电平不同宽度的PWM波形了。

2.2、PWM占空比计算

计算PWM占空比的计算方式为:如图为输出50%PWM信号,1KHZ。

2.3、时基单元初始化函数

TIM_TimeBaseInit函数,TIM_TimeBaseInitTypeDef结构体参数有:

TIM_Prescaler,预分频器值,也就是PSC值。

TIM_CounterMode,计数模式,一般为向上计数模式,

TIM_Period,自动重装值,ARR.

TIM_ClockDivision,预分频,多少分频,对72MHZ的频率进行除法,一分频则不变。

TIM_RepetitionCounter,不太理解,给的是0

2.4输出比较初始化函数

 以上函数是用来配置输出比较模块的,每个函数对应一个定时器的通道,配合结构体使用。

TIM_OCInitTypeDef,结构体参数有:

TIM_OCMode:输出比较模式,PWM应用中就PWM1和PWM2两种模式,其他有冻结/有效/无效/反转等用不到的模式。

TIM_OutputState:输出使能

TIM_OutputNState:输出失能

TIM_Pulse:比较器值CCR, 0x0000 and 0xFFFF之间的值。

TIM_OCPolarity:极性,TIM_OCNPolarity_High,TIM_OCNPolarity_Low 

TIM_OCNPolarity:同上

TIM_OCIdleState:未理解,没用到

TIM_OCNIdleState:未理解,没用到

如上面几个在程序中未用到的参数,就可以调用函数TIM_OCStructInit(&TIM_OCInitStructure);,给他们统一赋初始值。

下图为输出比较模式的详解图:

2.5设置CCR值

以上函数是用来更改占空比的,调整CCR的值来改变占空比,

参考:

PWM原理 PWM频率与占空比详解

PWM详解(嵌入式学习)

STM32入门教程-2023版 细致讲解 中文字幕

  • 23
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,让我来回答你的问题。 首先,STM32F401是一款基于ARM Cortex-M4内核的微控制器,它具有丰富的外设和强大的性能。PWM(脉冲宽度调制)是一种常用的数字信号调制技术,可以用来控制LED等外设的亮度。 下面是一个简单的呼吸灯控制程序,使用了STM32CubeMX和HAL库。假设我们使用的是PA5引脚来驱动LED: 1. 配置TIM2为PWM模式,设置周期和分辨率 ```c void MX_TIM2_Init(void) { TIM_MasterConfigTypeDef sMasterConfig = {0}; TIM_OC_InitTypeDef sConfigOC = {0}; htim2.Instance = TIM2; htim2.Init.Prescaler = 0; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 999; htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; if (HAL_TIM_PWM_Init(&htim2) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK) { Error_Handler(); } sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 0; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) { Error_Handler(); } HAL_TIM_MspPostInit(&htim2); } ``` 2. 在main函数中初始化TIM2和GPIOA ```c int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_TIM2_Init(); HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); while (1) { for (int i = 0; i <= 999; i++) { __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, i); HAL_Delay(2); } for (int i = 999; i >= 0; i--) { __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, i); HAL_Delay(2); } } } ``` 3. 在主循环中,使用for循环逐步增加或减小PWM占空比,从而实现呼吸灯效果。 上述代码可以实现一个简单的呼吸灯效果,你可以根据实际需求进行修改。希望对你有所帮助!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值