由于我们前期的任务目标中,不做台灯,而改为环境检测了,对于PWM的应用就缺失了一部分,这样也会导致基本上没有下行的控制命令的必要的,这样可不行,所以有关PWM控制部分我们集成到板载的LED控制,来实现三个LED的多种控制模式,我们这里实现四种控制模式。
第一种就是循环灯,三个LED循环点亮;
第二种就是Blink,这里实现的事所有LED同亮和同灭;
第三种是循环呼吸灯,三个LED循环呼吸点亮;
第四个是同步呼吸灯,所有LED同频进行呼吸灯的实现;
这里我们就要看一下芯片的资源是不是能满足我们的要求,我们这里不去看手册,在STM32CubeMX中进行查看:

如上图,这样查看可以看到是不是是定时器CH口,如果可以,就能实现PWM呼吸灯的功能,LED1对应PB4,LED2对应PA9,LED3对应的是PB8,为了节约资源可以将其中PB4和PB8可以用同一个定时器(TIM1),PA9只能用定时器3了。
咱们先初步将PB4配置为普通GPIO输出,PB8和PA9配置为PWM输出:

上图可以看到配置为PWM输出的引脚是黄色,说明我们还没有配置完成,我们还要对对应的定时器进行配置例如PB8:

PWM输出不需要配置中断等内容,只要配置时钟源、通道、定时基准就可以了,其他的使用默认配置就可以了。
这里我们还添加了一个按键的控制,B1,作为还没有蓝牙控制的一个手动切换模式的控制按键:

B1对应的按键是PC13:

结合原理图,我们需要修改外部中断的配置,下降沿触发并且需要上拉,注意开启外部中断;
我们先测试一下按键的效果,添加外部中断的回调函数:
void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == B1_Pin)
{/* KEY */
HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
}
}LED1(蓝灯)的控制随着B1的按下进行翻转,加下来我们测试一下普通定时器16的,10ms定时功能:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM16) {
HAL_IncTick();
LED.TIMcnt ++;
if(LED.TIMcnt>100){
LED.TIMcnt = 0;
HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
}
}
}这样就实现了和之前创建初始工程时的效果一样了,1s实现一次LED(蓝灯的翻转),这里需要注意一下,对于定时器不会自动开启,我们需要使用HAL_TIM_Base_Start_IT(&htim16);才能真正的运转起来。
接下来我们看一下LED3(红灯)的呼吸灯效果,这也是加入定时器16的一个主要原因:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM16) {
HAL_IncTick();
LED.TIMcnt ++;
LED.PWMcnt ++;
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,LED.PWMcnt*50);
if(LED.PWMcnt>100)
LED.PWMcnt = 0;
}
}注意启动PWM对应的定时器,使用HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1)效果正常;
接下来就是一个整合了,由于我们对LED的控制分为不同的配置,这个我们是无法通过STM32CubeMX进行同步配置多以我们需要写两个不同状态的初始化程序,一个是三个LED都配置为GPIO输出:
void LED_GPIO_init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
/*Configure GPIO pin : PtPin */
GPIO_InitStruct.Pin = LED1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(LED1_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = LED2_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(LED2_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = LED3_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(LED3_GPIO_Port, &GPIO_InitStruct);
}另外一种模式就是PWM控制模式的初始化,这一部分我们是通过STM32CubeMX生成的,切换模式的时候直接使用系统生成的函数就可以,注意一点就是STM32CubeMX对引脚配置只能是一种,所以要想切换只能手动写一下。
接下来就是模式的切换,通过外部中断实现:
void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == B1_Pin)
{/* KEY */
LED.Mode_Dis++;
if(LED.Mode_Dis>=4)
LED.Mode_Dis = 0;
}
}重点是在定时器中对LED中间太的控制:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM16) {
HAL_IncTick();
switch(LED.Mode_OidDis)
{
case 0:
LED.TIMcnt++;
if(LED.TIMcnt>100){
LED.TIMcnt = 0;
LEDRed_off;
LEDBlue_off;
LEDGreen_off;
LED.state ++;
switch(LED.state%3){
case 0:
LEDRed_on;
break;
case 1:
LEDBlue_on;
break;
case 2:
LEDGreen_on;
break;
default:
break;
}
}
break;
case 1:
LED.TIMcnt++;
if(LED.TIMcnt>100){
LED.TIMcnt = 0;
LEDRed_Toggle;
LEDBlue_Toggle;
LEDGreen_Toggle;
}
break;
case 2:
LED.PWMcnt ++;
if(LED.PWMcnt<100){
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,LED.PWMcnt*50);
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,LED.PWMcnt*50);
__HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_2,LED.PWMcnt*50);
}
else if(LED.PWMcnt>=100 && LED.PWMcnt<200){
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,(200-LED.PWMcnt)*50);
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,(200-LED.PWMcnt)*50);
__HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_2,(200-LED.PWMcnt)*50);
}
else
LED.PWMcnt = 0;
break;
case 3:
LED.PWMcnt ++;
if(LED.PWMcnt<100){
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,LED.PWMcnt*50);
}
else if(LED.PWMcnt>=100 && LED.PWMcnt<200){
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,(200-LED.PWMcnt)*50);
}
else if(LED.PWMcnt>=200 && LED.PWMcnt<300){
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,(LED.PWMcnt-200)*50);
}
else if(LED.PWMcnt>=300 && LED.PWMcnt<400){
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,(400-LED.PWMcnt)*50);
}
else if(LED.PWMcnt>=400 && LED.PWMcnt<500){
__HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_2,(LED.PWMcnt-400)*50);
}
else if(LED.PWMcnt>=500 && LED.PWMcnt<600){
__HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_2,(600-LED.PWMcnt)*50);
}
else
LED.PWMcnt = 0;
break;
default:
break;
}
}
}效果如下:

我要赚赏金
