一、项目要求:
混合彩色呼吸灯,通过PC端串口小助手控制呼吸灯速率,开发板上按键控制呼吸灯的颜色。
二、设计说明:
三、效果示意图:
四、相关代码:
/********************************************************************************************************
******************************* 野火开发板STM32F429 LED呼吸灯 ********************************************
********************************************************************************************************/
#include "stm32f4xx_hal.h"
/*****************************************************************************************************
**************************** 基础定义 ***************************************************************
*******************************************************************************************************/
TIM_HandleTypeDef TIM5_Handler; //定时器5 PWM句柄
TIM_OC_InitTypeDef TIM5_CH1Handler; //定时器5 通道句柄
GPIO_InitTypeDef gpio_init;
UART_HandleTypeDef uart_handler;
uint8_t RxBUF[10];
int arr = 700;
uint8_t pdata[1];
int ccr = 1;
int ccr2 = 3;
uint32_t channel1;
uint32_t channel2;
/*****************************************************************************************************
**************************** LED初始化 *************************************************************
*******************************************************************************************************/
void LED_Init(void)
{
__HAL_RCC_GPIOH_CLK_ENABLE();
gpio_init.Pin = GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12; //初始化引脚
gpio_init.Mode = GPIO_MODE_AF_PP; //复用推挽输出
gpio_init.Pull = GPIO_PULLUP; //不上下拉
gpio_init.Speed = GPIO_SPEED_FREQ_VERY_HIGH; //速度非常高
gpio_init.Alternate = GPIO_AF2_TIM5; //复用为定时器5(PH10-PH12 对应TIM5的CH1-CH3)
HAL_GPIO_Init(GPIOH , &gpio_init);
}
/*****************************************************************************************************
**************************** TIMER PWM 初始化配置 ************************************************
*******************************************************************************************************/
void TIME_PWM_Init()
{
TIM5_Handler.Instance = TIM5; //定时器5
TIM5_Handler.Init.Prescaler = 90-1; //定时器预分频系数
TIM5_Handler.Init.CounterMode = TIM_COUNTERMODE_UP; //向上计数模式
TIM5_Handler.Init.Period = 1000-1; //自动重装载值
TIM5_Handler.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_PWM_Init(&TIM5_Handler); //初始化PWM
TIM5_CH1Handler.OCMode = TIM_OCMODE_PWM1; //模式选择(PWM模式1:向上计数时,TIMx_CNT < TIMx_CCR1时为有效电平,否则为无效电平)
TIM5_CH1Handler.Pulse = 500; //设置比较值,此值用来确定占空比,默认比较值为自动重装载值的一半,即占空比为50%
TIM5_CH1Handler.OCPolarity = TIM_OCPOLARITY_LOW; //输出比较极性为低 即低电平有效
}
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
if((htim->Instance) == TIM5)
{
__HAL_RCC_TIM5_CLK_ENABLE(); //使能定时器
LED_Init();
}
}
void MY_PWM_Init_1(uint32_t channel)
{
channel1 = channel; //保存上一次更改的通道
HAL_TIM_PWM_ConfigChannel(&TIM5_Handler,&TIM5_CH1Handler,channel); //配置TIM5通道
HAL_TIM_PWM_Start(&TIM5_Handler,channel);//开启PWM通道
}
void MY_PWM_Init_2(uint32_t channel)
{
channel2 = channel; //保存上一次更改的通道
HAL_TIM_PWM_ConfigChannel(&TIM5_Handler,&TIM5_CH1Handler,channel); //配置TIM5通道
HAL_TIM_PWM_Start(&TIM5_Handler,channel);//开启PWM通道
}
/*****************************************************************************************************
**************************** 设置计算器比较值函数 *************************************************
*******************************************************************************************************/
void TIM_SetTIM5Compare(int ccr,uint32_t compare)
{
if(ccr == 3){
TIM5->CCR3 = compare;
}else if(ccr == 2){
TIM5->CCR2 = compare;
}else if(ccr == 1){
TIM5->CCR1 = compare;
}
}
void TIM_SetTIM5Compare_2(int ccr2,uint32_t compare)
{
if(ccr2 == 3){
TIM5->CCR3 = compare;
}else if(ccr2 == 2){
TIM5->CCR2 = compare;
}else if(ccr2 == 1){
TIM5->CCR1 = compare;
}
}
/*****************************************************************************************************
**************************** 外部中断初始化 *********************************************************
*******************************************************************************************************/
void EXTI_init(void)
{
GPIO_InitTypeDef gpio_init;
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
gpio_init.Pin = GPIO_PIN_0;
gpio_init.Mode = GPIO_MODE_IT_RISING; //上升沿触发
gpio_init.Pull = GPIO_PULLDOWN;
gpio_init.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA,& gpio_init);
gpio_init.Pin = GPIO_PIN_13;
HAL_GPIO_Init(GPIOC,& gpio_init);
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2); //分组仅仅设置一次
HAL_NVIC_SetPriority(EXTI0_IRQn, 2, 2);
HAL_NVIC_EnableIRQ(EXTI0_IRQn);
HAL_NVIC_SetPriority(EXTI15_10_IRQn, 1, 1);
HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
}
/*****************************************************************************************************
**************************** 外部中断服务函数 *******************************************************
*******************************************************************************************************/
void EXTI0_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
}
void EXTI15_10_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);
}
/*******************************************************************************************************
**************************** 外部中断回调函数 - 重写弱函数 *******************************************
*******************************************************************************************************/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == GPIO_PIN_0){
HAL_TIM_PWM_Stop(&TIM5_Handler,channel1);
HAL_TIM_PWM_Stop(&TIM5_Handler,channel2);
MY_PWM_Init_1(TIM_CHANNEL_1);
MY_PWM_Init_2(TIM_CHANNEL_3);
ccr = 1;
}else if(GPIO_Pin == GPIO_PIN_13){
HAL_TIM_PWM_Stop(&TIM5_Handler,channel1);
HAL_TIM_PWM_Stop(&TIM5_Handler,channel2);
MY_PWM_Init_1(TIM_CHANNEL_2);
MY_PWM_Init_2(TIM_CHANNEL_3);
ccr = 2;
}
}
/*******************************************************************************************************
**************************** 串口初始化 **************************************************************
*******************************************************************************************************/
void UART_init(uint32_t BaudRrate)
{
uart_handler.Instance = USART1;
uart_handler.Init.BaudRate = BaudRrate;
uart_handler.Init.WordLength = USART_WORDLENGTH_8B;
uart_handler.Init.StopBits = USART_STOPBITS_1;
uart_handler.Init.Parity = USART_PARITY_NONE;
uart_handler.Init.Mode = USART_MODE_TX_RX;
HAL_UART_Init(&uart_handler);
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2); //分组仅仅设置一次
HAL_NVIC_SetPriority(USART1_IRQn, 1, 1);
HAL_NVIC_EnableIRQ(USART1_IRQn);
}
void HAL_UART_MspInit(UART_HandleTypeDef *husart)
{
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
gpio_init.Pin = GPIO_PIN_9 | GPIO_PIN_10;
gpio_init.Mode = GPIO_MODE_AF_PP;
gpio_init.Pull = GPIO_MODE_IT_RISING;
gpio_init.Speed = GPIO_SPEED_FREQ_HIGH;
gpio_init.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA,&gpio_init);
}
/******************************************************************************************************
**************************** 串口服务函数 *************************************************************
*******************************************************************************************************/
void USART1_IRQHandler(void)
{
HAL_UART_IRQHandler(&uart_handler);
}
/*******************************************************************************************************
**************************** 串口接收回调函数 *******************************************************
*******************************************************************************************************/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *husart)
{
HAL_UART_Receive_IT(&uart_handler , pdata , 1);
uint8_t ch;
ch = pdata[0];
if(('0'< ch )&&(ch<= '5')&&(pdata[1] == 0)){
switch (ch){
case '1':
arr = 100;
break;
case '2':
arr = 200;
break;
case '3':
arr = 400;
break;
case '4':
arr = 600;
break;
case '5':
arr = 800;
break;
}
}else{
arr = 1000;
HAL_UART_Transmit(&uart_handler ,"Error!Please enter a new number between 1 and 5.\r\n" ,50,100);
}
}
/*************************************************************************************************
**************************** 延时函数 **********************************************************
*************************************************************************************************/
void delay_ms(int x)
{
int y;
while(x--)
{
for(y=0;y<1000;y++);
}
}
/*************************************************************************************************
**************************** 主函数 *********************************************************
*************************************************************************************************/
int main(void)
{
uint8_t dir = 1; //亮暗方向。占空比大,亮度大;占空比小,亮度小。
uint16_t ledpwmval = 0; //设置值
TIME_PWM_Init();
MY_PWM_Init_1(TIM_CHANNEL_3);
MY_PWM_Init_2(TIM_CHANNEL_3);
EXTI_init();
UART_init(115200);
HAL_UART_Receive_IT(&uart_handler, pdata, 1); //只要有中断就有回调函数
HAL_UART_Transmit(&uart_handler ,"Please enter a number between 1 and 5.\r\n" ,40,100);
while(1)
{
delay_ms(10);
if(dir)ledpwmval++; //dir==1 由暗变亮 ledpwmval递增
else ledpwmval--; //dir==0 ledpwmval递减
if(ledpwmval>arr)dir=0; //ledpwmval到达300后,方向为递减
if(ledpwmval==0)dir=1; //ledpwmval递减到0后,方向改为递增
TIM_SetTIM5Compare(ccr,ledpwmval); //修改比较值,修改占空比
TIM_SetTIM5Compare_2(ccr2,ledpwmval); //修改比较值,修改占空比
}
}