STM32 多路PWM信号频率检测

这星期老师让给项目中添加一个检测输入信号频率的功能,用于矿下煤气浓度检测,于是搞了几天做成了一个样例,由于电路板的限制,用的是TIM3和TIM4。
这个程序最多支持8路不通频率信号的测量,由于有实际要求,我把测量的频率设定在1000~200Hz之间,当然测更高的频率也行,只是我没有测试过2000Hz以上的信号。

频率检测的原理

怎么编程需要看懂下面这张定时器输入捕获结构图,我只进行了最低限度的解释,要了解更多推荐看看野火的《零死角玩转STM32F103指南者》高级定时器那一章。
输入捕获部分结构
使用 STM32 一定要找到参考手册、数据手册或者其他参考书,不然寸步难行。
这里先说一下怎么进行信号捕获
0.TIMx一直在计数
1.信号通过 TIMx_CH1/2/3/4 流入
2.经过滤波器和边沿检测
3.信号进入捕获通道
4.经过预分频器
5.捕获寄存器在发生捕获时存储 CNT 的值,产生 CCxI 中断

首先借助于定时器的输入捕获的4个通道的边沿捕获功能,检测到上升沿后出发 CI 中断。
以 TIM3 的 CH1 为例,它检测到第一个上升沿后,我们用变量 cnt_val 记录一下 CNT(计数器) 的值。
当 CH1 遇到第二次遇到上升沿时,TIM3->CCR1 寄存器记录下此时 CNT 的值,我们用一个变量 ccr_val 记录一下。
然后退出中断, ( ccr_val - cnt_val ) 的值就是一个周期内 TIM3 计数的次数(忽略计数器更新),用变量 c_num 记录。接着用 TIM3 的计时频率 / c_num 可以得出频率的值。
检测原理描述
从上面的图中可以看出,假如捕获信号的一个周期内定时器发生了更新,那这次采集就算失败,因为更新后CNT重新计数了。
还有一种情况是信号源突然掉线,所以需要定时进行在线检测。
目前我没想到其它的bug。

GPIO初始化

我用到了两个计时器,这里我只拿一个TIM3举例子,下面用到了很多宏定义,是为了方便我开关某些功能。

#define USE_TIM3			  1
#define USE_TIM3_CH1          1
#define USE_TIM3_CH2          1
#define USE_TIM3_CH3          1
#define USE_TIM3_CH4          1
#define TIM3_IT_CCx						/**/TIM_IT_CC1|TIM_IT_CC2|TIM_IT_CC3|TIM_IT_CC4/*注意要与上面的通道向对应*/
#define TIM3_GPIO_CLK 	RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB 

static void TIM3_GPIO_Config(void)
{
   
	GPIO_InitTypeDef GPIO_InitStructure;
  //GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE);//TIM3 端口重映射,我用不上
  //GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);	//禁止JTAG功能,把PB3,PB4作为普通IO口使用,我也用不上
	RCC_APB2PeriphClockCmd(TIM3_GPIO_CLK,ENABLE);//开启对应GPIO的时钟,TIM3_GPIO_CLK是宏定义
#if USE_TIM3_CH1
	//配置CH1 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
	GPIO_InitStructure.GPIO_Pin = TIM3_CH1_PIN;
	GPIO_Init(TIM3_CH1_PORT,&GPIO_InitStructure);
#endif
	
#if USE_TIM3_CH2
	//配置CH2 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Pin = TIM3_CH2_PIN;
	GPIO_Init(TIM3_CH2_PORT,&GPIO_InitStructure);
#endif
	
#if USE_TIM3_CH3
	//配置CH3 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Pin = TIM3_CH3_PIN;
	GPIO_Init(TIM3_CH3_PORT,&GPIO_InitStructure);
#endif

#if USE_TIM3_CH4
	//配置CH4 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Pin = TIM3_CH4_PIN;
	GPIO_Init(TIM3_CH4_PORT,&GPIO_InitStructure);
#endif
}

定时器初始化

同样,只拿一个TIM3举例

static void GENERAL_TIM3_Config(void)
{
   
	//配置引脚,就是上面的那个函数
	TIM3_GPIO_Config();
	//配置时基
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	//初始化TIM3时钟72MHz
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	
	TIM_TimeBaseInitStructure.TIM_Prescaler = 72-1;	//分频 72M/72 = 1MHz
	TIM_TimeBaseInitStructure.TIM_Period = 0xffff-1;  //计时周期65535  计时器的一个周期是(1s/1M)*65535 =  0.0656s即65ms
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;	//配置为1分频
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//配置为向上计数模式
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重复计数器,TIM3没有
	
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值