HC32单片机定时器

目录

1,定时器/计数器工作原理 

2,定时器/计数器的定时和计数是怎么实现的 

定时器分类

定时器组成

1.计数器​编辑

2.自动重装寄存器

3.预分频器

定时器计数原理

程序编写

实例:


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.计数器HC32单片机定时器_第1张图片

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

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

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

2.自动重装寄存器

HC32单片机定时器_第2张图片

3.预分频器

HC32单片机定时器_第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++;
        }
 
		
    }
}

你可能感兴趣的:(HC单片机,1024程序员节,单片机,开发语言,编辑器)