最近看了一篇高精度高频频率测量的文章,觉得写的很好,于是打算按照文章进行实现。
一开始的思路是用STM32L4的TIM2的ETR脚进行脉冲计数(前置电路已经把波形整理成方波),
TIM7进行定时1S钟去读取TIM2 CNT计数,这样CNT值就是测得的方波的频率。
代码实现的时候,用Debug模式查看寄存器值,也跟参考手册的寄存器进行了比较,确实没有什么问题。
TIM2使用PA0,PA5,PA15引脚都试过了,还是不行,真的不知道还能是什么原因,请各位大佬不吝赐教!
最后我是使用TIM1实现了我的方案,代码如下:
void TIM1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
TIM_ClockConfigTypeDef sClockSourceConfig;
HAL_TIM_Base_DeInit(&TIM1_Handler);
TIM1_Handler.Instance = TIM1; //通用定时器 2
TIM1_Handler.Init.Prescaler = 0; //分频系数,不分频72MHz
TIM1_Handler.Init.CounterMode=TIM_COUNTERMODE_UP; //向上计数器
TIM1_Handler.Init.Period=0xFFFF; //自动装载值
TIM1_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1; //时钟分频银子
HAL_TIM_Base_Init(&TIM1_Handler);
//设置位外部时钟2模式
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_ETRMODE2;
sClockSourceConfig.ClockPolarity = TIM_ETRPOLARITY_NONINVERTED;
sClockSourceConfig.ClockPrescaler = TIM_ETRPRESCALER_DIV1;
sClockSourceConfig.ClockFilter = 0x0;
HAL_TIM_ConfigClockSource(&TIM1_Handler, &sClockSourceConfig);
__HAL_TIM_SET_COUNTER(&TIM1_Handler,0);
HAL_TIM_Base_Start(&TIM1_Handler);
}
void TIM7_Init(u16 arr,u16 psc)
{
TIM7_Handler.Instance= TIM7; //通用定时器7
TIM7_Handler.Init.Prescaler=psc; //分频系数
TIM7_Handler.Init.CounterMode=TIM_COUNTERMODE_UP; //向上计数器
TIM7_Handler.Init.Period=arr; //自动装载值
TIM7_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;//时钟分频因子
HAL_TIM_Base_Init(&TIM7_Handler);
HAL_TIM_Base_Start_IT(&TIM7_Handler); //使能定时器7和定时器7更新中断:TIM_IT_UPDATE
TIM7_Enable();
}
//定时器底册驱动,开启时钟,设置中断优先级
//此函数会被HAL_TIM_Base_Init()函数调用
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(htim->Instance==TIM1)
{
__HAL_RCC_TIM1_CLK_ENABLE(); //使能 TIM1 时钟
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;//复用功能选择很重要,一定要对照数据手册修改
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}/**/
if(htim->Instance==TIM2)
{
}/**/
if(htim->Instance==TIM7)
{
__HAL_RCC_TIM7_CLK_ENABLE(); //使能TIM7时钟
HAL_NVIC_SetPriority(TIM7_IRQn,1,2); //设置中断优先级,抢占优先级1,子优先级3
HAL_NVIC_EnableIRQ(TIM7_IRQn); //开启ITM7中断
}
}
//定时器7中断服务函数
void TIM7_IRQHandler(void)
{
HAL_TIM_IRQHandler(&TIM7_Handler);
}
//回调函数,定时器中断服务函数调用
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim==(&TIM7_Handler))
{
//printf("TIM7
");
fq= __HAL_TIM_GET_COUNTER(&TIM1_Handler); //读取1s内计数器计的CNT值即是脉冲的频率
__HAL_TIM_SET_COUNTER(&TIM1_Handler,0);
}
/*if(htim==(&LPTIM1_Handler))
{
IWDG_Feed();
printf("TIM7
");
}*/
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART2_UART_Init();
delay_init(72); //延时函数初始化
TIM1_Init();
TIM7_Init((10000-1),7199);//定时器初始化10Khz 的计数频率7199
printf("SystemCoreClock = %d
",SystemCoreClock);
while(1)
{
printf("fq = %d
",fq);
LED_TOGGLE;
delay_ms(1000);
}/**/
}
最后用示波器产生的1KHz的标准方波进行采集测量,fq=1000,证明程序实现了功能。
TIM2与TIM1的区别是TIM2是32位的CNT,而TIM是16位的CNT,也就是说此种方法TIM1最大测频是60KHz左右,
有点遗憾,不过功能基本实现了。也没有60KHz左右的标准波进行测试,准备用IO口产生一个标准波形试一下。
如果想要再测更高频率,可以修改sClockSourceConfig.ClockPrescaler = TIM_ETRPRESCALER_DIV1;
进行分频,这样可以把测量范围提高几倍,
还可以把TIM7的定时时间缩短到100ms,这样测频范围也会扩大10倍,只是理论分析,没有实测,不知道精度如何。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
1S钟1次中断还是可以接受的。如果觉得中断太频繁可以用PDF里的方法进行实现。
一周热门 更多>