stm32-输入捕获模式测频率,PWMI模式测频率占空比

一、知识点

TIM输入捕获模式:
1.输入捕获模式测频率占空比
无信号发生器:先用PWM模块,在PA0端口输出一个频率和占空比可调的波形,把PA0和PA6连在一起,PA6为输入波形,相当于自己测自己。
2.PWMI模式测频率占空比

1.IC(Input Capture)输入捕获

输入捕获模式下,当通道输入引脚出现指定电平跳变时,当前CNT的值将被锁存到CCR中

2.通用定时器结构

在这里插入图片描述
左边为输入捕获,右边为输出捕获。

a.四个输入捕获和输出比较通道

由上图可知,一共由四个CCR寄存器,一共有四个通道,其中每个通道的输入输出模式都是共用的。所以对于同一个定时器,输入捕获和输出比较只能用一个。

b.输入捕获的作用

测PWM波形的频率、占空比等参数

c.输入和输出的区别

输出比较:引脚是输出端口,根据CNT和CCR的大小关系来执行输出动作
输入捕获:引脚是输入端口,接收到输入信号,执行CNT锁存到CCR的动作

d.PWMI模式

PWMI模式是PWM的输入模式,专门为测量PWM频率和占空比设计的。

e.主从触发模式

将输入捕获和PWMI模式结合起来,实现测频率占空比硬件全自动执行,可减轻软件的压力

3.测频法和测周法测量频率

在这里插入图片描述

a.原理

测频法:定义一个时间T,比如在1s的时间内,有N个周期,就有N/T赫兹
测周法:周期测量(使用一个已知频率fc的计次时钟,来驱动计数器,来一个上升沿就开始计数,记一个数的时间为1/fc,假设到下一个上升沿时计数为N,这时间为N/fc,那么频率为fc/N)

b.方法选择

中介频率:让两个方法的N相等,即可求出。
测频法适合高频信号,(N很大则误差小);
测周法适合低频信号,(N很大,则误差小);

c.方法实现

测频法的思路:之前的对射式红外传感器计次计次,每来一个上升沿计次1,再用有一个定时器,每隔1s中断,再中断中,每隔1s取一次计次值,同时清0计次,为下一次做准备,这样每次读取的计次值就是频率

定时器外部时钟也同理,每隔1s取一次计次,就能实现

测周法:(见本次代码)

4.主从触发模式

在这里插入图片描述

主模式:可以将定时器内部的信号映射到TRGO引脚上,用于触发别的外设
从模式:可以接收其他外设或者自身外设的一些信号,来实现一些功能(被控制)
触发源选择:选择从模式的触发信号源,可以认为是从模式的一部分,通过一个信可以触发从模式
  • 若想让TI1FP1信号自动触发CNT清零,触发源一个选择TI1FP1,从模式选择执行Reset的操作,这样TI1FP1信号就可以自动触发从模式,从模式自动清零CNT,实现硬件全自动测量

二、实例

1.输入捕获基本结构

在这里插入图片描述

  • RCC开启时钟
  • 配置GPIO,设置为上拉输入
  • 配置时基单元
  • 配置输入捕获单元,包括滤波器,级联,直联,分频器等
  • 选择重模式触发源,触发源选择为TIFP1
  • 选择触发之后的:RESET
  • 开启TIM_CMD定时器

2.PWMI基本结构

在这里插入图片描述
占空比:CCR2/CCR1

3.代码 (输入捕获测频率)

IC.c

#include "stm32f10x.h"                  // Device header

void IC_Init(void)
{
	//TIM3
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	//配置GPIO口
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;  //上拉模式
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;		//PA6
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	TIM_InternalClockConfig(TIM3);
	//配置时基模块
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1;		//ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;		//PSC
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
	//配置输入捕获单元
	TIM_ICInitTypeDef TIM_ICInitStructure;
	TIM_ICInitStructure.TIM_Channel=TIM_Channel_1;  /选择通道1
	TIM_ICInitStructure.TIM_ICFilter=0xF;  //数越大,滤波效果越好
	TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;  //上升沿触发
	TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;  //分频
	TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;  //直连通道
	TIM_ICInit(TIM3,&TIM_ICInitStructure);
	//选择重模式触发源
	TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);
	//选择触发后的执行操作
	TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);	
	//使能时钟
	TIM_Cmd(TIM3,ENABLE);
}

