STM32外部时钟脉冲计数实验详解

STM32 外部时钟脉冲计数实验


文章目录

  • STM32 外部时钟脉冲计数实验
  • 前言
  • 1、实验原理
  • 2、开发板原理图
  • 2、定时器工作原理框图
  • 2、主要源码
  • 3、总结

  • 前言

    最近在学正点原子的HAL库视频,通用定时器脉冲计数功能的实现,以前都习惯用标准库了,所以现在尝试参考HAL库的原理用标准库的思想来实现这个功能。


    1、实验原理

    本实验使用外部时钟模式1,外部输入引脚作为定时器的时钟来源。
    使用开发板的 WK_UP 按键按下产生高电平脉冲作为定时器的计数器时钟来源,计数器工作在递增计数模式,那么每来一个上升沿信号,计数器就加一。即每按下一次按键产生一次高电平脉冲,计数器加一,一直计数到ARR的值溢出从新计数。

    2、开发板原理图

    2、定时器工作原理框图

    外部时钟源信号通过通道 1 输入后,TI1 分别要经过滤波器、边沿检测器后来到 TI1FP1,被触发输入选择器选择为触发源,接着来到从模式控制器,从模式选择为外部时钟模式 1,这时候外部时钟源信号就会到达时基单元的预分频器,最后,经过分频后就可作为计数器的计数时钟了。外部时钟源信号的边沿计数个数会保存到计数器寄存器中,需要时直接读取 CNT 的值即可。

    2、主要源码

    示例代码如下:

    void tim2_Init(u8 arr)
    {
        GPIO_InitTypeDef GPIO_InitStructure = {0};
        TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure = {0};
    
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);       /* 使能TIM2时钟 */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);      /* 使能GPIOA时钟 */
    
        GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0;                 /* PA0 */
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;              /* 下拉输入 */
        GPIO_Init(GPIOA, &GPIO_InitStructure);                     /* 初始化GPIOA */
        GPIO_ResetBits(GPIOA, GPIO_Pin_0);                         /* IO初始化为低电平 */
    
        TIM_TimeBaseStructure.TIM_Period = arr;                    /* 设置重装载值 */
        TIM_TimeBaseStructure.TIM_Prescaler = 0;                   /* 预分频器为0 */
        TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;    /* 不分频 */
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;/* 向上计数模式 */
        TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);            /* 初始化TIM2时基单元 */
    
        TIM_ITRxExternalClockConfig(TIM2, TIM_TS_ETRF);            /* 配置定时器2外部触发 */
        TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0);/* 外部时钟模式2的配置 */
        TIM_Cmd(TIM2, ENABLE);                                     /* 使能定时器2 */
    }
    

    相关成员解析:

    成员 说明
    TIM_ExtTRGPSC_OFF TIM ETRP 关闭预分频
    TIM_TS_ETRF TIM 外部触发输入
    TIM_ExtTRGPolarity_Inverted TIM 外部触发极性翻转:低电平或下降沿有效
    TIM_ExtTRGPolarity_NonInverted TIM 外部触发极性非翻转:高电平或上升沿有效
    int main(void)
    {
        u8 key ,count; 
        u8 oldcnt = 0;
        
        delay_init();           //延时函数初始化
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
        uart_init(115200);      //串口初始化为 115200
        LED_Init();             //初始化与LED连接的硬件接口
        KEY_Init();
        tim2_Init(10);//计数值为10次
        while(1)
        {
            key = KEY_Scan(0);
            if(key == KEY1_PRES)
            {
                TIM_SetCounter(TIM2, 0);//清空计数值
            }
            
            count = TIM_GetCounter(TIM2);//获取计数值
            if(oldcnt != count)
            {
                oldcnt = count;
                printf("CNT:%d\r\n", oldcnt);
            }
        }
    }
    

    理想的实验结果:

    不理想的实验结果:


    3、总结

    通用定时器的频率计数学习起来还是比较好理解的,只要把定时器的工作模式和工作原理框图弄明白就比较好理解了。
    测试时有时候结果很不理想,数值跳的很明显,不确定是不是按键抖动引起的,还是我程序设计逻辑上不够严谨导致的。

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32外部时钟脉冲计数实验详解

    发表评论