[新手园地] 【第四批】从51跳新唐cortex学习3——细说新唐两种定时器

[复制链接]
 楼主| watch186 发表于 2011-11-27 11:40 | 显示全部楼层 |阅读模式
【第四批】从51跳新唐cortex学习3——细说新唐两种定时器
新唐中的有关时间的寄存器
我们知道,我们在使用任何一种芯片的时候,定时器对我们的编程和使用是至关重要的,对于51的定时器我们已经是相当熟悉啦。但是,对于第一次接触新唐,第一次接触cortex的人来说,对其上定时器可能还是比较模糊的。严格来说,新唐 cortex是有两种定时器(注意,是两种)。
1.

时钟控制寄存器为整个芯片提供时钟源(五种时钟源选择),包括系统时钟和外设时钟,该控制器还通过个别时钟的关或开,时钟源的选择和分频器来进行功耗控制。
2.

   定时器控制寄存器(和51的定时器一样,都是加1计数,但是功能和容量变大了),包括432位定时器(里面放24位的数据),还有分频功能。TMER0TMER3。他支持频率测量、计数、间隔时间测量、时钟产生、延时时间等。定时器可以在计时溢出时产生中断,也可在计数中间修改当前值。新唐定时器的中断没有固定的中断入口,也就是我们可以自己设定中断函数(以前在51中我们用的是  函数后加interrupt
而新唐中我们用的是  指向函数的指针)
3.

