打印
[技术问答]

HC32单片机定时器

[复制链接]
3202|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
nawu|  楼主 | 2023-11-13 11:38 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
1,定时器/计数器工作原理
  许多初学者弄不明白,为什么叫定时器/计数器呢?原因是这个设备既能用于定时也可以用于计数。这是什么原理呢?单片机怎么知道什么时候该定时,什么时候该计数呢?
解:
  首先说一下既可以定时又可以计数的原理,实际上定时和计数的原理是一样的,都是靠数数来实现。比方说我家的水龙头坏了,关不紧,总是一滴一滴漏水,而且水滴滴的特别均匀,每两滴之间的时间间隔都是 1 秒,现在我们就可以利用数水滴滴数的方法来计算出时间,这就是定时的原理。
  再举个例子,阿范有一天很无聊,站在窗前向外看着公路上跑的小汽车,不自觉的就开始数汽车的数量,1、2、3…,由于每两辆汽车之间的时间间隔不同,所以这回我数出来的数就不能算出来我那天究竟向窗外看了多长时间,而只能算作数出来的车的数量,即当成计82 数器,这就是计数器,大家会发现两次实际上都是在数数,只是数的内容不同而已,一个是匀速的水滴,另一个是非匀速通过的车辆。
2,定时器/计数器的定时和计数是怎么实现的
  现在我们来说说单片机是怎么定时和计数的。其实都是数数,只不过单片机本身就是数字电路,如果让它去数数,也只能数脉冲。而脉冲来源于两个地方:一个是由单片机的 18和 19 引脚接的晶振产生的稳定而均匀的脉冲信号,这个信号到单片机内部经过 12 分频(即脉冲变宽,频率为晶振频率的十二分之一)后提供给定时器;定时器每接收一个脉冲就会自动把计的数加 1,当把装这个数的容器加满了,会自动有一个标志位从 0 变成 1,这时我们可以算出计了多少时间;另一个脉冲来源是单片机的外部引脚 P3.4 和 P3.5,当用定时器 T0时数的是 P3.4 引脚输入的脉冲,当用定时器 T1 时数的是 P3.5 引脚输入的脉冲。至于怎么才能命令单片机工作在定时状态还是工作在计数状态,这个需要设置特殊功能寄存器 TMOD中的内容,我们将在下面和大家分享。
定时器分类
    定时器的基本结构是通用的,很多模块电路都能用到,所以STM32定时上扩展了非常多的功能,根据复杂度和应用场景分为了高级定时器、通用定时器、基本定时器三种类型。高级定时器通常提供更多的功能和扩展性,例如可以支持编码器模式、PWM输入输出等。

定时器组成
1.计数器

   向上计数模式:计数器从0开始计数,当达到自动装载寄存器(TIMx_ARR)里的值时,自动清零且产生一个溢出事件,然后再从0开始向上计数。

   向下计数模式:计数器从自动装载寄存器(TIMx_ARR)里的值开始递减计数,当计数值达到0时产生一个定时器溢出事件,并重装初值,继续向下计数。

   中央对齐模式:又称为向上/向下计数,计数器从0开始递增达到ARR的值,产生一个定时器溢出事件,再从ARR的值递减到0,产生一个定时器溢出事件。

2.自动重装寄存器


3.预分频器


定时器计数原理
   假设当前时钟为64Mhz,如何让定时器TIMn产生一个1s中断?

   预分频器 写64-1相当于64分频 ,得到分频后的频率为1Mhz

              64Mhz / 64 = 1Mhz

   在1Mhz的频率下计1个数需要 1/1000000s 即 1us

   向自动重装计数器写入1000000-1,并开始计数,

   即计1000000个数产生一个溢出中断

   可以实现每隔1s产生一个中断信号。

程序编写
//中断相关函数
//中断标志获取
boolean_t Bt_GetIntFlag(en_bt_unit_t enUnit);
//中断标志清除
en_result_t Bt_ClearIntFlag(en_bt_unit_t enUnit);
//中断使能/禁止
en_result_t Bt_EnableIrq (en_bt_unit_t enUnit);
en_result_t Bt_DisableIrq(en_bt_unit_t enUnit);

