打印
[Atmel]

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

[复制链接]
479|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
ddllxxrr|  楼主 | 2015-11-22 07:23 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
实时定时器(RTT)基于一个32位的计数器,用来对可编程16位预分频器的转翻次数进行统计。从而统计 经过 的秒数。关时定时器
可产生周期性的中断和触发报警。

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

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

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

程序如下:


#include "sam.h"


#define PRESCALE (1u<<10)

/* LED 使用的GPIO引脚 */
#define LED1_GPIO PIO_PA0
/* LED 闪烁的周期 */
#define LED1_OFF_MS 200
#define LED1_ON_MS  300

/*[子程序]*/
/*读取RTT数值寄存器RTT_VRR*/
uint32_t ReadRTT_CRTV(void)
{
        uint32_t v1;
        uint32_t v2;
        /* 通过连续读取两次RTT_VR的值以增加准确性 */
        while(1)
        {
                v1 = (RTT->RTT_VR) & RTT_VR_CRTV_Msk;
                v2 = (RTT->RTT_VR) & RTT_VR_CRTV_Msk;
                if (v1 == v2)
                {
                        return v1;
                }
        }
}
/*计算设定时间,RTT记数器应增加的值*/
inline 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);
}

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

void RTT_Handler(void)
{
        /*通过读取状态寄存器清除Alarm */
        uint32_t a = RTT->RTT_SR;
      /*读取当前的计数值*/
        uint32_t begin_rttv = ReadRTT_CRTV();
        uint32_t int_gap_ms ;
        uint32_t need_inc;
        if ((PIOA->PIO_ODSR & LED1_GPIO) == 0)
        {
            /* 现在引脚电平为低,LED是亮的 */
            /* 灭灯 */
            PIOA->PIO_SODR = LED1_GPIO;
            /* 设置下次中断唤醒间隔的时间 */
            int_gap_ms = LED1_OFF_MS;
        }
        else
        {
            /* 现在引脚电平为高,LED是灭的 */
                /* 亮灯 */
                PIOA->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)
{
    /* Initialize the SAM system */
    SystemInit();
     
        /* 关闭看门狗 */
        WDT->WDT_MR = WDT_MR_WDDIS;
        /* 初始化PIO,让PIO控制器直接控制引脚 */
        PIOA->PIO_PER = LED1_GPIO;
        /* 引脚输出使能 */
        PIOA->PIO_OER = LED1_GPIO;
        /* 引脚输出写使能 */
        PIOA->PIO_OWER = LED1_GPIO;
        /* 启用中断 */
        NVIC_ClearPendingIRQ(RTT_IRQn);
        NVIC_EnableIRQ(RTT_IRQn);
        /*设置RTT 时钟分频,重置32位计数器,报警会触发中断,其中RTT_MR_xx表示RTT_MR寄存器xx位域*/
        RTT->RTT_MR = RTT_MR_RTPRES(PRESCALE)     /*RTT时钟分频*/
        | RTT_MR_RTTRST  /*重置32位计数器*/
        | RTT_MR_ALMIEN; /*使RTT_SR寄存器报警位ALMIEN触发中断*/
        /* 计算第一次中断的时间, RTT_AR 寄存器存储报警时间设定值*/
        RTT->RTT_AR = RTT_AR_ALMV(ReadRTT_CRTV() + CalcRTTNeedInc(LED1_ON_MS) -1);
        while(1);
   
}


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




相关帖子

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

本版积分规则

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

2398

主题

6945

帖子

66

粉丝