|
花了一天的时间把原子的RTC例程移植到了野火的板子(固件库版本);顺便自己想做一个闹钟程序,凭借自己的功底肯定是不可能的任务!只好学习原子的闹钟例程了。根据自己的理解做了比较详细的注释。手机上看似一个简单的闹钟设置功能,要自己写出实现闹钟功能的c语言程序却不是一件简单的事。
综合例程就有闹钟设置部分,核心代码:
//重新初始化闹钟
//alarmx:闹钟结构体
void calendar_alarm_init(_alarm_obj *alarmx)
{
u32 curtime=0; //rtc寄存器的当前时间,即秒数
u32 temptime=0;
u32 destime=0XFFFFFFFF;//目标闹铃时间(s)设定到最大 ,即我要设定的闹钟目标日期 if(alarmx->weekmask)//必须要有闹钟存在,周日到周六任意一天,当alarmx->weekmask是0时,说明没有闹钟要设置 {
curtime=RTC->CNTH;//得到计数器中的值(秒钟数)
curtime<<=16;
curtime+=RTC->CNTL; //获取RTC当前的秒数值,注意c语言取值技巧!
//取一个与当前时间最接近的值作为闹钟寄存器的内容
temptime=curtime/86400; //得到当前运行天数(此处没有用到天数,仅作说明用) ,一天等于86400秒
temptime=temptime*86400;
temptime+=(u32)alarmx->hour*3600+(u32)alarmx->min*60;//得到秒钟数
if(temptime<=curtime)temptime+=86400;//执行时间已过,推迟到明天
destime=temptime;//更改闹钟寄存器
}
RCC->APB1ENR|=1<<28;//使能电源时钟
RCC->APB1ENR|=1<<27;//使能备份时钟
PWR->CR|=1<<8; //取消备份区写保护
//上面三步是必须的!
RTC->CRL|=1<<4; //允许配置
RTC->ALRL=destime&0xffff; //把destime的低16位存入闹钟数据寄存器RTC->ALRL
RTC->ALRH=destime>>16; //把destime的高16位存入闹钟数据寄存器RTC->ALRH
RTC->CRL&=~(1<<4);//配置更新
while(!(RTC->CRL&(1<<5)));//等待RTC寄存器操作完成
}
程序说明:如果alarmx->weekmask是0时,说明没有闹钟要设置;这时“if(alarmx->weekmask)”控制的语句就不会执行,所以此时我要设定的闹钟目标日期值即秒数是最大值0XFFFFFFFF,这是一个138年之内不可能的闹钟。假设当alarmx->weekmask是“真”,则执行“if(alarmx->weekmask)”控制的语句,这时本函数的核心!最终就是要为闹钟数据寄存器取得准确闹钟时间。
其中_alarm_obj的结构体定义如下:
//闹钟结构体
__packed typedef struct
{
u8 weekmask; //闹钟响铃掩码
u8 ringsta; //闹铃状态及铃声标志.
//[7]:0,无闹铃;1,闹铃中;
//[6:3]:保留
//[2:0]:闹钟铃声类型
u8 hour; //闹铃小时
u8 min; //闹铃分钟
u8 saveflag; //保存标志,0X0A,保存过了;其他,还从未保存
}_alarm_obj;
|
|