|
花了一天的時間把原子的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;
|
|