uint32_t IC_GetFreq(void)
{
   //fc除N
	return 1000000/TIM_GetCapture1(TIM3);
}

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"
#include "IC.h"                  // Device header


uint8_t i;

int main(void)
{
	OLED_Init();
	PWM_Init();
	IC_Init();
	
	OLED_ShowString(1,1,"Freq:00000Hz");

	PWM_SetCompare1(50);   //占空比:  CCR/100
	PWM_SetPrescaler(720-1);  //频率(Freq:72M/(PSC+1)/100)
	while(1)
	{
		OLED_ShowNum(1,6,IC_GetFreq(),5);
	}
}

4.代码(PWMI模式测占空比)

IC.h

#include "stm32f10x.h"                  // Device header

void IC_Init(void)
{
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;		//GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	TIM_InternalClockConfig(TIM3);
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1;		//ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;		//PSC
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
	
	TIM_ICInitTypeDef TIM_ICInitStructure;
	TIM_ICInitStructure.TIM_Channel=TIM_Channel_1;
	TIM_ICInitStructure.TIM_ICFilter=0xF;
	TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;
	TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;
	TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;
	TIM_ICInit(TIM3,&TIM_ICInitStructure);
	TIM_PWMIConfig(TIM3,&TIM_ICInitStructure);
	//该函数会自动把剩下的一个通道初始化成相反的配置,第一个为通道1,直连,上升沿;第二个为通道2,交叉,下降沿
	
	TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);
	TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);	
	
	TIM_Cmd(TIM3,ENABLE);
	 
}

uint32_t IC_GetFreq(void)
{
	return 1000000/TIM_GetCapture1(TIM3);
}

uint32_t IC_GetDuty(void)
{
	return (TIM_GetCapture2(TIM3)+1)*100/(TIM_GetCapture1(TIM3)+1);
}

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"
#include "IC.h"                  // Device header


int main(void)
{
	OLED_Init();
	PWM_Init();
	IC_Init();
	
	OLED_ShowString(1,1,"Freq:00000Hz");
	OLED_ShowString(2,1,"Duty:00%");
	PWM_SetCompare1(50);   //占空比:  CCR/100
	PWM_SetPrescaler(720-1);  //频率(Freq:72M/(PSC+1)/100)
	while(1)
	{
		OLED_ShowNum(1,6,IC_GetFreq(),5);
		OLED_ShowNum(2,6,IC_GetDuty(),2);
	}
}
  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32捕获占空比程序可以用于PWM信号的占空比,该程序适用于STM32系列微控制器。以下是一个简单的捕获占空比程序示例: 首先,你需要初始化相关的寄存器和引脚配置,以使得STM32能够捕获PWM信号。这可以通过设置GPIO引脚为输入模式、配置定时器和捕获比较寄存器等来实现。 然后,你需要配置定时器为输入捕获模式。定时器是用来计数PWM的高电平和低电平时间的。你需要设置计数时钟频率和计数器的位数。比如,如果你使用定时器3,可以将其设置为输入捕获模式,并启用输入捕获中断。 接下来,在捕获中断服务函数中,你可以读取定时器的捕获寄存器值。通常情况下,定时器在捕获到PWM的上升沿时会自动将计数值存储到捕获寄存器中。你可以读取两次捕获寄存器的值,第一次捕获到PWM的上升沿,第二次捕获到PWM的下降沿。 最后,你可以计算出占空比,即PWM的高电平时间与一个完整周期的比值。假设捕获到的上升沿计数值为Capture1,下降沿计数值为Capture2。占空比可以通过计算公式:占空比 = (Capture2 - Capture1) / Capture2 * 100% 来得到。 除了以上简单的捕获占空比程序示例,还可以通过使用对应的HAL库或者其他开发工具库来更方便地实现捕获占空比功能。这些库提供了现成的函数和接口,帮助你能够更加快速地开发和应用捕获占空比程序。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值