KA_IX

  • 2955 主题
  • 3005 帖子
  • 8421 积分
  • 身份:LV6 初级工程师
  • 论坛新秀 灌水之王 突出贡献
  • E币:2584

ME32F030基本定时器详解

2021-6-15 12:08:19 显示全部楼层
本帖最后由 KA_IX 于 2021-6-15 12:09 编辑

学习笔记


1、ME32F030基本定时器简介

ME32F030内置 4 个基本功能的 16 位定时器/计数器。 定时器/计数器工作时钟由 SYSAHBCLKDIV 寄存器控制。关闭 SYSAHBCLKDIV 寄存器中定时器/计数器的时钟供给可节省系统功耗。主要功能如下:
• 可预置分频的 16 位定时器/计数器
• 1 个 16 位匹配寄存器:
–可产生中断
–停止定时器
–对定时器复位
16 位基本型定时器/计数器模块框图如下图所示:

e16933d695654c21942386473011f64b?from=pc.jpg
图1 基本定时器结构图

为了便于理解,可以将基本定时器框图分为4个功能单元。
①:预分频计数单元,由PRESCALE COUNTER (PC) 和 PRESCALE REGISTER (PR)组成,预分频计数器(PC)会在每个 PCLK 时钟上递增计数。达到设定的预分频值后,定时器计数器就会加1,而预分频值就是由PR寄存器决定的。
②:定时器计数单元,由TIMER COUNTER (TC) 和 TIMER CONTROL REGISTER (TCR)组成,定时器控制寄存器TCR决定计数器TC是否启用。预分频计数器(PC)溢出后,定时器计数器(TC)加1,达到设定的匹配值MR0之后可以根据设置产生中断等行为。
③:定时器匹配单元:该单元只有一个MATCH REGISTER0(MR0),它决定着定时器计数器TC的匹配值。
④:定时器控制单元,由MATCH CONTROL REGISTER (MCR) 和 INTERRUPT REGISTER (IR)组成,二者共同作用,控制着定时器的主要功能和参数。

2、ME32F030基本定时器寄存器

在简介中,我们介绍了基本定时器的模块框图,其实每个功能模块都有对应的寄存器来实现其功能。基本定时器的寄存器列表如图所示:

966db2b200e44416b103a6901bdb2da6?from=pc.jpg
图2 基本定时器寄存器列表

2-1 中断寄存器


中断寄存器包含用于匹配中断的位。如果有中断产生, IR 中的相应位为高电平。否则,该位为低电平。向对应的 IR 位写逻 辑 1 会使中断复位。写 0 无效。

2-2 定时器控制寄存器


定时器控制寄存器用于控制计数器/定时器的操作。它主要控制着计数器的使能和复位,具体的操作如图所示:

aef46cd4835742de86815fc3b2062eaf?from=pc.jpg
图3 控制寄存器

2-4 定时器计数寄存器

当预分频器计数器达到其 PC 数值时, 16 位定时器计数器会递增计数。如果 TC 在到达计数器上限之前没有复位,它将一直 计数到 0x0000 FFFF 然后翻转到 0x0000 0000。该事件不会产生中断,如果需要,可使用匹配寄存器检测溢出。

2-4 预分频寄存器

16 位预分频寄存器指定预分频计数器的最大值。当预分频计数器计数到此值后,会从0开始重新计数。

2-5 预分频计数寄存器

16 位预分频计数器用某个常量来控制 PCLK 的分频,再使其输入到定时器计数器。它所控制的是定时器分辨率与最大时间之间的关系,从而能防止定时器溢流。预分频计数器会在每个 PCLK 时钟上递增计数。当预分频计数器的计数达到预分频寄存器中存储的值时,定时器计数器将递增计数,并且在下一个 PCLK 时钟上对预分频计数器复位。这将使得 TC 当 PR = 0 时在每个 PCLK 上递增计数,当 PR = 1 时,在每 2 个 PCLK 上递增计数,依次类推。.

2-6 匹配控制寄存器

