使用RTC的alarm功能写一个闹钟

 1. 使用RTC的alarm功能写一个闹钟

RTC_ALARM 的中断id为76

1.1 配置寄存器

ALM...设置时间数据寄存器

他的寄存器配置这一坨和上面的BCD... 寄存器格局一模一样,往里面写值就等于设置了警报时间了

使用RTC的alarm功能写一个闹钟_第1张图片

RTCALM寄存器

使用RTC的alarm功能写一个闹钟_第2张图片

INTP 清除RTC中断挂起

清除RTC中断挂起

使用RTC的alarm功能写一个闹钟_第3张图片

1.2 写代码

rtc_alarm

pwm.h

#ifndef __PWM_H__
#define __PWM_H__

//pwm 初始化
void pwm_init();

//启动pwm
void pwm_start();

//关闭pwm
void pwm_stop();

#endif

pwm.c

#include"exynos_4412.h"

//pwm 初始化
void pwm_init(){

    //配置GPD0_0 为pwm功能
    GPD0.CON = (GPD0.CON & ~(0xf<<0)) | (2<<0);

    //配置pwm控制器,五路固定分频 TCFG1 [3:0] = 0  这里设不固定分频
    PWM.TCFG1 &= ~(0xf);

    //频率 =  总线时钟 /固定分频/ (分频值+1) / 重载值 ;
    //两路预分频 TCFG0 [7:0] = 99  100M/(99+1) = 1M
    PWM.TCFG0 = (PWM.TCFG0 & ~(0xff<<0)) | (99<<0);

    //重载值
    PWM.TCNTB0 = 2000;
    //比较寄存器  占空比 = 比较寄存器/重载值
    PWM.TCMPB0 = 1000;

    //配置总控
    //不使能死区
    PWM.TCON &= ~(1<<4);
    //自动重装
    PWM.TCON |= 1<<3;
    //打开输出
    PWM.TCON |= 1<<2;
    //装载TCNTB0  TCMPB0
    PWM.TCON |= 1<<1;
    //关闭装载
    PWM.TCON &= ~(1<<1);

}

//启动pwm
void pwm_start(){
    //启动pwm
    PWM.TCON |= 1;
}

//关闭pwm
void pwm_stop(){
    //启动pwm
    PWM.TCON &= ~1;
}

rtc.h

#ifndef __RTC_H__
#define __RTC_H__
/*
* 启动/停止 闹钟对应的位,年月日时分秒
*
* */
#define SEC_EABLE       0
#define SEC_DISABLE     1
#define MIN_EABLE       2
#define MIN_DISABLE     3
#define HOUR_EABLE      4
#define HOUR_DISABLE    5
#define DAY_EABLE       6
#define DAY_DISABLE     7
#define MON_EABLE       8
#define MON_DISABLE     9
#define YEAR_EABLE      10
#define YEAR_DISABLE    11
#define ALL_DISABLE     12


typedef struct
{  //均是用BCD码表示
    unsigned int bcdyear;  // 3位十进制数有效
    unsigned char bcdmon;  // 1-12
    unsigned char bcdday;  // 1-31
    unsigned char bcdhour; // 0-23
    unsigned char bcdmin;  // 0-59
    unsigned char bcdsec;  // 0-59
    unsigned char bcdweek; // 1-7
}bcd_time_struct;

//初始化RTC
void rtc_init(unsigned int bcdyear,unsigned char bcdmon, 
              unsigned char bcdday,unsigned char bcdhour,
              unsigned char bcdmin,unsigned char bcdsec,
              unsigned char bcdweek);
//读取RTC 时钟
void rtc_get_time(bcd_time_struct *bcd_struct);

//结构体元素的值初始化 即设置报警时间
void bcd_time_struct_init(bcd_time_struct *bcd_struct,
                        unsigned int bcdyear,unsigned char bcdmon, 
                        unsigned char bcdday,unsigned char bcdhour,
                        unsigned char bcdmin,unsigned char bcdsec,
                        unsigned char bcdweek);

//rtc_alarm_init 警报功能初始化
void rtc_alarm_init(bcd_time_struct* bcd_struct);

