RT-Thread RTC設(shè)備學(xué)習(xí)筆記
前面我們學(xué)習(xí)了RTT的I2C總線設(shè)備的使用,文章鏈接:
RT-Thread I2C總線設(shè)備學(xué)習(xí)筆記
這節(jié)學(xué)習(xí)RTT里非常簡(jiǎn)單的設(shè)備--RTC設(shè)備
1、RTC設(shè)備簡(jiǎn)介
RTC是什么呢?相信學(xué)習(xí)嵌入式的伙伴都熟悉,以下介紹引用自RT-Thread文檔中心-RTC設(shè)備
RTC(Real-Time Clock)
實(shí)時(shí)時(shí)鐘可以提供精確的實(shí)時(shí)時(shí)間,它可以用于產(chǎn)生年、月、日、時(shí)、分、秒等信息。目前實(shí)時(shí)時(shí)鐘芯片大多采用精度較高的晶體振蕩器作為時(shí)鐘源。有些時(shí)鐘芯片為了在主電源掉電時(shí)還可以工作,會(huì)外加電池供電,使時(shí)間信息一直保持有效。
RT-Thread 的 RTC設(shè)備為操作系統(tǒng)的時(shí)間系統(tǒng)提供了基礎(chǔ)服務(wù)。面對(duì)越來越多的 IoT 場(chǎng)景,RTC 已經(jīng)成為產(chǎn)品的標(biāo)配,甚至在諸如 SSL 的安全傳輸過程中,RTC 已經(jīng)成為不可或缺的部分。
2、RTC設(shè)備操作接口
RT-Thread為RTC設(shè)備提供了三個(gè)用戶層次的應(yīng)用操作接口,分別是設(shè)置日期
、設(shè)置時(shí)間
和獲取當(dāng)前時(shí)間
。在RT-Thread的設(shè)備中,有且僅有一個(gè)RTC設(shè)備,設(shè)備名稱為"rtc"
。
2.1 設(shè)置日期(set_date)
rt_err_t set_date(rt_uint32_t year, rt_uint32_t month, rt_uint32_t day)
參數(shù) | 描述 |
---|---|
year | 待設(shè)置生效的年份 |
month | 待設(shè)置生效的月份 |
day | 待設(shè)置生效的日 |
返回 | —— |
RT_EOK | 設(shè)置成功 |
-RT_ERROR | 失敗,沒有找到 rtc 設(shè)備 |
其他錯(cuò)誤碼 | 失敗 |
如何使用呢?
/* 設(shè)置日期為2020年5月1號(hào) */
set_date(2020,5,1);
2.2 設(shè)置時(shí)間(set_time)
rt_err_t set_time(rt_uint32_t hour, rt_uint32_t minute, rt_uint32_t second)
參數(shù) | 描述 |
---|---|
hour | 待設(shè)置生效的時(shí) |
minute | 待設(shè)置生效的分 |
second | 待設(shè)置生效的秒 |
返回 | —— |
RT_EOK | 設(shè)置成功 |
-RT_ERROR | 失敗,沒有找到 rtc 設(shè)備 |
其他錯(cuò)誤碼 | 失敗 |
如何使用呢?
/* 設(shè)置時(shí)間為21點(diǎn)48分15秒 */
set_time(21, 48, 15);
2.3 獲取時(shí)間(time)
time_t time(time_t *t)
參數(shù) | 描述 |
---|---|
t | 時(shí)間數(shù)據(jù)指針 |
返回 | —— |
當(dāng)前時(shí)間值 | time_t |
如何使用呢?
/* 保存獲取的當(dāng)前時(shí)間值 */
time_t now;
/* 獲取時(shí)間 */
now = time(RT_NULL);
/* 打印輸出時(shí)間信息 */
rt_kprintf("%s\n", ctime(&now));
3、RTC設(shè)備的使用
本次實(shí)驗(yàn)基于小熊派開發(fā)板:
配置finsh命令、libc以及軟件模擬rtc選項(xiàng)。
打開RTC模塊使能
在終端處輸入date相關(guān)的命令,可讀取和設(shè)置RTC。
溫馨提示: 由于我們沒設(shè)置RTC硬件備份,所以這個(gè)時(shí)間設(shè)置僅僅是當(dāng)前有效,當(dāng)重新斷電重啟的時(shí)候,又會(huì)恢復(fù)為原來最開始的時(shí)間(如下圖所示)。
以下是date
命令在RT-Thread中的實(shí)現(xiàn),源碼位于rtc.c
#if defined(RT_USING_FINSH) && defined(FINSH_USING_MSH)
static void date(uint8_t argc, char **argv)
{
if (argc == 1)
{
time_t now;
/* output current time */
now = time(RT_NULL);
rt_kprintf("%s", ctime(&now));
}
else if (argc >= 7)
{
/* set time and date */
uint16_t year;
uint8_t month, day, hour, min, sec;
year = atoi(argv[1]);
month = atoi(argv[2]);
day = atoi(argv[3]);
hour = atoi(argv[4]);
min = atoi(argv[5]);
sec = atoi(argv[6]);
if (year > 2099 || year < 2000)
{
rt_kprintf("year is out of range [2000-2099]\n");
return;
}
if (month == 0 || month > 12)
{
rt_kprintf("month is out of range [1-12]\n");
return;
}
if (day == 0 || day > 31)
{
rt_kprintf("day is out of range [1-31]\n");
return;
}
if (hour > 23)
{
rt_kprintf("hour is out of range [0-23]\n");
return;
}
if (min > 59)
{
rt_kprintf("minute is out of range [0-59]\n");
return;
}
if (sec > 59)
{
rt_kprintf("second is out of range [0-59]\n");
return;
}
set_time(hour, min, sec);
set_date(year, month, day);
}
else
{
rt_kprintf("please input: date [year month day hour min sec] or date\n");
rt_kprintf("e.g: date 2018 01 01 23 59 59 or date\n");
}
}
MSH_CMD_EXPORT(date, get date and time or set [year month day hour min sec]);
#endif /* defined(RT_USING_FINSH) && defined(FINSH_USING_MSH) */
根據(jù)RTC設(shè)備API說明文檔,以及結(jié)合官方例程很容易可以實(shí)現(xiàn)以下demo:
/*
* Copyright (c) 2006-2019, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-09-09 RT-Thread first version
*/
#include <rtthread.h>
#include <board.h>
#include <rtdevice.h>
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
/* PLEASE DEFINE the LED0 pin for your board, such as: PA5 */
#define LED0_PIN GET_PIN(C, 13)
/*
* 程序清單:這是一個(gè) RTC 設(shè)備使用例程
* 例程導(dǎo)出了 rtc_sample 命令到控制終端
* 命令調(diào)用格式:rtc_sample
* 程序功能:設(shè)置RTC設(shè)備的日期和時(shí)間,延時(shí)一段時(shí)間后獲取當(dāng)前時(shí)間并打印顯示。
*/
#include <rtthread.h>
#include <rtdevice.h>
static int rtc_sample(int argc, char *argv[])
{
rt_err_t ret = RT_EOK;
time_t now;
/* 設(shè)置日期 */
ret = set_date(2020, 5, 2);
if (ret != RT_EOK)
{
rt_kprintf("set RTC date failed\n");
return ret;
}
/* 設(shè)置時(shí)間 */
ret = set_time(0, 21, 14);
if (ret != RT_EOK)
{
rt_kprintf("set RTC time failed\n");
return ret;
}
/* 延時(shí)3秒 */
rt_thread_mdelay(3000);
/* 獲取時(shí)間 */
now = time(RT_NULL);
rt_kprintf("%s\n", ctime(&now));
return ret;
}
/* 導(dǎo)出到 msh 命令列表中 */
MSH_CMD_EXPORT(rtc_sample, rtc sample);
int main(void)
{
int count = 1;
/* set LED0 pin mode to output */
rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
time_t now;
/* 獲取時(shí)間 */
now = time(RT_NULL);
rt_kprintf("%s\n", ctime(&now));
while (count++)
{
/* set LED0 pin level to high or low */
rt_pin_write(LED0_PIN, count % 2);
//LOG_D("Hello RT-Thread!");
rt_thread_mdelay(1000);
}
return RT_EOK;
}
導(dǎo)出rtc_sample命令后,就可以在終端上使用了。
如果我們要使用硬件RTC,那怎么辦呢?看board.h的RTC配置項(xiàng)相關(guān)說明:
/** if you want to use rtc(hardware) you can use the following instructions.
*
* STEP 1, open rtc driver framework(hardware) support in the RT-Thread Settings file
*
* STEP 2, define macro related to the rtc
* such as BSP_USING_ONCHIP_RTC
*
* STEP 3, modify your stm32xxxx_hal_config.h file to support rtc peripherals. define macro related to the peripherals
* such as #define HAL_RTC_MODULE_ENABLED
*
*/
根據(jù)說明提示:
-
1 設(shè)置RT-Thread Settings
-
2
#define BSP_USING_ONCHIP_RTC
-
3
#define HAL_RTC_MODULE_ENABLED
配置完編譯工程下載后,看到串口的錯(cuò)誤提示:
我一直以為是我哪里寫錯(cuò)了還是哪里配置錯(cuò)了,不知道問題出在哪里,最后跟蹤調(diào)試了下代碼以及查看以前的調(diào)試筆記終于找到了問題點(diǎn):
調(diào)試筆記:
STM32 使用HAL庫調(diào)試內(nèi)部RTC經(jīng)驗(yàn)總結(jié)
跳轉(zhuǎn)到定義,最后發(fā)現(xiàn)它是跳轉(zhuǎn)到這里了:
很明顯,這個(gè)地方有BUG,不應(yīng)該是一個(gè)值,果斷將這個(gè)部分注釋掉!(drv_rtc.c)
這樣的話跳轉(zhuǎn)過去的就是HAL庫的函數(shù)了嘛,這不就對(duì)了嘛:
發(fā)現(xiàn)論壇上也有大佬討論這個(gè)問題: https://www.rt-thread.org/qa/search.php?mod=forum&searchid=191&orderby=lastpost&ascdesc=desc&searchsubmit=yes&kw=RTC
將代碼下載到板子以后,這次終于正常了:
溫馨提示:由于小熊派上沒有帶RTC備用電池,所以軟件復(fù)位后時(shí)間是可以正常跑的,但是斷電還是會(huì)恢復(fù)到原來的初始值噢!后來我拿了野火的STM32F103ZET6(帶RTC備用電池)驗(yàn)證了一下是沒問題的,可以拿帶RTC備用電池的開發(fā)板嘗試一下!
大功告成!解決了問題,安心睡覺!祝各位朋友五一快樂!
公眾號(hào)粉絲福利時(shí)刻
這里我給大家申請(qǐng)到了福利,本公眾號(hào)讀者購買小熊派開發(fā)板可享受9折優(yōu)惠,有需要購買小熊派的朋友,淘寶搜索即可,跟客服說你是公眾號(hào):嵌入式云IOT技術(shù)圈
的粉絲,立享9折優(yōu)惠!
往期精彩
RT-Thread I2C總線設(shè)備學(xué)習(xí)筆記
RT-Thread ADC設(shè)備學(xué)習(xí)筆記
RT-Thread PIN設(shè)備學(xué)習(xí)筆記
RT-Thread UART設(shè)備驅(qū)動(dòng)框架初體驗(yàn)(中斷方式接收帶\r\n的數(shù)據(jù))
若覺得本次分享的文章對(duì)您有幫助,隨手點(diǎn)[在看]
并轉(zhuǎn)發(fā)分享,也是對(duì)我的支持。
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問題,請(qǐng)聯(lián)系我們,謝謝!