欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【STM32】【STM32CubeMX】STM32CubeMX的使用之六:定时器配置输出PWM,实现变色呼吸灯

程序员文章站 2022-06-08 19:06:18
...


  下载工程文件:
  https://gitee.com/Joseph_Cooper/stm32-cube-mx-stm32-l151-c8-t6



0、前言

  有关STM32实现PWM的理论知识戳这里


1、硬件设计

【STM32】【STM32CubeMX】STM32CubeMX的使用之六:定时器配置输出PWM,实现变色呼吸灯

▲ 核心板上的RGB_LED原理图

  查阅数据手册可知引脚对应的定时器通道:
【STM32】【STM32CubeMX】STM32CubeMX的使用之六:定时器配置输出PWM,实现变色呼吸灯

▲ STM32L151手册截图

2、CubeMX配置

【STM32】【STM32CubeMX】STM32CubeMX的使用之六:定时器配置输出PWM,实现变色呼吸灯

▲ CubeMX PWM配置图

  时基设置,设置2ms定时器溢出,即500HzPWM
【STM32】【STM32CubeMX】STM32CubeMX的使用之六:定时器配置输出PWM,实现变色呼吸灯

▲定时器时基设置

3、软件设计

  在配置占空比参数之前需要先使能定时器的各个通道。

	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