//警报中断初始化
void rtc_alarm_interrupt_start(unsigned char flag);

//警报中断清除挂起
void rtc_alarm_interrupt_clear(void);

#endif

rtc.c

#include"exynos_4412.h"
#include "rtc.h"

//初始化RTC
void rtc_init(unsigned int bcdyear,unsigned char bcdmon, 
              unsigned char bcdday,unsigned char bcdhour,
              unsigned char bcdmin,unsigned char bcdsec,
              unsigned char bcdweek){
    //使能RTC控制器
    RTCCON |= 0x1;
    
    //设置年月日,时分秒
    RTC.BCDSEC = bcdsec;
    RTC.BCDMIN = bcdmin;
    RTC.BCDHOUR = bcdhour;

    //注意芯片手册的星期和地址是反的,它写错了,所以我们只好反着写
    RTC.BCDWEEK = bcdday; //设置日
    RTC.BCDDAY = bcdweek;//设置星期

    RTC.BCDMON = bcdmon;
    RTC.BCDYEAR = bcdyear;

    RTCCON &= ~(1);// 关闭RTC控制器使能

}

//读取RTC 时钟
void rtc_get_time(bcd_time_struct *bcd_struct)
{
    if(bcd_struct != (void *)0)
    {
        bcd_struct->bcdyear = RTC.BCDYEAR;
        bcd_struct->bcdmon  = RTC.BCDMON;

        bcd_struct->bcdday = RTC.BCDWEEK;//这里读出来的是日

        bcd_struct->bcdhour = RTC.BCDHOUR;
        bcd_struct->bcdmin  = RTC.BCDMIN;
        bcd_struct->bcdsec  = RTC.BCDSEC;

        bcd_struct->bcdweek = RTC.BCDDAY; //这里读出来的是星期
    }
}

//结构体元素的值初始化 即设置报警时间
void bcd_time_struct_init(bcd_time_struct *bcd_struct,
                        unsigned int bcdyear,unsigned char bcdmon, 
                        unsigned char bcdday,unsigned char bcdhour,
                        unsigned char bcdmin,unsigned char bcdsec,
                        unsigned char bcdweek){
    bcd_struct->bcdyear = bcdyear;
    bcd_struct->bcdmon  = bcdmon;
    bcd_struct->bcdday  = bcdday;
    bcd_struct->bcdhour = bcdhour;
    bcd_struct->bcdmin  = bcdmin;
    bcd_struct->bcdsec  = bcdsec;
    bcd_struct->bcdweek = bcdweek;
}

//rtc_alarm_init 警报功能初始化 将报警时间设置经RTCALM寄存器
void rtc_alarm_init(bcd_time_struct* bcd_struct)
{
    RTCALM.SEC = bcd_struct->bcdsec;
    RTCALM.MIN = bcd_struct->bcdmin;
    RTCALM.HOUR= bcd_struct->bcdhour;
    RTCALM.DAY = bcd_struct->bcdday;
    RTCALM.MON = bcd_struct->bcdmon;
    RTCALM.YEAR= bcd_struct->bcdyear;
}