匹配控制寄存器用于控制当其中一个匹配寄存器的值与定时器计数器的值匹配时应执行的操作。功能如下所示。
位0:决定着计数器TC与匹配值相等后,中断是否使能。
位1:MR0与TC匹配时,决定TC是否复位。如果选择复位,TC则会清0重新计数,这样就会形成一个固定时间的计数周期。
位2:MR0与TC匹配时,决定TC是否停止。如果置1选择使能,TC则不再会计数。这样就是个单次周期的计数了。如果想要周期性循环计数,那么就需要置0(默认)禁止。
1d2ce6b5abd84969a780afa9c1a2d732?from=pc.jpg
图4 匹配控制寄存器

2-7 匹配寄存器

匹配寄存器的值会不断地与定时器计数器值进行比较。当两个值相等时,自动触发相应操作。这些操作包括产生中断、复位定时器计数器或停止定时器。所有操作均由 MCR 寄存器中的设置控制。

3、基本定时器驱动函数

在例程LIB->common->Drivers->Source文件夹内有timer.c文件,这个就是提供的定时器库程序,里面除了基本定时器的驱动函数,还包括高级定时器、PWM输出等功能函数,本章节先对基本定时器的函数进行讲解。

3-1 基本定时器初始化

ct:要初始化的定时器模块,可选TIM0、TIM1、TIM2、TIM3。
tickpersecond:预分频系数。
  1. void TIM0_Init(TIM0_Type *ct, uint32_t tickpersecond)
  2. {
  3. if (ct == TIM0)
  4. {
  5. SYSCON->SYSAHBCLKCTRL_b.TIM0_CLK=1;//使能定时器时钟
  6. SYSCON->PRESETCTRL_b.TIM0_RST_N=0; //复位定时器
  7. SYSCON->PRESETCTRL_b.TIM0_RST_N=1;
  8. }

  9. else if (ct == TIM1)
  10. {

  11. SYSCON->SYSAHBCLKCTRL_b.TIM1_CLK=1;

  12. SYSCON->PRESETCTRL_b.TIM1_RST_N=0;

  13. SYSCON->PRESETCTRL_b.TIM1_RST_N=1;
  14. }

  15. else if (ct == TIM2)
  16. {
  17. SYSCON->SYSAHBCLKCTRL_b.TIM2_CLK=1;

  18. SYSCON->PRESETCTRL_b.TIM2_RST_N=0;

  19. SYSCON->PRESETCTRL_b.TIM2_RST_N=1;
  20. }

  21. else if (ct == TIM3)
  22. {

  23. SYSCON->SYSAHBCLKCTRL_b.TIM3_CLK=1;

  24. SYSCON->PRESETCTRL_b.TIM3_RST_N=0;

  25. SYSCON->PRESETCTRL_b.TIM3_RST_N=1;

  26. } else return;

  27. //设置预分频系数
  28. if (tickpersecond>SystemCoreClock)
  29. tickpersecond=SystemCoreClock;
  30. ct->PR_b.PRVAL=SystemCoreClock/tickpersecond-1;
  31. return;
  32. }
3-2 设置匹配寄存器

这个函数用于设置定时器的匹配值,以及达到匹配值之后的行为。
Ct:要设置的定时器模块,可选TIM0、TIM1、TIM2、TIM3。
Ticks:要写入的计数器匹配值。
Action: 触发中断 TIM_MATCH_TRIGGER_INT
复位计数器 TIM_MATCH_RESET_COUNTER
停止计数器 TIM_MATCH_STOP_COUNTER
  1. void TIM0_ConfigMatch(TIM0_Type *ct, uint16_t ticks, uint8_t action)
  2. {
  3. ct->MR0_b.MATCH=ticks-1;
  4. ct->MCR=action;
  5. return;
  6. }
3-3 设置预分频计数器值
  1. void TIM0_SetTimerCounter(TIM0_Type *ct, uint16_t tick)
  2. {
  3. ct->PC_b.PCVAL=tick;
  4. return;
  5. }
3-4 复位预分频计数器值
  1. void TIM0_ResetTimerCounter(TIM0_Type *ct)
  2. {
  3. ct->PC_b.PCVAL=0;
  4. return;
  5. }