Cortex中特有的 系统定时器(注意,这与定时器不同,是减1计数)。这是一种简单的24位写清零、递减、子封装灵活控制的计数器。他可以作为rtos的定时器和简单的计数器。系统时钟也是也是可以产生中断的,但是它的中断有固定的中断入口地址(这里又和51变成一样的啦),也就是中断函数放在SysTick_Handler() (用过OS的人相比对这个函数是相当熟悉的)。所以,我们一般将这个系统定时器保留给操作系统,这里是我见论坛里有人将他当做普通的定时器用,所以特意指出来以供新手了解。


   由以上可知,自己的工程中要使用定时器,无非就是两种,一种是我们普通的定时器(TMR ,另一种是使用系统定时器(SysClk)。而无论我们使用那种定时器之前都要先对时钟控制寄存器进行配置。下面我们依次讲解两种定时器的使用:
一、系统定时器(SYSTick
先说使用系统定时器作为定时器的方式配置。
1、首先为系统时钟选择时钟源(晶振)。


主要是设定AHB ->CLK_BA->CLKSEL0->STCLK_S 。我们一般选择外部晶振(要是当做普通的定时器来用的话)
2、之后配置系统定时控制寄存器SysTick
SysTick主要配置SYST_CSRSYST_RVRSYST_CVR

SYST_CSR下配置的第0,1,2位;
SYST_RVR 下配置第023

SYST_CVR下配置第023

  以上寄存器配置完成后,系统会自动进行定时。定时时间到,系统自动跳去执行中断函数SysTick_Handler()中的程序。
二、定时器TMR
1、和上面一样,首先配置时钟控制寄存器,选择时钟源(晶振)
AHB 下的CLK_BA -> CLKSEL1 TMRx 位。

   我们现在用他的定时器功能,选择外部晶振。
2、定时控制器TMR配置


新唐的定时器好多模式,什么4种模式5个时钟源什么的,好多,所以我们基本上是先查自己需要的模式,在进行设置。

我们就以TMR0为例

TCSR主要设置第0-31位,当然,上面有许多是无定义的位。

TCMPR下主要设置第0-23位。

TISR设置第0位。

TDR设置第0-23


这里需要说明一点的是,定时器中断函数的入口地址是由我们用户来进行设定的。其函数为DrvTIMER_SetTimerEvent()来设置的。其中有一个指向函数的指针来调用中断函数。


   上面我们介绍了如何进行两种定时器的配置,那么接下来我们就通过一个例子,来了解具体工程中是如何应用两种定时器的。本来是不打算上例子的,因为从我的心里一直感觉:一种东西的思想远比一种东西的用法重要,所以在我的前两篇51跳新唐cortex——思想转变和程序详解中,都是以讲述新唐思想、编程思想为主。但是近期看了一下大家的笔记,可能更是热衷于贴出来程序。呵呵 不过我也从大家的程序中找到了许多应用的知识。所以,在此,我也贴上一个定时器有关的例程,以供大家对照、比对、参考学习。
   本例程led_bee_timer 主要是使用新唐中的两种定时器,分别用作led灯和蜂鸣器的计时。其中,使用系统定时器(SYSTICK)来为蜂鸣器定时,蜂鸣器间歇性开关发声;使用定时器(TMR0)来控制LED流水灯定时。两种定时器都使用了中断函数进行目标的控制,大家要注意两种中断的异同。例程中保留了调试时的东西,希望大家也可以从中看到些许调试技巧。例程中为了方便,并没有套用程序框架,是进行的裸编程,而适合新唐的程序框架,笔者也正在摸索之中,哪位有比较成熟的框架结构,还希望共享一下。呵呵,先啰嗦到这里,下面附上例程:
  1. #include"include.h"

  2. E_TYPE_LED temp_led;
  3. static uint32_t flag_100ms = 0;

  4. //uint8_t test = 0;


  5. void AllLedOff()
  6. {
  7. DrvGPIO_SetBit(E_GPA,2);
  8. DrvGPIO_SetBit(E_GPA,3);
  9. DrvGPIO_SetBit(E_GPA,4);
  10. DrvGPIO_SetBit(E_GPA,5);
  11. }


  12. void Tim0CALLBACK(void) //定时器0中断函数 执行LED
  13. {
  14. // DrvGPIO_ClrBit(E_GPA,2);
  15. // DrvGPIO_ClrBit(E_GPA,5);
  16. switch(temp_led++)//(test++)
  17. {
  18. case LED1 ://1:
  19. AllLedOff();
  20. DrvGPIO_ClrBit(E_GPA,2);
  21. break;
  22. case LED2 ://2:
  23. AllLedOff();
  24. DrvGPIO_ClrBit(E_GPA,3);
  25. break;
  26. case LED3 ://3:
  27. AllLedOff();
  28. DrvGPIO_ClrBit(E_GPA,4);
  29. break;
  30. case LED4 : //4:
  31. AllLedOff();
  32. DrvGPIO_ClrBit(E_GPA,5);
  33. break;
  34. default :
  35. AllLedOff();
  36. temp_led = LED1;//test = 1;
  37. break;
  38. }
  39. }

  40. void BeeOn() //蜂鸣器
  41. {
  42. DrvGPIO_SetBit(E_GPB,10); //怎么读入某位的值
  43. }


  44. void BeeOff()
  45. {
  46. DrvGPIO_ClrBit(E_GPB,10);
  47. }

  48. void SysTick_Handler(void) //系统定时器中断函数
  49. {
  50. flag_100ms++;
  51. if(flag_100ms <= 100)
  52. {
  53. // DrvGPIO_ClrBit(E_GPA,4);
  54. // DrvGPIO_SetBit(E_GPA,5);
  55. BeeOn();
  56. }
  57. else if((flag_100ms > 100) && (flag_100ms <= 200))
  58. {
  59. // DrvGPIO_ClrBit(E_GPA,5);
  60. // DrvGPIO_SetBit(E_GPA,4);
  61. BeeOff();
  62. }
  63. else if(flag_100ms > 200)
  64. {
  65. flag_100ms = 0;
  66. }
  67. }

  68. void GPIOInit()
  69. {
  70. DrvGPIO_Open(E_GPA,2,E_IO_OUTPUT);
  71. DrvGPIO_Open(E_GPA,3,E_IO_OUTPUT);
  72. DrvGPIO_Open(E_GPA,4,E_IO_OUTPUT);
  73. DrvGPIO_Open(E_GPA,5,E_IO_OUTPUT);

  74. DrvGPIO_Open(E_GPB,10,E_IO_OUTPUT);
  75. }


  76. void TIMERInit()
  77. {
  78. DrvTIMER_Init();

  79. DrvSYS_SelectIPClockSource(E_SYS_TMR0_CLKSRC,0);

  80. DrvTIMER_Open(E_TMR0,1,E_PERIODIC_MODE); //每秒tick数 每秒tick一次

  81. DrvTIMER_SetTimerEvent(E_TMR0,1,(TIMER_CALLBACK) Tim0CALLBACK,0); //定时器的tick周期 每秒1次
  82. // DrvTIMER_Open(E_TMR0,1,E_PERIODIC_MODE); //每秒tick数 每秒tick一次


  83. DrvTIMER_EnableInt(E_TMR0);

  84. DrvTIMER_Start(E_TMR0);
  85. }

  86. void SYSCLKInit()
  87. {
  88. DrvSYS_SelectSysTickSource(0);
  89. SysTick->CTRL = 0x00000003; SysTick->VAL = 0x00000000;
  90. SysTick->LOAD = 0x6000; //100ms
  91. }

  92. void SysInit()
  93. {
  94. UNLOCKREG();
  95. SYSCLK->PWRCON.XTL12M_EN = 1;
  96. LOCKREG();

  97. GPIOInit(); //GPIO 初始化
  98. TIMERInit();
  99. SYSCLKInit();
  100. }


  101. int main()
  102. {
  103. SysInit();


  104. while(1)
  105. {
  106. ;
  107. }
  108. }

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
tendence 发表于 2011-11-27 11:42 | 显示全部楼层
沙发
 楼主| watch186 发表于 2011-11-27 11:44 | 显示全部楼层
哎  第三贴终于完成啦 ,最近发现我的心得都是关于  思想、方法、技巧的  可能和大家的类型有些不太一样。不过,我认为,一旦思想掌握好了,剩下的编程方面的东西相对来说就简单多啦。所以,第三贴还是一样,只要谈思想——谈两种定时器的使用异同。不过,这次也是附上了  自己的例程,同时使用了两种定时方法分别控制不同的东西。这样可能更加有助于大家理解。不过,了解两种定时器的思想还是比例程重要的多的   呵呵
 楼主| watch186 发表于 2011-11-27 11:45 | 显示全部楼层
成了三楼啦……
 楼主| watch186 发表于 2011-11-27 11:52 | 显示全部楼层
哎  可能三篇的心得之后,笔记的更新可能会稍微慢一些了,呵呵  马上还有更重要的事情等着我的……呵呵  还好三篇心得我自己感觉讲的是比较全面的  从芯片中的存储器到芯片中的特殊寄存器的控制,在到现在定时器的使用,一个芯片的基本功是都讲到了,呵呵。就是还不知道新唐里面的高端功能好不好用,那么接下来争取在这个新项目中能够使用新唐的芯片,相信那样自己的理解可能会更加深刻!
 楼主| watch186 发表于 2011-11-27 11:55 | 显示全部楼层
2# tendence tendence  果然名不虚传  很tend    这么快就抢楼……哈哈
hotpower 发表于 2011-11-27 18:37 | 显示全部楼层
static uint32_t flag_100ms = 0;
应该放到回调函数void SysTick_Handler(void)内,假设没其他访问时。
JackieYang2010 发表于 2011-11-28 09:13 | 显示全部楼层
牛,真的很牛
bing103 发表于 2011-11-28 14:41 | 显示全部楼层
顶楼主,一定要**这种方式哦!
lee9888 发表于 2011-11-29 11:26 | 显示全部楼层
不错,学习过你的前两篇好有帮助,谢
hotpower 发表于 2011-11-29 11:59 | 显示全部楼层
学单片机最重要的就是特殊寄存器,特别是位的含义。
 楼主| watch186 发表于 2011-11-29 19:24 | 显示全部楼层
9# bing103 呵呵  一定啊  我也是感到这先理解思想的东西是很关键的  谢谢鼓励,一起加油……
 楼主| watch186 发表于 2011-11-29 19:29 | 显示全部楼层
11# hotpower 大叔,我是感觉新唐这么多寄存器  要是要用某个功能  找他的相关寄存器是在是太不方便啦,因为一种功能很可能要好多个寄存器的设定,而且还会牵扯到寄存器写入的顺序问题。还有就是  用函数对寄存器操作  和  直接用结构体进行赋值  这两种方法函数是比较慢,但  结构体  给的库函数中  的函数定义和  手册中的定义  不同,用结构体赋值速度快,但是对于  不经常用的 结构体,就很难简单的找到寄存器。菜农大哥,有没有什么好点的简单的方法……呵呵  谢谢啊……
 楼主| watch186 发表于 2011-11-29 19:31 | 显示全部楼层
10# lee9888 呵呵   谢谢啊  我也是感觉到两种东西对比着学习会比较快把   呵呵  所以主要以对比的方式叙述……谢谢鼓励
 楼主| watch186 发表于 2011-11-29 19:32 | 显示全部楼层
7# hotpower 我本来是要  单写  操作函数的,回调函数中就只改标志,但是后来为了省事  呵呵  就……
hotpower 发表于 2011-11-29 20:28 | 显示全部楼层
目前只能用库函数,寄存器或结构体访问这些
最基本的方法和手段。
aijinquan 发表于 2012-7-6 16:11 | 显示全部楼层
好帖~学习了~ 1# watch186
Harvard 发表于 2013-3-3 12:50 | 显示全部楼层
好帖 学习了 .老菜鸟刚刚开始学m0 感谢lz的资料
hotpower 发表于 2013-3-3 18:42 | 显示全部楼层
是有条件约束吗?可以返回订金
jcqsean 发表于 2014-4-1 11:08 | 显示全部楼层
学习中。。。。,谢谢!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

104

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部