STM32L4 HAL库实现TIM ETR计数测频率

2019-07-20 23:17发布

最近看了一篇高精度高频频率测量的文章,觉得写的很好,于是打算按照文章进行实现。
一开始的思路是用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倍,只是理论分析,没有实测,不知道精度如何。



友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
7条回答
lvkanger
1楼-- · 2019-07-21 03:35
芯片型号STM32L431CCT6
正点原子
2楼-- · 2019-07-21 08:48
帮顶
lvkanger
3楼-- · 2019-07-21 12:39
用定时器翻转IO口产生1个50KHz的波,接到TIM1 ETR脚上进行测量,测量值正好是fq=50000,说明此种方法的测量精度还是比较高的。
1S钟1次中断还是可以接受的。如果觉得中断太频繁可以用PDF里的方法进行实现。
lvkanger
4楼-- · 2019-07-21 17:31
 精彩回答 2  元偷偷看……
正点原子
5楼-- · 2019-07-21 18:25
 精彩回答 2  元偷偷看……
liwenyao24
6楼-- · 2019-07-22 00:01
请问,TIM1_Handler这个变量是自己定义的吗?我在keil里直接使用,发现找不到这个变量。

一周热门 更多>