stm32学习笔记:TIIM-输入捕获

输入捕获理论

4个输入捕获和输出比较通道,共用4个CCR寄存器

另外它们的CH1到CH4,4个通道的引脚,也是共用的。

所以对于同一个定时器,输入捕获和输出比较只能使用其中一个,不能同时使用。

电平跳变:上升沿或下降沿
脉冲间隔:频率
电平持续:占空比
输入引脚电平跳变的瞬间,把CNT的值锁存在CCR中(把当前CNT的值读出来,写入到CCR中去) 

定时器的计数器CNT在不停地计数,当选定的输入引脚上出现了设定的上升沿或下降沿时,把CNT的值记录到CCR中。

CCR是捕获和比较共用的,当使用输入捕获时,它就是捕获寄存器,当使用输出比较时,它就是比较寄存器

CNT计数自增,CCR是我们给定的一个值

上图,这4个是边沿信号输入引脚,一旦有边沿,比如上升沿,那这一块输入滤波和边沿检测就会检测到这个上升沿,让输入捕获电路产生动作。与外部中断类似,检测电平跳变,然后执行动作,只不过外部中断执行的动作是向CPU申请中断,而这里电路执行的动作就是控制后续电路,让当前CNT的值,锁存到CCR寄存器中

输入捕获和输出比较的区别

1、输出比较,是根据CNT和CCR大小关系来执行输出动作;
2、输入捕获,接收到输入信号,执行CNT锁存到CCR的动作。

频率测量相关知识

1、测频法(适用于高频)
在1s时间内,对信号上升沿计次,从0开始计算,每来一个上升沿(即来了一个周期的信号),计次+1。1s时间内,来了多少个周期,就是多少Hz。

频率的定义:1s内出现了多少个重复的周期,频率就是多少Hz。

2、测周法(适用于低频)

首先捕获信号的两个上升沿,然后测量它们之间的持续时间,但实际上我们并没有精度无穷大的秒表来测量时间,测量时间的方法实际上也是定时器计次,我们使用一个已知的标准频率fc的计次时钟,来驱动计数器,从一个上升沿开始计,计数器从0开始,一直计到下一个上升沿,停止,计一个数的时间是1/fc,计N个数,时间就是N/fc(周期),再取个倒数,就是fx = fc / N(频率)。

总结:测频法,适合测量高频信号,测周法,适合测量低频信号。

 输入捕获的各部分电路

第一个捕获通道,使用上升沿触发,用来捕获周期;第二个通道,使用下降沿触发,用来捕获占空比,两个通道同时对一个引脚进行捕获,就可以同时测量频率和占空比。

一个通道灵活测量两个引脚和两个通道同时捕获一个引脚,这就是交叉的作用。

TRC信号可以选择作为捕获部分的输入,主要为了无刷电机的驱动。

预分频器,每个通道各有一个,可以选择对前面的信号进行分频,分频之后的触发信号,可以触发捕获电路进行工作,每来一个触发信号,CNT的值就会向CCR转运一次,转运的同时会发生一个捕获事件,这个事件会在状态寄存器置标志位,同时也可以产生中断。如果需要在捕获的瞬间,处理一些事情,就可以开启捕获中断。

比如我们可以配置上升沿触发捕获,每来一个上升沿,CNT转运到CCR一次,又因为CNT计数器是由内部的标准时钟驱动的,所以CNT的数值,可以用来记录两个上升沿之间的时间间隔,这个时间间隔就是周期,再取个周期的倒数就是测周法测量的频率。 

升沿用于触发输入捕获,CNT用于计数计时,每来一个上升沿,取一下CNT的值,自动存在CCR里,CCR捕获到的值,就是计数值N,CNT的驱动时钟就是fc,fc/N就是待测信号的频率。细节:每次捕获之后都需要把CNT清零,这样下一次上升沿的时候,取出的CNT才是两个上升沿的时间间隔,在一次捕获后自动清零的步骤可以用主从触发模式自动来完成

