STM32 外部时钟脉冲计数实验

STM32 外部时钟脉冲计数实验



前言

最近在学正点原子的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_OFFTIM ETRP 关闭预分频
TIM_TS_ETRFTIM 外部触发输入
TIM_ExtTRGPolarity_InvertedTIM 外部触发极性翻转:低电平或下降沿有效
TIM_ExtTRGPolarity_NonInvertedTIM 外部触发极性非翻转:高电平或上升沿有效
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、总结

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值