//初始化及相关功能操作
//timer配置及初始化
en_result_t Bt_Init(en_bt_unit_t enUnit, stc_bt_config_t* pstcConfig);
//Lptimer 启动/停止
en_result_t Bt_Run(en_bt_unit_t enUnit);
en_result_t Bt_Stop(en_bt_unit_t enUnit);
//重载值设置
en_result_t Bt_ARRSet(en_bt_unit_t enUnit, uint16_t u16Data);
//16位计数值设置/获取
en_result_t Bt_Cnt16Set(en_bt_unit_t enUnit, uint16_t u16Data);
uint16_t Bt_Cnt16Get(en_bt_unit_t enUnit);
//32位计数值设置/获取
en_result_t Bt_Cnt32Set(en_bt_unit_t enUnit, uint32_t u32Data);
uint32_t Bt_Cnt32Get(en_bt_unit_t enUnit);

实例:

/*******************************************************************************
* BT定时功能测试 (重载模式)
******************************************************************************/
en_result_t BtTimer2Init(void)
{
    stc_bt_config_t   stcConfig;
    en_result_t       enResult = Error;
    uint16_t          u16ArrData = 0xFF05;//计数到0xffff中断一次 1ms中断一次
    uint16_t          u16InitCntData = 0xFF05;//0xC000;

    stcConfig.pfnTim2Cb = Bt2Int;

    Clk_SetPeripheralGate(ClkPeripheralBt, TRUE);

    stcConfig.enGateP = BtPositive;
    stcConfig.enGate  = BtGateDisable;
    stcConfig.enPRS   = BtPCLKDiv16;//4M/16= 250KHZ 滴答一次0.004ms 计数0xFA次中断一次
    stcConfig.enTog   = BtTogDisable;
    stcConfig.enCT    = BtTimer;
    stcConfig.enMD    = BtMode2;
    //Bt初始化
    if (Ok != Bt_Init(TIM2, &stcConfig))
    {
        enResult = Error;
    }

    //TIM2中断使能
    Bt_ClearIntFlag(TIM2);
    Bt_EnableIrq(TIM2);
    EnableNvic(TIM2_IRQn, 3, TRUE);

    //设置重载值和计数值,启动计数
    Bt_ARRSet(TIM2, u16ArrData);
    Bt_Cnt16Set(TIM2, u16InitCntData);
//    Bt_Run(TIM2);
   M0P_BT2->CR_f.TR = TRUE;
    return Ok;
}

BT中断函数

/*******************************************************************************
* BT1中断服务函数
******************************************************************************/
void Bt2Int(void)
{
    if (TRUE == Bt_GetIntFlag(TIM2))
    {
        Bt_ClearIntFlag(TIM2);
        //UpdateStpTimer();

        //秒表
        msTimer++;
                halmstime++;
        if (msTimer >= 1000)//一秒
        {
            msTimer = 0;
            HeartTimer++;
                        HeartL2Timer++;
        }

               
    }
}

————————————————
版权声明:本文为CSDN博主「烤辣大师」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_44110278/article/details/134005035

使用特权

评论回复
沙发
yangxiaor520| | 2023-11-14 07:46 | 只看该作者
对于MCU的定时器来讲,应用频率非常高。

使用特权

评论回复
板凳
只是个新人-| | 2023-11-16 09:35 | 只看该作者

使用特权

评论回复
地板
woai32lala| | 2023-11-17 08:42 | 只看该作者
学习

使用特权

评论回复
5
daichaodai| | 2023-11-20 08:57 | 只看该作者
可以用一个硬件定时器来实现软件定时器

使用特权

评论回复
6
feifeifeichang| | 2024-4-26 10:19 | 只看该作者
学习

使用特权

评论回复
7
鹿鼎计| | 2024-4-28 20:37 | 只看该作者
定时器真的是单片机的一大利器,很多地方都能用。

使用特权

评论回复
8
软核硬核| | 2024-4-28 21:13 | 只看该作者
定时器用好了,其实可以做很多事,感觉自己定时器使用还是不够深。

使用特权

评论回复
9
1564564| | 2024-7-10 09:29 | 只看该作者
听楼主这么一说,才明白定时器和计数器的区别,实话说,我还真没用过计数器,所以有佬能举个计数器的应用例子吗?定时器倒是应用的停过。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

72

主题

3307

帖子

3

粉丝