//警报中断初始化
void rtc_alarm_interrupt_start(unsigned char flag)
{
    //设置寄存器RTCALM.ALM  第[6]位置1,闹钟使能
    RTCALM.ALM =  (0x1 << 6);

    //GIC 面向中断源
    //开启总中断
    ICDDCR = ICDDCR | 0x1;

    //配置端口中断使能
    ICDISER.ICDISER2 = ICDISER.ICDISER2 | (0x1 << 12);

    //配置端口优先级 优先级设置为5  rtc_alarm 中断id  76
    ICDIPR.ICDIPR19 = (ICDIPR.ICDIPR19 & ~(0xff<<0)) | (5<<0);

    //配置中断源送去哪个cpu处理 0x1表示直送cpu0
    ICDIPTR.ICDIPTR19 = ICDIPTR.ICDIPTR19 & (~(0xFF << 0)) | (0x1 << 0);

    //GIC 面向cpu
    //cpu响应中断使能  =1 使能  =0 不使能
    CPU0.ICCICR = CPU0.ICCICR | 0x1;

    //配置cpu过滤优先级
    CPU0.ICCPMR = CPU0.ICCPMR | 255;

    //启动RTC
    RTCCON = RTCCON | 0x1;

    //选择哪一位使能,哪个就一到时间就报警
    switch(flag)
    {
        case SEC_EABLE:
            RTCALM.ALM |= (0x3 << 0);//使能
            break;
        case SEC_DISABLE:
            RTCALM.ALM &= ~ (0x1 << 0);//不使能
            break;
        case MIN_EABLE:
            RTCALM.ALM |=  (0x1 << 1);
            break;
        case MIN_DISABLE:
            RTCALM.ALM &= ~ (0x1 << 1);
            break;
        case HOUR_EABLE:
            RTCALM.ALM |=  (0x1 << 2);
            break;
        case HOUR_DISABLE:
            RTCALM.ALM &= ~ (0x1 << 2);
            break;
        case DAY_EABLE:
            RTCALM.ALM |=  (0x1 << 3);
            break;
        case DAY_DISABLE:
            RTCALM.ALM &= ~ (0x1 << 3);
            break;
        case MON_EABLE:
            RTCALM.ALM |=  (0x1 << 4);
            break;
        case MON_DISABLE:
            RTCALM.ALM &=  ~(0x1 << 4);
            break;
        case YEAR_EABLE:
            RTCALM.ALM |=  (0x1 << 5);
            break;
        case YEAR_DISABLE:
            RTCALM.ALM &= ~ (0x1 << 5);
            break;
        case ALL_DISABLE: 
            RTCALM.ALM |=  (0x3f << 0);//打开各个位都使能
            break;
        default:
            RTCALM.ALM = 0 ;
    }
}

//警报中断清除挂起
void rtc_alarm_interrupt_clear(void)
{
    
    RTCINTP = RTCINTP | (0x1 << 1);   //清RTC中断标志位
    ICDICPR.ICDICPR2 = ICDICPR.ICDICPR2 | (0x1 << 12);  //清除GIC中断标志位
}

main.c

#include"exynos_4412.h"
#include"uart.h"
#include "rtc.h"
#include "pwm.h"

//使用rtc的警报功能

//延时
void delay(unsigned int msec)
{
    unsigned int i,j;
    while(msec --)
    {
        for(i=0;i<5;i++)
            for(j=0;j<512;j++);
    }
}


//中断处理函数
void do_irq(void)
{
    unsigned int irq_num;
    irq_num = CPU0.ICCIAR & 0x3FF;  //获取中断号
    switch(irq_num)
    {
        case 76: //警报
            rtc_alarm_interrupt_clear();
            printf("time over!\r\n");

            pwm_start();

            break;

    }

    // CPU0.ICCEOIR = CPU0.ICCEOIR & (~(0x3FF)) | irq_num; //清cpu中断标志位
    //最后清除cpu中断挂起
    //写入中断id清除对应中断挂起
    CPU0.ICCEOIR = irq_num;
}

int main()
{
    int a = 100;
    uart_init();
    printf("hello!a=%d\r\n",a);

    //定义个结构体类型
    bcd_time_struct tm;

    //初始化RTC时钟 起到校验作用
    rtc_init(0x023,0x12,0x13,0x22,0x55,0x30,0x3);

    //警报值初始化
    bcd_time_struct tm2;
    bcd_time_struct_init(&tm2,0x023,0x12,0x13,0x22,0x56,0x35,0x3);
    rtc_alarm_init(&tm2);

    //开启警报中断初始化
    rtc_alarm_interrupt_start(12);

    //蜂鸣器初始化
    pwm_init();

    while(1){
        rtc_get_time(&tm);
        //打印实时时钟
        //%03x  保留3位  如果不足三位用0来补充
        printf("time:2%03x/%x/%x,%x:%x:%x,week:%x  \r\n",tm.bcdyear,tm.bcdmon,
               tm.bcdday,tm.bcdhour,tm.bcdmin,tm.bcdsec,tm.bcdweek);
        delay(1000);
    }
    return 0;
}


使用RTC的alarm功能写一个闹钟_第4张图片

你可能感兴趣的:(exynos4412接口编程,c语言,arm开发,嵌入式硬件,RTC)