PWM控制LED亮度(2-呼吸灯)-STM32电控学习笔记10

PWM控制LED亮度(2-呼吸灯)-STM32电控学习笔记10

day10:2022/9/29

前面学了两三天的PWM了,PWM本身不难理解,至于为啥进度缓慢,还不是这时钟定时器分频值重装载啥的太难理解了呜呜呜,今天终于可以掌握并实现PWM脉宽调制了,接下来离调试电机也不远了!

【PWM控制亮度】

上一篇帖子大致介绍了PWM,时钟,预分频值和重载值等概念,结尾说到

通过设置合适的分频值可以得到我们需要的定时器频率
通过设置合适的重载值可以得到我们需要的定时器周期PWM信号频率
通过设置脉宽即可得到我们需要的PWM信号

现在我们来具体尝试一下改变LED灯的亮度:
首先我们对定时器进行简单设置,如下图:
在这里插入图片描述

我们设定的重载值为200,那么设定的脉宽就只能在0-200之间,因为是向上计数,因此脉宽越大,占空比越大,我们将三个引脚的脉宽都设置为100,就可以得到一个占空比为50%的PWM信号,相对于LED灯的亮度为最大值的一半。然后我们生成代码

打开源代码后,可以找到我们设置的预分频值、重载值、脉宽等,后续操作如需改变相关参数,只需要直接在源代码里修改即可,无需重新配置
在这里插入图片描述

接着打开我们的main.c文件,开始书写代码

第一步:在单片机上电开始工作时,需要进行许多初始化操作,PWM脉宽调制需要用到定时器,因此我们需要把定时器先打开
在int main()函数内,写入代码开启定时器TIM5
HAL_TIM_Base_Start(&htim5);

第二步:我们既然需要开灯,就要在while循环内部设置相关引脚进行输出,而我们在前面配置时,将LED灯的RGB三个引脚设置为了PWM输出模式,因此我们可以利用下面这个函数进行引脚输出
在这里插入图片描述

在while循环内部输入

    HAL_TIM_PWM_Start(&htim5, TIM_CHANNEL_1);
	HAL_TIM_PWM_Start(&htim5, TIM_CHANNEL_2);
	HAL_TIM_PWM_Start(&htim5, TIM_CHANNEL_3);

第三步:编译上传,可以发现我们的LED灯在以一半亮度持续发光,这是因为我们设置的占空比为50%。

【PWM实现呼吸灯】

至此,PWM调制LED亮度的方式大家应该有所掌握了,那我们可不可以令脉宽(占空比)在一定范围内高低变化,从而实现呼吸灯的效果呢,当然是可以的,只需要在原有的代码上稍作修改即可。

首先我们在主函数内定义一个变量来代表脉宽 uint16_t Pulse=0;
初始值设置为0,代表占空比为0,即LED不亮。

接着while循环代码书写如下:

while (1)
  {
	HAL_TIM_PWM_Start(&htim5, TIM_CHANNEL_1);
	HAL_TIM_PWM_Start(&htim5, TIM_CHANNEL_2);
	HAL_TIM_PWM_Start(&htim5, TIM_CHANNEL_3);
	 while (Pulse < 200)
	  {
	  Pulse ++;
    __HAL_TIM_SetCompare(&htim5, TIM_CHANNEL_1, Pulse);  
	__HAL_TIM_SetCompare(&htim5, TIM_CHANNEL_2, Pulse);   
	__HAL_TIM_SetCompare(&htim5, TIM_CHANNEL_3, Pulse);   	
	 HAL_Delay(5);
	  }
	  while (Pulse)
	  {
		  Pulse --;
	__HAL_TIM_SetCompare(&htim5, TIM_CHANNEL_1, Pulse); 
	__HAL_TIM_SetCompare(&htim5, TIM_CHANNEL_2, Pulse);   
	__HAL_TIM_SetCompare(&htim5, TIM_CHANNEL_3, Pulse);   
	HAL_Delay(5);
	  }
	HAL_Delay(200);
  }
}

函数__HAL_TIM_SetCompare(&htim5, TIM_CHANNEL_1, Pulse);
代表将定时器5的PWM输出引脚1的脉宽设定为Pulse。

然后编译烧录,就可以实现呼吸灯的效果啦。

nrf51822并没有PWM模块,但是如果巧妙的结合PPI模块,并加上一个定时器中断就可以轻松的实现了PWM,思路是这样的: 定时器使用三个比较器 cc0、cc1和cc2,当三个比较器任何一产生比较事件的时候都会通过PPI去翻转GPIO的引脚,在初始化的时候这样设置这三个比较器: NRF_TIMER2->CC[0] = MAX_SAMPLE_LEVELS + next_sample_get(); NRF_TIMER2->CC[1] = MAX_SAMPLE_LEVELS; // CC2 will be set on the first CC1 interrupt. NRF_TIMER2->CC[2] = 0; 这是初始化的配置,到这里会有一个思考,这样的话计数器技术到cc0的时候依然会继续的往下计数,那这样的话他的再溢出的值就将回到cc2的时候也就是归零的时候,那这样的波形就分为了三段了,这不是我们所需要的,那这样要实现PWM就要把cc2的比较值往后挪,让他超过cc0,并且cc2到之前的一个比较值是固定的,这样就需要从新设置cc2的值,还有一个办法就是当计数器到cc0的时候请求中断重置计数器,但是这样做有一个问题就是进入中断是需要时间的,而当计数器到达cc0的时候就需要重置,同时计数器的下一个值就是cc2,这样就会造成冲突,所以我们使用了第一种方案。 具体实现是这样的,使能cc1比较中断,在第一次中断中重新设置cc1,让他的值变成了两倍,同时从新设置cc2,让他的值变成了cc1+N,N就是占空比参数,在第二次中断中,也是从新设置cc1,但是和上一次中断不同的是这时候设置的是cc0,而不是cc2 这样造成的计数器溢出值是这样的:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SZTU_ELIAS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值