打印

SAM4E -实时时钟定时RTT

[复制链接]
1000|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
jcky001|  楼主 | 2021-10-26 10:41 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
实时时钟定时器是一个围绕在32位计数器旁的一个用来计数被32khz慢时钟源驱动的可编程的16位预分频器翻滚事件的计数器.因此利用一个校验过的1HZ的时钟,RTT也可以被配置成直接由1HZRTC信号驱动.当仅仅需要一个秒计数器时慢时钟可以被完全关闭以节省功耗。
RTT是ATMEL的芯片特有的功能这在st上好像没有见过,而且RTT使用起来也比较简单,下面就让我来给大家介绍一下RTT的使用。


千言万语尽在BLOCK那张图上,首先先看看那张图
  • /*
  • * rtt_int.c
  • *
  • * Created: 2015/1/22 20:03:21
  • *  Author: ThinkPad
  • */
  • #include "sam.h"
  • #define LED1_GPIO PIO_PD22
  • #define LED1_OFF_MS (300)
  • #define LED1_ON_MS  (300)
  • #define PRESCALE (1u<<10)
  • uint32_t ReadRTT_CRTV(void)
  • {
  •     uint32_t v1;
  •     uint32_t v2;
  •     while(1)
  •     {
  •         v1 = (RTT->RTT_VR) & RTT_VR_CRTV_Msk;
  •         v2 = (RTT->RTT_VR) & RTT_VR_CRTV_Msk;
  •         /* 通过连续读取两次RTT_VR的值以增加准备性 */
  •         if (v1 == v2)
  •         {
  •             return v1;
  •         }
  •     }
  • }
  • uint32_t CalcRTTNeedInc(unsigned int ms)
  • {
  •     /* 计数器加一的频率 */
  •     const uint32_t freq = CHIP_FREQ_SLCK_RC / PRESCALE;
  •     /* 计算延迟后,计数器需要增加的值
  •      * need_inc = ms /1000 / (1/freq) */
  •     return (ms * freq / 1000);       //1s钟跑freq,1ms就跑freq/1000,所以ms毫秒,就是ms*freq/1000//
  • }
  • void Delay(unsigned int ms)
  • {
  •     uint32_t begin_rttv = ReadRTT_CRTV();
  •     uint32_t need_inc = CalcRTTNeedInc(ms);
  •     uint32_t end_rttv = begin_rttv + need_inc;
  •     /* 等待*/
  •     while(ReadRTT_CRTV() < end_rttv)
  •         ;
  • }
  • /* RTT 中断处理函数
  • * 在这里主要就进行LED1引脚电平的切换了
  • */
  • void RTT_Handler(void)
  • {
  •     /* 通过读取状态寄存器清除Alarm */
  •     uint32_t read_clear = RTT->RTT_SR;
  •     uint32_t begin_rttv = ReadRTT_CRTV();
  •     uint32_t int_gap_ms ;
  •     uint32_t need_inc;
  •     if ((PIOD->PIO_ODSR & LED1_GPIO) == 0)
  •     {
  •         /* 现在引脚电平为低,LED是亮的 */
  •         /* 灭灯 */
  •         PIOD->PIO_SODR = LED1_GPIO;
  •         /* 设置下次中断唤醒间隔的时间 */
  •         int_gap_ms = LED1_OFF_MS;
  •     }
  •     else
  •     {
  •         /* 现在引脚电平为高,LED是灭的 */
  •         /* 亮灯 */
  •         PIOD->PIO_CODR = LED1_GPIO;
  •         /* 设置下次中断唤醒间隔的时间 */
  •         int_gap_ms = LED1_ON_MS;
  •     }
  •     /* 计算并设置下一次中断的条件 */
  •     need_inc = CalcRTTNeedInc(int_gap_ms);
  •     RTT->RTT_AR = RTT_AR_ALMV(begin_rttv + need_inc - 1);
  •     return;
  • }
  • int main(void)
  • {
  •     /* 必须要开PIOA的外围时钟*/
  • //    PMC->PMC_PCER0 = (1 << ID_PIOA);
  •         /* 关闭看门狗 */
  •     WDT->WDT_MR = WDT_MR_WDDIS;
  •     /* 初始化PIO */
  •     /* 让PIO控制器直接控制引脚 */
  •     PIOD->PIO_PER = LED1_GPIO;
  •     /* 引脚输出使能 */
  •     PIOD->PIO_OER = LED1_GPIO;
  •     /* 引脚输出写使能 */
  • //    PIOA->PIO_OWER = LED0_GPIO;
  • //    PIOD->PIO_OWER = LED1_GPIO;
  • // NVIC_SetPriorityGrouping(0);//也可以不设置默认是0
  •     /* 初始化 RTT */
  •     /* 启用中断 */
  •     NVIC_ClearPendingIRQ(RTT_IRQn);
  •     RTT->RTT_MR = RTT_MR_RTPRES(PRESCALE)
  •                     | RTT_MR_RTTRST
  •                     | RTT_MR_ALMIEN    //设置预分频器 重启定时器 开alarm中断
  •                     ;
  •     /* 计算第一次中断的时间
  •      * 现在灯是亮的,第一次中断即在需要灯灭时
  •      */
  •          NVIC_SetPriority(RTT_IRQn,0);//设置rtt的中断优先级
  •          NVIC_EnableIRQ(RTT_IRQn);    //使能RTT中断
  •     RTT->RTT_AR = RTT_AR_ALMV(ReadRTT_CRTV() + CalcRTTNeedInc(LED1_ON_MS) -1);   //设置和CRTV比较的那个值
  •     while (1) {
  •     }
  •     return 0;
  • }

复制代码


使用特权

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

本版积分规则

1414

主题

3849

帖子

6

粉丝