STM32應用 第3節 永不消逝的時鐘 RTC

2021-08-31 11:55:23 字數 4178 閱讀 7002

每乙個複雜的專案,都包括了許多基礎內容。每乙個複雜的任務,都是通過一系列簡單的分解動作組裝而成。

rtc就是諸多分解動作中重要的一環。在物聯網的各類裝置中,許多都需要利用rtc,才能為資料提供準確的定時。

rtc初始化根據bkp_readbackupregister讀數值進行判斷,如果讀數值不等於bkp_valid,說明沒有完成rtc初始化(rtc初始化完成後,會把backupregister設定為bkp_valid)。

rtc初始化時,將會有乙個延時等待時間,等待rtc晶振穩定。如果等待超時,則將返回1,表示初始化失敗。

設定時,會呼叫rtc_set設定當前的具體時間。這個時間在系統上電時,一次設定成功後,後續通過rtc電池供電,時間永不丟失。

如果bkp_readbackupregister(bkp_r_valid)==bkp_valid,表示rtc已經完成了初始化,則使能中斷,並通過rtc_get獲取當前rtc時間。

u8 rtc_init(void)

if (temp>=250) return 1;//初始化時鐘失敗,晶振有問題

rcc_rtcclkconfig(rcc_rtcclksource_lse); //設定rtc時鐘(rtcclk),選擇lse作為rtc時鐘

rcc_rtcclkcmd(enable); //使能rtc時鐘

rtc_waitforlasttask(); //等待最近一次對rtc暫存器的寫操作完成

rtc_waitforsynchro(); //等待rtc暫存器同步

rtc_itconfig(rtc_it_sec, enable); //使能rtc秒中斷

rtc_waitforlasttask(); //等待最近一次對rtc暫存器的寫操作完成

rtc_enterconfigmode(); //允許配置

rtc_setprescaler(32767); //設定rtc預分頻的值

rtc_waitforlasttask(); //等待最近一次對rtc暫存器的寫操作完成

rtc_set(2018,11,8,16,02,55); //設定時間

rtc_exitconfigmode(); //退出配置模式

// 向指定的後備暫存器中寫入使用者程式資料

bkp_writebackupregister(bkp_r_valid, bkp_valid); // 備份暫存器生效標誌

bkp_writebackupregister(bkp_r_adxl_set, adxl_initial_value); // adxl設定預設值

bkp_writebackupregister(bkp_r_acc_num, 0); // 3軸資料檔案序號

bkp_writebackupregister(bkp_r_acc_del_num, 0); // 3軸資料檔案待刪除序號

} else//已經完成了初始化,系統繼續計時

rtc_nvic_config();//rct中斷分組設定

rtc_get();//更新時間

return 0; //ok

}

rtc_set完成rtc時間的寫入和修改。設定時,呼叫rtc_setcounter(seccount); 其中引數seccount為時間戳。時間戳是指格林威治時間2023年01月01日00時00分00秒(北京時間2023年01月01日08時00分00秒)起至現在的總秒數。

u8 rtc_set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec)

}else temp-=365; //平年

temp1++;

} g_cainfo.year=temp1;//得到年份

temp1=0;

while (temp>=28)//超過了乙個月

else

temp1++;

} g_cainfo.month=temp1+1; //得到月份

g_cainfo.date=temp+1; //得到日期

} temp=timecount%86400; //得到秒鐘數

g_cainfo.time.hour=temp/3600; //小時

g_cainfo.time.min=(temp%3600)/60; //分鐘

g_cainfo.time.sec=(temp%3600)%60; //秒鐘

//g_cainfo.week=rtc_get_week(g_cainfo.year,g_cainfo.month,g_cainfo.date);//獲取星期

//printf("\r\nget rtc success");

return 0;

}

rtc_alarm_set用來設定定時。具體方法和前面相似,首先計算總秒數:seccount。然後使能外設時鐘,最後使能後備暫存器訪問。

具體設定alarm通過stm32的庫函式rtc_setalarm(seccount)完成設定。

u8 rtc_alarm_set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec)

計算閏年,當年c語言課程中的試題。

u8 is_leap_year(u16 year)

else return 1;

}else return 0;

}

設定rtc中斷優先順序配置,在rtc_init()中呼叫。

static void rtc_nvic_config(void)

rtc中斷處理中, 當rtc_getitstatus(rtc_it_sec) != reset時,rtc觸發了秒中斷,這時呼叫rtc_get獲取資訊,並設定g_bsecflag,作為標誌。

如果檢查到(rtc_getitstatus(rtc_it_alr)!= reset, 則可以進行鬧鐘中斷處理,例如,設定鬧鐘標誌位。當然,在這裡並未進行處理。

void rtc_irqhandler(void)

if(rtc_getitstatus(rtc_it_alr)!= reset)//鬧鐘中斷

rtc_clearitpendingbit(rtc_it_sec|rtc_it_ow); //清鬧鐘中斷

rtc_waitforlasttask();

}

其實任何乙個複雜的專案,都是由乙個又乙個簡單工程拼接而成的。當我們在砌磚時,不要忘記內心中規劃的那個美好的建築。

通過rtc_alarm_set可以設定定時時間。同時,需要在中斷處理函式中,設定相關標誌位

if(rtc_getitstatus(rtc_it_alr)!= reset)//鬧鐘中斷

在主迴圈中,檢查到標誌位後,進行相應處理,這裡僅僅進行簡單列印。

也可以通過rtc進行定時休眠和定時喚醒功能。具體方法是:

1. 主迴圈中,當sec達到15s時,設定15s後鬧鐘,然後進入待機模式sys_enter_standby;

主迴圈中,設定鬧鐘,進入待機模式

if (g_bsecflag)  //每秒計時器

}

2. rtc中斷定時中,清中斷。rtc定時中斷中,不需要做其他操作。定時到達後,rtc定時會自動喚醒mcu;

if(rtc_getitstatus(rtc_it_alr)!= reset)//鬧鐘中斷

注意:standby喚醒後,程式會重頭開始執行, standby之後語句執行不到。

通過rtc設定系統進入待機模式,並定時喚醒,是乙個非常省電而且非常可靠的方法。

rtc操作原始碼:

rtc休眠並定時喚醒原始碼

**通過uart2輸出,波特率115200,執行結果如下:

當時間到達15s時,自動休眠,休眠30s後,再通過rtc中斷喚醒,中斷喚醒後,從頭開始執行,當然,休眠時間和喚醒時間可以自行調整設定。

STM32應用 第7節 低功耗設計

隨著電池供電的應用場景越來越對,非常有必要深入理解和應用stm32的低功耗設計。程式執行過程中,呼叫 wfi 命令,即可進入睡眠模式。wfi可以通過任意中斷喚醒,這裡採用按鍵中斷喚醒。pa15 void exti15 10 irqhandler void exti clearitpendingbit...

STM32應用 第8節 AM2320單線驅動

和常用的dht11相比較,am2320溫濕度感測器的溫濕度等級高許多,是乙個不錯的感測器選擇。該驅動經過開發和長期測試,穩定好用,採用單獨的.c和.h檔案編寫,方便移植到不同程式中。static void am2320 gpio config void brief am2320 初始化函式 para...

基於STM32的FREERTOS應用的幾個常見問題

1 怎樣將 freertos 移植到不同的cortex m 核心?答 若需將 freertos 移植到正確的cortex m 產品,您必須從正確的目錄匯入 port.c 檔案。例如,若微控制器是帶有iar 工具的 cortex m0 核心,則您必須從 freertos source portable...