STM32F103ZET6【HAL开发】STM32CUBEMX------3.3测量PWM的频率和占空比

目的测量PWM的频率和占空比,通过串口调试助手打印出来

方法一:用定时器的PWM输入模式,采用一个定时器的两个通道(通道一和通道二),配置从模式为复位模式,没有进行溢出处理,所以需要考虑捕获的最低频率;

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
因为需要测量一个PWM信号,那么首先需要先产生一个PWM信号,这里我用TIM4_CH1(PD12)输出一个频率为50HZ,占空比为50%的PWM信号
在这里插入图片描述
在这里插入图片描述
然后参见定时器的内部框图可知,当从CH1输入一个PWM波,通过输入滤波后将会产生两路信号:tim_ti1fp1 & tim_ti1fp2,分别送至tim_ic1 & tim_ic2,也就是说一个TI信号将会被映射成两路的IC信号,所以可以通过进行边沿检测来测量PWM的频率以及占空比。

在这里插入图片描述
所以需要用到另外一个定时器的一个通道,此处选择TIM3_CH1(PA6)
1、设置定时器Slave Mode为Reset Mode,也就是当检测到上升沿时,定时器复位;
2、PWM由CH1进入,触发源设置为TI1FP1,并设置IC1为上升沿捕获;
3、当第一次捕获到上升沿时,定时器复位,计数寄存器CNT清零;
4、当IC2捕获到下降沿时,计数器CNT的值将会被存到捕获寄存器CCR2中;
5、当IC1再次捕获到上升沿时,计数器CNT的值将会被存到捕获寄存器CCR1中,同时将定时器复位;
6、开启TIM3的中断
因此,CCR1的值就是周期,CCR2的值就是占空比。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
最终计算得到的频率值 = 分频后得到的时钟频率 / 上升沿个数 = ( 定时器时钟频率 / 预分频系数 )/ 上升沿个数 ;
最终计算的到的占空比 = 下降沿个数 / 上升沿个数;
值得注意的是:要明确输入PWM波的大致范围,因为需要根据PWM波范围来确定预分频系数;比如说输入一个频率大概为50Hz,占空比为10%的PWM波,需要将预分频系数稍微设置大一些;(这是因为:定时器所能测量到的最小频率 = 定时器频率 / ( 预分频系数 * 自动重载值 ),而因为ARR(Auto-Reload-Register)是一个十六位寄存器,其最大值为65536,所以当需要测量的频率值较小时,必须要将预分频系数设为较大值)
以本次使用定时器TIM3为例,其时钟频率已配置为84MHz,再配置PSC(Prescaler)为(8400-1),因此,最终频率 = ( 84000000 / 8400 )/ PWM_RisingCount;

由于需要用到串口,所以还需要配置USART1
在这里插入图片描述
在这里插入图片描述

三、编写代码
串口1重定义,在keil设置中勾选微库(use mircolib)

#include <stdio.h>
int fputc(int ch, FILE *f)
{
	/* 发送一个字节数据到串口DEBUG_USART */
	HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 1000);	
	
	return (ch);
}

TIM4_CH1输出频率50HZ,占空比50%PWM信号

HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_1);  //启动TIM4_CH1 PWM输出

TIM3_CH1输入捕获PWM信号的占空比和频率,需要用跳线将PA6和PD12连接在一起。
定义相关变量,以及使能相关定时器和计数处理代码

#define cnt_clk 72000000/(71+1)//计数器频率
#define arr 65535//自定重装载值   
uint32_t CCR1,CCR2,end_flag;//存捕获寄存器获取的值的变量
float duty_cycle,frequency;//频率,占空比

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

  while (1)
  {
    //每1秒输出一次
		if(end_flag==1)
		{
			printf("\r\n频率=%.2fHZ,占空比=%.2f%%\r\n",frequency,duty_cycle);
			end_flag=0;
		}
		HAL_Delay(1000);
  }

输入捕获中断回调函数

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	  /*PWM 信号的第一个上升沿时,定时器产生中断,计数器,CCR寄存器被复位。
    当下降沿到来时,IC2 会捕获,对应的是脉冲宽度测量,但不会产生中断。当第
	  二个上升沿时,IC1会捕获,对应的是周期宽度测量,而且会再次进入中断*/
				//printf("0");
				CCR1=HAL_TIM_ReadCapturedValue(&htim8, TIM_CHANNEL_1);
				if(CCR1!=0)
				{
					CCR2=HAL_TIM_ReadCapturedValue(&htim8, TIM_CHANNEL_2);
					frequency=(float)cnt_clk/(CCR1+1);
					duty_cycle=(float)(CCR2+1)*100/(CCR1+1);	
					end_flag=1;
				}
				else
				{
					frequency=0;
					duty_cycle=0;
				}
}

在这里插入图片描述

串口调试助手打印的结果基本正确
注意事项
1、 PWM模式只能使用通道1和通道2
2、能捕获的最低频率f=(时钟频率/(分频系数PSC+1))/(重装载值ARR+1)
f=(72000000/(71+1))/(65535+1)=15.2HZ

▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂
二、普通输入捕获模式

  • 5
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
对于 STM32F103ZET6,它是一款基于 ARM Cortex-M3 内核的微控制器。该芯片具有多个定时器,可以用于生成 PWM 信号。下面是一种实现多路 PWM 输出的方法: 1. 配置定时器:选择一个可用的定时器(例如 TIM1、TIM2、TIM3 等),并根据需要配置定时器的工作模式和时钟源。 2. 配置 GPIO 引脚:选择要输出 PWM 信号的 GPIO 引脚,并将其配置为替代功能模式。 3. 配置 PWM 输出:根据需要,配置定时器的通道为 PWM 模式,并设置相应的占空比频率。 4. 启动定时器:启动定时器以开始生成 PWM 信号。 这是一个基本的框架,你可以根据具体需求进行调整。以下是一个简单的示例代码,演示如何使用 STM32Cube HAL 库在 STM32F103ZET6 上实现两路 PWM 输出: ```c #include "stm32f1xx_hal.h" TIM_HandleTypeDef htim1; TIM_HandleTypeDef htim2; void MX_TIM1_Init(void); void MX_TIM2_Init(void); int main(void) { HAL_Init(); MX_TIM1_Init(); MX_TIM2_Init(); // 启动定时器 HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); // 设置占空比 __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 50); __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, 75); while (1) { // 主循环 } } void MX_TIM1_Init(void) { TIM_OC_InitTypeDef sConfigOC; htim1.Instance = TIM1; htim1.Init.Prescaler = 0; htim1.Init.CounterMode = TIM_COUNTERMODE_UP; htim1.Init.Period = 999; htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; HAL_TIM_PWM_Init(&htim1); sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 0; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1); } void MX_TIM2_Init(void) { TIM_OC_InitTypeDef sConfigOC; htim2.Instance = TIM2; htim2.Init.Prescaler = 0; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 999; htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; HAL_TIM_PWM_Init(&htim2); sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 0; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1); } ``` 在这个示例中,使用了 TIM1 和 TIM2 定时器,分别控制两个 PWM 输出通道(TIM_CHANNEL_1)。你可以在 MX_TIM1_Init 和 MX_TIM2_Init 函数中根据需要进行配置。注意修改占空比的值以控制 PWM 输出的电平。 需要注意的是,这只是一个简单的示例代码,实际应用中可能还需要进行其他配置和处理。请根据你的具体需求进行进一步的开发和调整。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值