滤波器工作原理:以采样频率对输入信号进行采样,当连续N个值都为高电平,输出才为高电平,连续N个值为低电平,输出才为低电平,如果信号出现高频抖动,导致连续采样N个值不全都一样,那输出就不会变化,这样就可以达到滤波的效果。采样频率越低,采样个数N越大,滤波效果就越好。 

TI1就是CH1的引脚,TI1F就是滤波后的信号,fDTS是滤波器的采样时钟来源,CCMR1寄存器的ICF位可以控制滤波器的参数 

主模式:可以将定时器内部的信号,映射到TRGO引脚,用于触发别的外设

从模式:接收其他外设或者自身外设的一些信号,用于控制自身定时器的运行,也就是被别的信号控制

触发源选择:选择从模式的触发信号源,选择指定的一个信号得到TRGI,TRGI去触发从模式,从模式可以在以上列表选择一项操作来自动执行。 如果想让TI1FP1信号自动触发CNT清零,那触发源选择就可以选择TI1FP1,从模式执行的操作就可以选择执行Reset的操作。 这样TI1FP1的信号就可以自动触发从模式,从模式自动清零CNT,实现硬件全自动测量。

以上三个东西对应库函数的三个函数,调用参数即可。
 

输入捕获基本结构

这个结构只使用了一个通道,所以目前只能测量频率,在右上角是时基单元,将时基单元配置好,启动定时器,CNT就会在预分频之后的这个时钟驱动下,不断自增,这个CNT就是测周法用来计数计时的东西,经过预分频之后这个位置的时钟频率就是驱动CNT的标准频率fc=72M/(PSC+1)。

然后下面输入捕获通道1的GPIO口,输入一个这样的方波信号,经过滤波器和边沿检测,选择TI1FP1为上升沿触发,之后输入选择智联的通道,分频器选择不分频,当TI1FP1出现上升沿之后,==CNT的当前计数值转运到CCR1里,==同时触发源选择,选中TI1FP1为触发信号,从模式选择复位操作,这样TI1FP1的上升沿也会通过上面一路。

==先后顺序:==先转运CNT的值到CCR里,再触发从模式给CNT清零,或者是非阻塞的同时转移,CNT的值转移到CCR,同时0转移到CNT里,先捕获再清零

信号出现一个上升沿,CCR1=CNT,就是把CNT的值转运到CCR1里面去,这是输入捕获自动执行的,然后CNT=0,清零计数器,这是从模式自动执行的。然后在一个周期内,CNT在标准时钟的驱动下,不断自增,并且由于之前清零过,所以CNT就是从上升沿开始,从0开始计时,一直++,直到下一次上升沿来临,然后执行相同的操作。CCR1始终保持为最新一个周期的计数值。这个计数值就是计次N,fc/N就是信号的频率。

PWMI基本结构

PWMI模式使用了两个通道同时捕获一个引脚,可以同时测量周期和占空比。

首先,TI1FP1配置上升沿触发,触发捕获和清零CNT,正常地捕获周期。这时TI1FP2配置为下降沿触发,通过交叉通道,去触发通道2的捕获单元。 

最开始上升沿,CCR1捕获,CCR1捕获,同时清零CNT,之后CNT一直++,然后再下降沿时刻,触发CCR2捕获,所以CCR2的值,就是CNT从a到b的计数值,就是高电平期间的计数值。CCR2捕获并不触发CNT清零,所以CNT继续++,直到下一次上升沿,CCR1捕获周期,CNT清零,此时,CCR1就是一整个周期的计数值。占空比:CCR2/CCR1。
 

输入捕获的编程步骤 

第一步,RCC开启时钟,把GPIO和TIM的时钟打开

第二步,GPIO初始化,把GPIO配置成输入模式,一般选择上拉输入或者浮空输入模式

第三步,配置时基单元,让CNT计数器在内部时钟的驱动下自增运行

第四步,配置输入捕获单元,包括滤波器、极性、直连通道还是交叉通道、分频器等参数

第五步,选择从模式的触发源,触发源选择为TI1FP1,调用库函数,给定一个参数即可

第六步,选择从模式触发后的执行操作,执行Reset操作,这里调用库函数即可

最后,调用TIM_Cmd函数,开启定时器

