定时器&PWM应用编程

一、定时器计数控制LED

使用STM32F103的 Tim2~Tim5其一定时器的某一个通道pin(与GPIOx管脚复用,见下图),连接一个LED,用定时器计数方式,控制LED以2s的频率周期性地亮-灭。

1.1、创建项目

在这里插入图片描述
在这里插入图片描述
再设置一个输出管脚控制LED灯的亮灭。这里设置的是A4。最后按照之前的配置,生成程序即可。

1.2、代码添加

  • 首先需要开启定时器中断
    在这里插入图片描述
  • 添加中断回调处理函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
	static uint32_t time_cnt = 0;
	if(htim->Instance == TIM2){
		if(++time_cnt >= 400){
			time_cnt = 0;
			HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_4);
		}
	}
}

1.3、实现效果

在这里插入图片描述

二、定时器pwm模式呼吸灯

采用定时器pwm模式,让 LED 以呼吸灯方式渐亮渐灭,周期为1~2秒,自己调整到一个满意效果。使用Keil虚拟示波器,观察 pwm输出波形。

2.1、设计思路

  • 第一步:定义初始化占空比Duty值为0
  • 第二步:如果占空比值小于200,则步进10,延迟60ms,一直循环,直到占空比值为200
  • 第三步:如果占空比值为200,则步进-10,延迟60ms,一直循环知道占空比值为0,又回到第2步。

一个PWM信号周期为20ms,因为STM32F103C8T6的时钟频率为72MHZ,故可以PSC为7199,ARR为200。这样单个脉冲周期为200/[72*10^6/(7199+1)]=0.02s即20ms

2.2、项目创建

在这里插入图片描述
改成72MHZ
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
最后生成这个项目即可

2.3、代码添加

  • 开启PWM
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
  • while循环控制pwm占空比
while (1)
  {
    /* USER CODE END WHILE */
	  while(Duty < 200){
		  HAL_Delay(60);
		  Duty = Duty + 10;
		  __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, Duty);
	  }
	  while(Duty > 0){
		  HAL_Delay(60);
		  Duty = Duty - 10;
		  __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, Duty);
	  }
    /* USER CODE BEGIN 3 */
  }

2.4、示波器观察

在这里插入图片描述
通过示波器可以看到占空比逐渐在变化,这一段是从0一直到200。因为使用了延迟函数,延迟同一占空比60ms,一个脉冲周期为20ms,所以会重复三次相同脉冲,步进值为10。60*20=1200ms,为从0到200的时间。
在这里插入图片描述
这段是从200到0,会持续1200ms的时间。所以总共一个呼吸下来会话2.4s的时间。

2.5、效果

在这里插入图片描述
人眼看的时候,这确实是一个呼吸灯,但使用手机录制视频时就会出现闪烁的情况,这是为什么?闪烁的频率太慢了。如何解决?增大闪烁的频率,即减小一个脉冲的周期。所以可以减小分频系数,或者减少计数值。

  • 将分频系数改为71,实际数值会加1,此时计算每个脉冲周期为0.2ms,示波器如下:
    在这里插入图片描述
    效果如下:
    在这里插入图片描述
  • 改变计数值
    在这里插入图片描述
    此时的一个脉冲周期为2ms。示波器如下:
    在这里插入图片描述
    效果如下:
    在这里插入图片描述

三、串口显示周期脉宽

采用定时器的另外一个通道,编程采集上面的pwm输出信号,获得其周期和脉宽,并重定向输出到串口显示。

3.1、创建项目

设置TIM1通道1为输入捕获并开启输入捕获中断
在这里插入图片描述
设置TIM2为PWM输出
在这里插入图片描述

3.2、代码

  • 输入捕获回调函数
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim){
	if(htim->Instance == TIM1) //ÅжϷ¢Éú²¶»ñÖжϵĶ¨Ê±Æ÷
	{
		if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) //Åжϲ¶»ñ·¢ÉúͨµÀ
		{
			if(CapIndex == 0){
				CapVal1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
				printf("CapVal1: %d\r\n",CapVal1);
				CapIndex = 1;
			}else if(CapIndex == 1){
				CapVal2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
				printf("CapVal2: %d\r\n",CapVal2);
				HAL_TIM_IC_Stop(htim, TIM_CHANNEL_1);
				CapIndex = 0;
				MeasureFlag = 1;
			}else{
				Error_Handler();
			}
		}
	}
}
  • while
while (1)
  {
    /* USER CODE END WHILE */
	  if(MeasureFlag == 1){
		  if(CapVal1>=CapVal2){
			Diff = CapVal2-CapVal1;
		  }else{
			  Diff = ((10000-CapVal1)+CapVal2);
		  }
		  printf("Period is:%.4fms\r\n",Diff/1.0);
		  MeasureFlag = 0;
		  HAL_Delay(1000);
		  HAL_TIM_IC_Start(&htim1, TIM_CHANNEL_1);
	  }
	  
	  //printf("Period is:%.4fms\r\n",Diff/1.0);
    /* USER CODE BEGIN 3 */
  }

3.3、运行效果

在这里插入图片描述

四、总结

经过本次实验,发现并没有很熟练的掌握定时器板块,有一部分实验没有做成功,比如输入捕获这里,还需要后续进一步完善,暂时没有找到原因。但呼吸灯以及定时控制亮灭都成功完成,对定时器有了初步的了解,以及如何控制PWM。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值