a560914a-979f-47bf-bb53-ca09a2fd22ba?from=pc.jpg
3-5 获取计数器当前值
  1. uint16_t TIM0_GetTimerCounter(TIM0_Type *ct)
  2. {
  3. return ct->TC_b.TC;
  4. }
3-6 清除定时器中断标志
  1. void TIM0_ClearIntFlag(TIM0_Type *ct)
  2. {
  3. ct->IR_b.MR0INT=1;
  4. return;
  5. }
4、ME32F030基本定时器例程


最早在讲解GPIO的时候,我们用的是系统延时的方法来闪烁LED小灯。但是这样有个问题,那就是调用系统延时的方法,程序是在这里无意义的空等。这在今后的开发中是十分不可取的,因为这样极大的降低程序的运行效率,尤其是面对多个任务需要执行的时候。这时候我们就可以通过硬件定时器中断的方式,来解决这个问题。下面就举例通过硬件中断来闪烁LED的方法,测试代码如下:
程序首先会设置定时器的预分频值,例程中将分频值设为1000Hz,即1ms溢出一次,这样计数器TC 就会加1。
接下来对基本定时器的触发条件和触发行为进行设置,这里我们将触发的匹配值设置为500,和预分频值共同作用产生一个500ms的计数周期。当达到匹配值之后,启动定时中断并且复位清0计数值,继续循环。
接下来就是使能中断服务程序和LED小灯端口初始化。
在最后用了个宏定义 TIM0_START 来让定时器开始工作。
  1. int main()
  2. {
  3. TIM0_Init(TIM0,1000); //TIM0 设置预分频值

  4. //基本定时器0, 500个计数触发一次中断(500ms),触发中断后复位清0计数值
  5. TIM0_ConfigMatch(TIM0,500,TIM_MATCH_TRIGGER_INT|TIM_MATCH_RESET_COUNTER);

  6. NVIC_EnableIRQ(TIM0_IRQn);//使能中断服务子程序

  7. GPIO_ConfigPinsAsOutput(PB, IO_PIN9);//PB9设置为输出口

  8. TIM0_START;//定时器0开始工作

  9. while(1);
  10. }


  11. //基本定时器0 中断服务子程序
  12. void TIM0_IRQHandler(void)  
  13. {
  14.   GPIO_InvertOutPin(PB, IO_PIN9);//端口输出反转
  15. TIM0_ClearIntFlag(TIM0);//清除中断标志
  16. }
程序编译没有报错之后,便可以下载仿真调试,我们在中断服务子程序内打上一个断点,然后全速运行程序。这时候发现程序会运行到断点处,这说明定时器的中断已经成功触发。取消掉断点,继续全速运行,观察LED小灯。这时候就看到LED小灯开始不停闪烁。
13a52770cc5b4d4c808ddb1f20178be8?from=pc.jpg
图5 程序仿真

相比较之前的GPIO 系统延时方法,点灯完全由中断子程序控制。这样main函数里的主程序就可以去做其他事情,这样程序效率就更高了。

来源:老马识途单片机
您需要登录后才可以评论 登录 | 立即注册

最新评论

楼层直达:

小小毛

  • 85 主题
  • 305 帖子
  • 1130 积分
  • 身份:LV4 高级技术员
  • 热心工程师 技术达人
  • E币:1893

SnailWillow

  • 78 主题
  • 271 帖子
  • 1354 积分
  • 身份:版主
  • 论坛新秀
  • E币:1662

深宣科

  • 2 主题
  • 9 帖子
  • 256 积分
  • 身份:LV1 技术小白
  • E币:254
深宣科 2021-6-22 16:54:54 显示全部楼层
韩国的LG也款类似的,有现货,价格美丽,WX13424332191
广告

深宣科

  • 2 主题
  • 9 帖子
  • 256 积分
  • 身份:LV1 技术小白
  • E币:254
快速回复
4
3
广告
关闭 热点推荐上一条 /3 下一条
快速回复 返回列表