主要函数

//输入捕获,通过结构体配置输入捕获单元,4个通道公用一个函数,在结构体里会额外有一个参数,可以用来选择具体是配置哪个通道
//因为有交叉通道,函数合在一起比较方便
TIM_ICInit//输入捕获的初始化函数,与上一个函数类似,都是用于初始化输入捕获单元,
//但是上一个函数只是单一地配置一个通道,
//而这个函数可以快速配置两个通道
TIM_PWMIConfig//可以给输入捕获结构体赋初始值
TIM_ICStructInit//选择输入触发源TRGI
TIM_SelectInputTrigger//选择输出触发源
TIM_SelectOutputTrigger//选择从模式
TIM_SelectSlaveMode//分别单独配置通道1、2、3、4的分频器
void TIM_SetIC1Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC2Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC3Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC4Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);//分别读取4个通道的CCR
uint16_t TIM_GetCapture1(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture2(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture3(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture4(TIM_TypeDef* TIMx);/*
输出比较模式下,CCR是只写的,要用SetCompare写入,
输入捕获模式下,CCR是只读的,要用GetCapture读出
*/

代码

main.c
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"
#include "IC.h"int main(void)
{OLED_Init();PWM_Init();IC_Init();OLED_ShowString(1,1,"Freq:00000Hz");//以下两行代码是PA0输出频率和占空比的参数调节部分/*PWM模块将待测信号输出到PA0,PA0有通过导线输入到PA6,PA6时TIM3的通道1*/PWM_SetPrescaler(720-1);  //Freq =  72M/(PSC + 1)/(ARR+1)   = 72M/(PSC + 1)/ 100 = 1KPWM_SetCompare1(50);      //Duty = CCR / (ARR + 1) = 50 / 100 = 50%/*TIM3的通道1通过输入捕获模块测量得到频率*/while(1){//在主循环里不断刷新显示频率OLED_ShowNum(1,6,IC_GetFreq(),5);}
}
PWM.c
#include "stm32f10x.h"                  // Device headervoid PWM_Init(void)
{RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
//	GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);    //引脚重映射配置函数,部分重映射,可将PA0换到PA15
//	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);  //关闭调试端口的复用GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;		//GPIO_Pin_15;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化时基单元TIM_InternalClockConfig(TIM2);TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;		//ARR周期TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1;		//PSC预分频器TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);//初始化输出比较单元(即初始化通道)TIM_OCInitTypeDef TIM_OCInitStructure;//给结构体赋初始值,如果不想把所有成员都列一遍赋值,可以先用structInit赋值,再更改想要修改的值TIM_OCStructInit(&TIM_OCInitStructure);TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;          //输出比较模式,PWM模式1TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;  //设置输出比较的极性,高极性,就是极性不翻转,REF波形直接输出TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;  //设置输出使能TIM_OCInitStructure.TIM_Pulse = 0;		//设置CCR//在TIM2的OC1通道上就可以输出PWM波形了,但最终这个波形需要借用GPIO口才能输出TIM_OC1Init(TIM2, &TIM_OCInitStructure);TIM_Cmd(TIM2, ENABLE);
}
//该函数单独设置CCR值。 
void PWM_SetCompare1(uint16_t Compare)
{TIM_SetCompare1(TIM2, Compare);
}
//该函数单独设置PSC值
void PWM_SetPrescaler(uint16_t Prescaler)
{//配置PSC库函数TIM_PrescalerConfig(TIM2, Prescaler, TIM_PSCReloadMode_Immediate);
}
PWM.h
#ifndef __PWM_H
#define __PWM_Hvoid PWM_Init(void);                    //PWM初始化                  
void PWM_SetCompare1(uint16_t Compare); //设置CCR,改变占空比
void PWM_SetPrescaler(uint16_t Prescaler);  //设置PSC,改变频率#endif
IC.c
#include "stm32f10x.h"void IC_Init(void)
{//1、开启时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);  //由于代码需要TIM2输出PWM,因此,输入捕获定时器需要换一个,此处换为TIM3,TIM3是APB1的外设RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  //GPIO的使用需要查看引脚定义//2、配置GPIOGPIO_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);//3、配置时基单元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 = 65535 - 1;		//ARR周期,给最大值,防止溢出,16位计数器可以满量程计数TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;		//PSC预分频器,这个值决定测周法的标准频率fc,72M/预分频 = 1Mhz,就是计数器自增的频率,就是计数标准频率TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);  //把以上参数配置为TIM3的时基单元//4、初始化输入捕获单元TIM_ICInitTypeDef TIM_ICInitStruct;TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;  //选用TIM3的通道1TIM_ICInitStruct.TIM_ICFilter = 0xF;   //用于选择输入捕获的滤波器TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising; //对应边沿检测极性选择这一部分TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;  //此处不分频,不分频就是每次触发都有效,2分频就是每个一次有效一次,以此类推TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI; //此处选择直连通道,配置数据选择器,可以选择直连通道或者交叉通道TIM_ICInit(TIM3,&TIM_ICInitStruct);//5、配置TRGI的触发源为TI1FP1TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);//6、配置从模式为Reset,给计数器清零,以便重新计数TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);//最后一步TIM_Cmd(TIM3,ENABLE);}/*自此,初始化后,整个电路就能全自动测量,当我们要查看频率时,需要读取CCR,进行计算,*///当需要查看频率时,需要读取CCR,进行计算
uint32_t IC_GetFreq(void)
{//fc=72/(PSC + 1)= 1MHZ//执行公式fx = fc / N//N 就是读取CCR的值//TIM_GetCapture1读取定时器3的通道1的CCR的值//输出比较模式下,CCR是只写的,要用setCompare写入//输入捕获模式下,CCR是只读的,要用GetCapture读出return 1000000 / (TIM_GetCapture1(TIM3)+1);}
IC.h
#ifndef __IC_H
#define __IC_H
void IC_Init(void);
uint32_t IC_GetFreq(void);#endif

PWM模式测频率占空比

继承上一个代码,首先开启时钟,GPIO和时基单元,都不需要更改,输入捕获初始化部分需要升级,配置成两个通道同时捕获同一个引脚的模式。 

代码

main.c
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"
#include "IC.h"int main(void)
{OLED_Init();PWM_Init();IC_Init();OLED_ShowString(1,1,"Freq:00000Hz");OLED_ShowString(2,1,"Duty:00%");/*PWM模块将待测信号输出到PA0,PA0有通过导线输入到PA6,PA6时TIM3的通道1*/PWM_SetPrescaler(720-1);  //Freq =  72M/(PSC + 1)/(ARR+1)   = 72M/(PSC + 1)/ 100 = 1KPWM_SetCompare1(50);      //Duty = CCR / (ARR + 1) = 50 / 100 = 50%/*TIM3的通道1通过输入捕获模块测量得到频率*/while(1){//在主循环里不断刷新显示频率OLED_ShowNum(1,6,IC_GetFreq(),5);OLED_ShowNum(2,6,IC_GetDuty(),2);}
}
//	PWM_SetPrescaler(7200-1);  //Freq =  72M/(PSC + 1)/(ARR+1)   = 72M/(PSC + 1)/ 100 = 100
//	PWM_SetCompare1(80);      //Duty = CCR / (ARR + 1) = 80 / 100 = 80%
PWM.c
#include "stm32f10x.h"                  // Device headervoid PWM_Init(void)
{RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
//	GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);    //引脚重映射配置函数,部分重映射,可将PA0换到PA15
//	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);  //关闭调试端口的复用GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;		//GPIO_Pin_15;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化时基单元TIM_InternalClockConfig(TIM2);TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;		//ARR周期,此处固定为100,分辨率为1%TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1;		//PSC预分频器,可改变PSC,决定频率TIM_TimeBaseInitStructure.TIM_RepetitionCounter =  0;TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);//初始化输出比较单元(即初始化通道)TIM_OCInitTypeDef TIM_OCInitStructure;//给结构体赋初始值,如果不想把所有成员都列一遍赋值,可以先用structInit赋值,再更改想要修改的值TIM_OCStructInit(&TIM_OCInitStructure);TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;          //输出比较模式,PWM模式1TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;  //设置输出比较的极性,高极性,就是极性不翻转,REF波形直接输出TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;  //设置输出使能TIM_OCInitStructure.TIM_Pulse = 0;		//设置CCR,决定占空比//在TIM2的OC1通道上就可以输出PWM波形了,但最终这个波形需要借用GPIO口才能输出TIM_OC1Init(TIM2, &TIM_OCInitStructure);TIM_Cmd(TIM2, ENABLE);
}
//前提固定了ARR的值
//该函数单独设置CCR值,改变占空比
void PWM_SetCompare1(uint16_t Compare)
{TIM_SetCompare1(TIM2, Compare);
}
//该函数单独设置PSC值,改变频率
void PWM_SetPrescaler(uint16_t Prescaler)
{  //配置PSC库函数TIM_PrescalerConfig(TIM2, Prescaler, TIM_PSCReloadMode_Immediate);  //TIM_PSCReloadMode_Immediate 表明写入的值是立刻生效,可能会在值改变时产生切断波形的现象//TIM_PSCReloadMode_Update    表明写入的值在更新事件生效,会有一个缓存器,延迟参数的写入时间,等一个周期结束了,在更新事件时,再统一改变参数,保证每个周期的完整。
}
IC.c

通道1,直连输入,上升沿触发,测周期,
通道2,交叉输入,下降沿触发,测占空比,

#include "stm32f10x.h"void IC_Init(void)
{//1、开启时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);  //由于代码需要TIM2输出PWM,因此,输入捕获定时器需要换一个RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//2、配置GPIOGPIO_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);//3、配置时基单元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 = 65535 - 1;		//ARR周期,给最大值,防止溢出,16位计数器可以满量程计数TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;		//PSC预分频器,这个值决定测周法的标准频率fc,72M/预分频,就是计数器自增的频率,就是计数标准频率TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);  //把以上参数配置为TIM3的时基单元//4、初始化输入捕获单元TIM_ICInitTypeDef TIM_ICInitStruct;TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;  //选用TIM3的通道1TIM_ICInitStruct.TIM_ICFilter = 0xF;   //用于选择输入捕获的滤波器TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;  //不分频就是每次触发都有效,2分频就是每个一次有效一次,以此类推TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI; //配置数据选择器,可以选择直连通道或者交叉通道TIM_PWMIConfig(TIM3,&TIM_ICInitStruct);  //可快速配置两个通道,把玩蛇电路结构配置成PWMI模式,//5、配置TRGI的触发源为TI1FP1TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);//6、配置从模式为ResetTIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);//最后一步TIM_Cmd(TIM3,ENABLE);}/*自此,初始化后,整个电路就能全自动测量,当我们要查看频率时,需要读取CCR,进行计算,*/
uint32_t IC_GetFreq(void)
{//fc=72/(PSC + 1)= 1MHZ//执行公式fx = fc / Nreturn 1000000 / (TIM_GetCapture1(TIM3)+1);}
//获取占空比的函数
uint32_t IC_GetDuty(void)
{//高电平的计数值存在CCR2里//整个周期的计数值存在CCR1里,占空比=CCR2/CCR1即可//显然该数是0~1,要显示整数,给他乘以100return (TIM_GetCapture2(TIM3)+1)* 100 / (TIM_GetCapture1(TIM3) + 1); //TIM_GetCapture2捕获CCR2,TIM_GetCapture1捕获CCR1//少一个数有没有可能是因为计数器CNT是从0开始计数的呢???
}
IC.h
#ifndef __IC_H
#define __IC_H
void IC_Init(void);
uint32_t IC_GetFreq(void);
uint32_t IC_GetDuty(void);#endif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/325096.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

个人调用OCR

一、自己训练模型 二、调用现成API 此处介绍百度智能云API,因为有免费次数。(原来一些网址在百度不是默认显示网址的,而是自己的网站名字) 首页找到OCR 每个人每月能用1K次。(有详细的API文档说明,不过跟…

在Uniapp中使用Echarts创建可视化图表

在uniapp中可以引入echarts创建数据可视化图表。 1. 安装Echarts 使用npm安装echarts插件,命令如下: npm install echarts --save2. 引入Eharts 在需要使用Echarts的页面引入: import *as echarts from echarts3. 创建实例 创建画布元素…

【产品应用】一体化伺服电机在管道检测机器人中的应用

一体化伺服电机在管道检测机器人的应用正日益受到关注。管道检测机器人是一种能够在管道内部进行检测和维护的智能化设备,它可以检测管道的内部结构、泄漏、腐蚀等问题,以确保管道的安全和稳定运行。而一体化伺服电机作为机器人的动力源,对于…

【AI视野·今日CV 计算机视觉论文速览 第281期】Tue, 2 Jan 2024

AI视野今日CS.CV 计算机视觉论文速览 Tue, 2 Jan 2024 Totally 95 papers 👉上期速览✈更多精彩请移步主页 Daily Computer Vision Papers Refining Pre-Trained Motion Models Authors Xinglong Sun, Adam W. Harley, Leonidas J. Guibas考虑到在视频中手动注释运…

在vue3中使用Cesium保姆篇

1.首先新建一个vue项目 Vue.js - 渐进式 JavaScript 框架 | Vue.js 可以直接到管网中查看命令通过npm来创建一个vue3的项目 然后通过命令下载1.99的版本的cesium和plugin npm i cesium1.99 vite-plugin-cesium 下载完了以后 2.引入cesium 首先找到vue的vite.config.js …

C# OpenCvSharp DNN FreeYOLO 目标检测

目录 效果 模型信息 项目 代码 下载 C# OpenCvSharp DNN FreeYOLO 目标检测 效果 模型信息 Inputs ------------------------- name:input tensor:Float[1, 3, 192, 320] --------------------------------------------------------------- Outp…

【力扣每日一题】1944队列中可以看到的人数

目录 题目来源 题目描述 示例 提示: 思路分析 总结 代码实现 java实现 c实现 得分情况 java c p.s.吐槽一点无足轻重的事情 题目来源 力扣1944队列中可以看到的人数 题目描述 有 n 个人排成一个队列,从左到右 编号为 0 到 n - 1 。给你以…

综合医院信息系统源码,HIS源码,(HIS+LIS+电子病历系统)正版授权,可商用

基层医院云HIS系统源码,二级综合医院信息系统源码,HIS源码,正版授权,可项目使用 一、云HIS系统介绍: 一款满足基层医院各类业务需要的云HIS系统。该系统能帮助基层医院完成日常各类业务,提供病患挂号支持、…

大师学SwiftUI第6章 - 声明式用户界面 Part 1

状态 在上一章,我们介绍了SwiftUI的主要特性,声明式语法。借助SwiftUI,我们可以按希望在屏幕上显示的方式声明视图,余下交由系统来创建所需的代码。但声明式语法不只用于组织视图,还可在应用状态发生变化时更新视图。…

南金研小巧的CAN总线记录仪在冬测中的使用

南金研小巧的CAN总线记录仪在冬测中的使用: 在这里插入图片描述 1.确定需求:在开始使用前,需要明确冬测的具体需求,例如需要记录的CAN总线数据类型、采样率、存储容量等。 2.连接硬件:将小巧的CAN总线记录仪与需要进行…

普中STM32-PZ6806L开发板(有点悲伤的故事续-人灯还未了)

简介 继上篇 普中STM32-PZ6806L开发板(有点悲伤的故事) 说到 关于 普中STM32-PZ6806L开发板的LED流水灯也被烧坏掉了,再也无法玩流水灯, 内心充满了只会流水灯的不甘, 流水灯就是单片机的Hello World,怎么能没有呢? 事情发展 好巧不巧想起最近…

紫光展锐5G扬帆出海 | 欧洲积极拥抱更多5G选择

和我国一样,欧洲不少国家也在2019年进入5G商用元年:英国在2019年5月推出了5G商用服务,该国最大的移动运营商EE(Everything Everywhere)最先商用5G;德国在2019年年中推出5G商用服务,德国电信、沃达丰和 Telefonica是首批…