【蓝桥杯嵌入式】四、各种外设驱动(六)通用定时器(2):利用定时器输入捕获模式读取PWM波(常考)

温馨提示:本文不会重复之前提到的内容,如需查看,请参考附录

【蓝桥杯嵌入式】附录

重点提炼:

引脚对应:

        TIM3_CH1/TIM16_CH1——PB4——频率输出1

        TIM2_CH1/TIM8_CH1——PA15——频率输出2

CubeMX设置:

        将Combined Channels(结合渠道)设置为PWM Input on CH1模式

        定时器基本参数:

  • 预分频系数:Prescaler (PSC - 16 bits value)
  • 定时器周期:Counter Period

        定时器模式参数:

  • 捕获极性:Polarity Selection  (根据要读取的PWM波形选择,一般习惯是:如果PWM波以上跳沿开始那么CH1就设置为上跳沿有效)

        打开对应的定时器中断。

MDK代码:

        需要打开对应定时器、中断方式打开两个通道

HAL_TIM_Base_Start(&htim3);
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_2);

         中断服务函数名称:

void TIM3_IRQHandler(void)

        读取比较寄存器的值:

__HAL_TIM_GET_COMPARE(定时器句柄地址, 通道号);

频率计算公式:

如果测量频率需要更精确,直接将预分频系数设置为0,这样定时器频率就等于APB1 Timer了。

读取的PWM波的频率 = 定时器频率/CH1读取的值

而:

定时器频率 = APB1 Timer/(预分频系数+1);

理论知识:

        根据我介绍的操作,你可以学会读取PWM波方法,读取的原理参考以下文章PWM输入捕获(只使用一路定时器通道)_pwm捕获-CSDN博客

       

一、需求分析

本示例设计:读取PWM波的周期和脉宽,并显示在LCD上。LCD设置为蓝色背景,白色字符。

1、需要的外设资源分析:

  • 读取PWM波:TIM3_CH1(PB4)
  • LCD

 2、外设具体分析:

查看原理图,和手册。

LCD部分见附录;

根据原理图,信号发生器(也就是开发板上的频率输出)有两个输出——PA15和PB4,如图:

利用CubeMX,发现引脚对应为:

TIM3_CH1/TIM16_CH1——PB4——频率输出1

TIM2_CH1/TIM8_CH1——PA15——频率输出2

所以,PB4可以用作TIM3的通道1,如图:

根据手册,输入捕获模式需要设置如下参数:

定时器基本参数:

  • 预分频系数:Prescaler (PSC - 16 bits value)
  • 定时器周期:Counter Period

定时器模式参数:

  • 捕获极性:Polarity Selection  (根据要读取的PWM波形选择,一般习惯是:如果PWM波以上跳沿开始那么CH1就设置为上跳沿有效)

3、软件分析:

要求分析:

使用TIM3_CH1捕获PWM信号,然后显示在LCD上。

二、软件配置

参考附录的内容,建立名为“PWM_In_Demo ”的项目,别忘记修改时钟配置。

按照分析配置引脚:

        LCD部分见附录;

        这里 TIM3 要先配置引脚,因为TIM3_CH1对应两个引脚,开发板上连接的是PB4。

        然后选中TIM3,将Combined Channels(结合渠道)设置为PWM Input on CH1模式,如图:

然后配置 Parameter Settings :

  • 为了看到明显改变,这里设置时钟频率为1万Hz。
  • 读取PWM的定时器周期应该大于要读取的PWM波周期,默认情况下读取PWM的定时器周期设置的尽量大即可。所以这里把溢出周期为5000ms。

即:

  • 预分频系数:Prescaler (PSC - 16 bits value)    =  4999
  • 定时器周期:Counter Period  =  49999         
  • 捕获极性:将CH1的 Polarity Selection 设置为Rising Edge     
  • 其余保持默认

结果如图:

打开TIM3中断,使用默认优先级即可;

生成项目文件后,打开MDK;

导入LCD驱动程序;

三、代码编写

分析:

  • 先在while循环前设置LCD的显示颜色,然后启动TIM3,以输入捕获模式中断启动CH1和CH2两个通道;

输入捕获模式中断启动CH1函数:

HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1):
  • 主循环体中不需要写代码,功能在中断服务函数里实现;
  • stm32g4xx_it.c 里用Find模式搜索TIM3,找到找到中断服务函数TIM3_IRQHandler

  • 在中断服务函数的第二个用户代码段里读取周期和脉宽,并显示在LCD上;

用到的函数:

中断服务函数名称:

void TIM3_IRQHandler(void)

读取比较寄存器的值:

__HAL_TIM_GET_COMPARE(定时器句柄地址, 通道号);

在MDK中编写代码:

在 main(void) 的 /* USER CODE BEGIN WHILE */ 代码段,编写以下代码:

  /* USER CODE BEGIN WHILE */
	LCD_SetBackColor(Blue);
	LCD_SetTextColor(White);
	LCD_Clear(Blue);
	
	HAL_TIM_Base_Start(&htim3);
	HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);
	HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_2);
  while (1)
  {
    /* USER CODE END WHILE */

在中断服务函数的 /* USER CODE BEGIN SysTick_IRQn 1 */代码段,编写以下代码:

  /* USER CODE BEGIN TIM3_IRQn 1 */
	uint16_t IC1_width = __HAL_TIM_GET_COMPARE(&htim3,TIM_CHANNEL_1);
	uint16_t IC2_pluse = __HAL_TIM_GET_COMPARE(&htim3,TIM_CHANNEL_2);	
	if(IC1_width==0 || IC2_pluse==0)
		return;
	char str_width[20];
	char str_pluse[20];
	sprintf(str_width,"PWM width = %d",IC1_width);
	sprintf(str_pluse,"PWM pluse = %d",IC2_pluse);	

	LCD_DisplayStringLine(Line3,str_width);
	LCD_DisplayStringLine(Line5,str_pluse);
  /* USER CODE END TIM3_IRQn 1 */

四、运行测试

编译、下载。

运行结果如下:

PWM_In_Deom实验结果

        我们读取到了开发板上频率输出的周期和脉宽。

        这里为了演示周期和脉宽的方便,设置的定时器频率太低了,不适合用来计算PWM波的频率。但是根据周期和定时器的配置,也可以粗略计算出频率,如果测量频率需要更精确,直接将预分频系数设置为0,这样定时器频率就等于APB1 Timer了。

频率计算公式:

读取的PWM波的频率 = 定时器频率/PWM波周期。

而:

定时器频率 = APB1 Timer/(预分频系数+1)

  • 29
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值