下载工程文件: https://gitee.com/Joseph_Cooper/stm32-cube-mx-stm32-l151-c8-t6 MCU:STM32L151C8T6-A IDE:MDK-Keil5 固件库:STM32Cube FW_L1 V1.10.1
有关STM32实现PWM的理论知识戳这里。
查阅数据手册可知引脚对应的定时器通道:
▲ STM32L151手册截图时基设置,设置2ms定时器溢出,即500Hz的PWM。
▲定时器时基设置在配置占空比参数之前需要先使能定时器的各个通道。
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2); HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_3);逻辑实现: main.c
... int main(void) { /* USER CODE BEGIN 1 */ uint8_t ColorIndex = 1; //颜色索引 double Duty = 0; //待计算的占空比 double DutyTempR = 0; //占空比临时值R double DutyTempG = 0; //占空比临时值G double DutyTempB = 0; //占空比临时值B double OperateTemp = 0; //计算产生的临时变量,用于使DutyTemp逼近Duty //RGB数值列表 uint8_t ValR[] = {255, 255, 255, 0 , 0 , 0 , 255}; uint8_t ValG[] = {0 , 125, 255, 255, 255, 0 , 0 }; uint8_t ValB[] = {0 , 0 , 0 , 0 , 255, 255, 255}; /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_TIM2_Init(); /* USER CODE BEGIN 2 */ HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2); HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_3); Duty = 100 - ((ValR[0] / 255) * 100); //根据RGB数值计算出相应的占空比参数 DutyTempR = Duty; __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, DutyTempR*(2000-1)/100); //赋值 Duty = 100 - ((ValG[0] / 255) * 100); //根据RGB数值计算出相应的占空比参数 DutyTempG = Duty; __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2, DutyTempG*(2000-1)/100); //赋值 Duty = 100 - ((ValB[0] / 255) * 100); //根据RGB数值计算出相应的占空比参数 DutyTempB = Duty; __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_3, DutyTempB*(2000-1)/100); //赋值 /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { //R Duty = 100 - ((ValR[ColorIndex] / 255) * 100); //根据RGB数值计算出相应的占空比参数 OperateTemp = Duty - DutyTempR; //计算总差值 OperateTemp /= 15; //差值分10次补偿给DutyTemp while (DutyTempR != Duty) { if (OperateTemp > 0 && DutyTempR > Duty) //解决因小数精度问题而无法满足循环解除条件的问题 break; if (OperateTemp < 0 && DutyTempR < Duty) //解决因小数精度问题而无法满足循环解除条件的问题 break; DutyTempR += OperateTemp; //差值补偿 if(DutyTempR > 100) //防溢出操作 DutyTempR = 100; else if(DutyTempR < 0) DutyTempR = 0; __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, DutyTempR*(2000-1)/100); //赋值 HAL_Delay(100); //延时100ms } __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, DutyTempR*(2000-1)/100);//最终赋确定值,此时DutyTemp=Duty //G Duty = 100 - ((ValG[ColorIndex] / 255) * 100); //根据RGB数值计算出相应的占空比参数 OperateTemp = Duty - DutyTempG; //计算总差值 OperateTemp /= 15; //差值分10次补偿给DutyTemp while (DutyTempG != Duty) { if (OperateTemp > 0 && DutyTempG > Duty) //解决因小数精度问题而无法满足循环解除条件的问题 break; if (OperateTemp < 0 && DutyTempG < Duty) //解决因小数精度问题而无法满足循环解除条件的问题 break; DutyTempG += OperateTemp; //差值补偿 if(DutyTempG > 100) //防溢出操作 DutyTempG = 100; else if(DutyTempG < 0) DutyTempG = 0; __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2, DutyTempG*(2000-1)/100); //赋值 HAL_Delay(100); //延时100ms } __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2, DutyTempG*(2000-1)/100);//最终赋确定值,此时DutyTemp=Duty //B Duty = 100 - ((ValB[ColorIndex] / 255) * 100); //根据RGB数值计算出相应的占空比参数 OperateTemp = Duty - DutyTempB; //计算总差值 OperateTemp /= 15; //差值分10次补偿给DutyTemp while (DutyTempB != Duty) { if (OperateTemp > 0 && DutyTempB > Duty) //解决因小数精度问题而无法满足循环解除条件的问题 break; if (OperateTemp < 0 && DutyTempB < Duty) //解决因小数精度问题而无法满足循环解除条件的问题 break; DutyTempB += OperateTemp; //差值补偿 if(DutyTempB > 100) //防溢出操作 DutyTempB = 100; else if(DutyTempB < 0) DutyTempB = 0; __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_3, DutyTempB*(2000-1)/100); //赋值 HAL_Delay(100); //延时100ms } __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_3, DutyTempB*(2000-1)/100);//最终赋确定值,此时DutyTemp=Duty HAL_Delay(1000); if(ColorIndex < 6) //使颜色于红~紫轮流切换 ColorIndex += 1; else ColorIndex = 0; /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ } ...本程序的逻辑部分移植于https://blog.csdn.net/weixin_43444989/article/details/107401333。