[Atmel] 用SAM-BA或JLINK跑ATSAM4E16的程序(15)RTT

[复制链接]
 楼主| ddllxxrr 发表于 2015-11-22 07:23 | 显示全部楼层 |阅读模式
实时定时器(RTT)基于一个32位的计数器,用来对可编程16位预分频器的转翻次数进行统计。从而统计 经过 的秒数。关时定时器
可产生周期性的中断和触发报警。

由四个寄存器组成,RTT_MR模式寄存器,RTT_AR报警寄存器,RTT_VR数值寄存器,RTT_SR状态寄存器

以下程序是RTT_AR数值 作为LED闪烁的延迟时间,并使能中断,当计数值达到RTT_AR寄存器的设定值发生RTT中断,
在中断中反转LED。

以下程序是基于寄存器的,没有用库,建立程序时不要选库工程。

程序如下:


  1. #include "sam.h"


  2. #define PRESCALE (1u<<10)

  3. /* LED 使用的GPIO引脚 */
  4. #define LED1_GPIO PIO_PA0
  5. /* LED 闪烁的周期 */
  6. #define LED1_OFF_MS 200
  7. #define LED1_ON_MS  300

  8. /*[子程序]*/
  9. /*读取RTT数值寄存器RTT_VRR*/
  10. uint32_t ReadRTT_CRTV(void)
  11. {
  12.         uint32_t v1;
  13.         uint32_t v2;
  14.         /* 通过连续读取两次RTT_VR的值以增加准确性 */
  15.         while(1)
  16.         {
  17.                 v1 = (RTT->RTT_VR) & RTT_VR_CRTV_Msk;
  18.                 v2 = (RTT->RTT_VR) & RTT_VR_CRTV_Msk;
  19.                 if (v1 == v2)
  20.                 {
  21.                         return v1;
  22.                 }
  23.         }
  24. }
  25. /*计算设定时间,RTT记数器应增加的值*/
  26. inline uint32_t CalcRTTNeedInc(unsigned int ms)
  27. {
  28.    /* 计数器加一的频率 */
  29.     const uint32_t freq = CHIP_FREQ_SLCK_RC / PRESCALE;
  30.    /* 计算延迟后,计数器需要增加的值
  31.      * need_inc = ms /1000 / (1/freq) */   
  32. return (ms * freq / 1000);
  33. }

  34. /*[中断程序]*/
  35. /* RTT 中断处理函数
  36. * 在这里主要就进行LED1引脚电平的切换了*/

  37. void RTT_Handler(void)
  38. {
  39.         /*通过读取状态寄存器清除Alarm */
  40.         uint32_t a = RTT->RTT_SR;
  41.       /*读取当前的计数值*/
  42.         uint32_t begin_rttv = ReadRTT_CRTV();
  43.         uint32_t int_gap_ms ;
  44.         uint32_t need_inc;
  45.         if ((PIOA->PIO_ODSR & LED1_GPIO) == 0)
  46.         {
  47.             /* 现在引脚电平为低,LED是亮的 */
  48.             /* 灭灯 */
  49.             PIOA->PIO_SODR = LED1_GPIO;
  50.             /* 设置下次中断唤醒间隔的时间 */
  51.             int_gap_ms = LED1_OFF_MS;
  52.         }
  53.         else
  54.         {
  55.             /* 现在引脚电平为高,LED是灭的 */
  56.                 /* 亮灯 */
  57.                 PIOA->PIO_CODR = LED1_GPIO;
  58.                 /* 设置下次中断唤醒间隔的时间 */
  59.                 int_gap_ms = LED1_ON_MS;
  60.         }
  61. /* 计算并设置下一次中断的条件 */
  62.       need_inc = CalcRTTNeedInc(int_gap_ms);
  63. /*设定报警值*/
  64.         RTT->RTT_AR = RTT_AR_ALMV(begin_rttv + need_inc - 1);
  65.         return;
  66. }

  67. int main(void)
  68. {
  69.     /* Initialize the SAM system */
  70.     SystemInit();
  71.      
  72.         /* 关闭看门狗 */
  73.         WDT->WDT_MR = WDT_MR_WDDIS;
  74.         /* 初始化PIO,让PIO控制器直接控制引脚 */
  75.         PIOA->PIO_PER = LED1_GPIO;
  76.         /* 引脚输出使能 */
  77.         PIOA->PIO_OER = LED1_GPIO;
  78.         /* 引脚输出写使能 */
  79.         PIOA->PIO_OWER = LED1_GPIO;
  80.         /* 启用中断 */
  81.         NVIC_ClearPendingIRQ(RTT_IRQn);
  82.         NVIC_EnableIRQ(RTT_IRQn);
  83.         /*设置RTT 时钟分频,重置32位计数器,报警会触发中断,其中RTT_MR_xx表示RTT_MR寄存器xx位域*/
  84.         RTT->RTT_MR = RTT_MR_RTPRES(PRESCALE)     /*RTT时钟分频*/
  85.         | RTT_MR_RTTRST  /*重置32位计数器*/
  86.         | RTT_MR_ALMIEN; /*使RTT_SR寄存器报警位ALMIEN触发中断*/
  87.         /* 计算第一次中断的时间, RTT_AR 寄存器存储报警时间设定值*/
  88.         RTT->RTT_AR = RTT_AR_ALMV(ReadRTT_CRTV() + CalcRTTNeedInc(LED1_ON_MS) -1);
  89.         while(1);
  90.    
  91. }


运行结果,LED以亮占多数中间灭一下。




您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:http://shop34182318.taobao.com/ http://shop562064536.taobao.com

2403

主题

6994

帖子

68

粉丝
快速回复 在线客服 返回列表 返回顶部
个人签名:http://shop34182318.taobao.com/ http://shop562064536.taobao.com

2403

主题

6994

帖子

68

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