25 linux ndk 头文件_正点原子Linux第二十五章RTC实时时钟实验
1)資料下載:點(diǎn)擊資料即可下載
2)對(duì)正點(diǎn)原子Linux感興趣的同學(xué)可以加群討論:935446741
3)關(guān)注正點(diǎn)原子公眾號(hào),獲取最新資料更新
第二十五章RTC實(shí)時(shí)時(shí)鐘實(shí)驗(yàn)
實(shí)時(shí)時(shí)鐘是很常用的一個(gè)外設(shè),通過(guò)實(shí)時(shí)時(shí)鐘我們就可以知道年、月、日和時(shí)間等信息。因此在需要記錄時(shí)間的場(chǎng)合就需要實(shí)時(shí)時(shí)鐘,可以使用專用的實(shí)時(shí)時(shí)鐘芯片來(lái)完成此功能,但是現(xiàn)在大多數(shù)的MCU或者M(jìn)PU內(nèi)部就已經(jīng)自帶了實(shí)時(shí)時(shí)鐘外設(shè)模塊。比如I.MX6U內(nèi)部的SNVS就提供了RTC功能,本章我們就學(xué)習(xí)如何使用I.MX6U內(nèi)部的RTC來(lái)完成實(shí)時(shí)時(shí)鐘功能。
25.1 I.MX6U RTC簡(jiǎn)介
如果學(xué)習(xí)過(guò)STM32的話應(yīng)該知道,STM32內(nèi)部有一個(gè)RTC外設(shè)模塊,這個(gè)模塊需要一個(gè)32.768KHz的晶振,對(duì)這個(gè)RTC模塊進(jìn)行初始化就可以得到一個(gè)實(shí)時(shí)時(shí)鐘。I.MX6U內(nèi)部也有個(gè)RTC模塊,但是不叫作“RTC”,而是叫做“SNVS”,這一點(diǎn)要注意!本章我們參考《I.MX6UL參考手冊(cè)》,而不是《I.MX6ULL參考手冊(cè)》,因?yàn)椤禝.MX6ULL參考手冊(cè)》很多SNVS相關(guān)的寄存器并沒(méi)有給出來(lái),不知道是為何?但是《I.MX6UL參考手冊(cè)》里面是完整的。所以本章我們使用《I.MX6UL參考手冊(cè)》,如果直接在《I.MX6UL參考手冊(cè)》的書(shū)簽里面找“RTC”相關(guān)的字眼是找不到的。I.MX6U系列的RTC是在SNVS里面,也就是《I.MX6UL參考手冊(cè)》的第46章“Chapter46 Secure Non-Volatile Storage(SNVS)”。
SNVS直譯過(guò)來(lái)就是安全的非易性存儲(chǔ),SNVS里面主要是一些低功耗的外設(shè),包括一個(gè)安全的實(shí)時(shí)計(jì)數(shù)器(RTC)、一個(gè)單調(diào)計(jì)數(shù)器(monotonic counter)和一些通用的寄存器,本章我們肯定只使用實(shí)時(shí)計(jì)數(shù)器(RTC)。SNVS里面的外設(shè)在芯片掉電以后由電池供電繼續(xù)運(yùn)行,I.MX6U-ALPHA開(kāi)發(fā)板上有一個(gè)紐扣電池,這個(gè)紐扣電池就是在主電源關(guān)閉以后為SNVS供電的,如圖25.1.1所示:
圖25.1.1 I.MX6U-ALPHA開(kāi)發(fā)板紐扣電池
因?yàn)榧~扣電池在掉電以后會(huì)繼續(xù)給SNVS供電,因此實(shí)時(shí)計(jì)數(shù)器就會(huì)一直運(yùn)行,這樣的話時(shí)間信息就不會(huì)丟失,除非紐扣電池沒(méi)電了。在有紐扣電池作為后備電源的情況下,不管系統(tǒng)主電源是否斷電,SNVS都正常運(yùn)行。SNVS有兩部分:SNVS_HP和SNVS_LP,系統(tǒng)主電源斷電以后SNVS_HP也會(huì)斷電,但是在后備電源支持下,SNVS_LP是不會(huì)斷電的,而且SNVS_LP是和芯片復(fù)位隔離開(kāi)的,因此SNVS_LP相關(guān)的寄存器的值會(huì)一直保存著。
SNVS分為兩個(gè)子模塊:SNVS_HP和SNVS_LP,也就是高功耗域(SNVS_HP)和低功耗域(SNVS_LP),這兩個(gè)域的電源來(lái)源如下:
SNVS_LP:專用的always-powered-on電源域,系統(tǒng)主電源和備用電源都可以為其供電。
SNVS_HP:系統(tǒng)(芯片)電源。
SNVS的這兩個(gè)子模塊的電源如圖25.1.2所示:
圖25.1.2 SNVS子模塊電源結(jié)構(gòu)圖
圖25.1.2中各個(gè)部分功能如下:
、VDD_HIGH_IN是系統(tǒng)(芯片)主電源,這個(gè)電源會(huì)同時(shí)供給給SNVS_HP和SNVS_LP。
、VDD_SNVS_IN是紐扣電池供電的電源,這個(gè)電源只會(huì)供給給SNVS_LP,保證在系統(tǒng)主電源VDD_HIGH_IN掉電以后SNVS_LP會(huì)繼續(xù)運(yùn)行。
、SNVS_HP部分。
、SNVS_LP部分,此部分有個(gè)SRTC,這個(gè)就是我們本章要使用的RTC。
其實(shí)不管是SNVS_HP還是SNVS_LP,其內(nèi)部都有一個(gè)SRTC,但是因?yàn)镾NVS_HP在系統(tǒng)電源掉電以后就會(huì)關(guān)閉,所以我們本章使用的是SNVS_LP內(nèi)部的SRTC。畢竟我們肯定都不想開(kāi)發(fā)板或者設(shè)備每次關(guān)閉以后時(shí)鐘都被清零,然后開(kāi)機(jī)以后先設(shè)置時(shí)鐘。
其實(shí)不管是SNVS_HP里面的RTC,還是SNVS_LP里面的SRTC,其本質(zhì)就是一個(gè)定時(shí)器,和我們?cè)诘诎苏轮v的EPIT定時(shí)器一樣,只要給它提供時(shí)鐘,它就會(huì)一直運(yùn)行。SRTC需要外界提供一個(gè)32.768KHz的時(shí)鐘,I.MX6U-ALPHA核心板上的32.768KHz的晶振就是提供這個(gè)時(shí)鐘的。寄存器SNVS_LPSRTCMR和SNVS_LPSRTCLR保存著秒數(shù),直接讀取這兩個(gè)寄存器的值就知道過(guò)了多長(zhǎng)時(shí)間了。一般以1970年1月1日為起點(diǎn),加上經(jīng)過(guò)的秒數(shù)即可得到現(xiàn)在的時(shí)間和日期,原理還是很簡(jiǎn)單的。SRTC也是帶有鬧鐘功能的,可以在寄存器SNVS_LPAR中寫(xiě)入鬧鐘時(shí)間值,當(dāng)時(shí)鐘值和鬧鐘值匹配的時(shí)候就會(huì)產(chǎn)生鬧鐘中斷,要使用時(shí)鐘功能的話還需要進(jìn)行一些設(shè)置,本章我們就不使用鬧鐘了。
接下來(lái)我們看一下本章要用到的與SRTC相關(guān)的部分寄存器,首先是SNVS_HPCOMR寄存器,這個(gè)寄存器我們只用到了位:NPSWA_EN(bit31),這個(gè)位是非特權(quán)軟件訪問(wèn)控制位,如果非特權(quán)軟件要訪問(wèn)SNVS的話此位必須為1。
接下來(lái)看一下寄存器SNVS_LPCR寄存器,此寄存器也只用到了一個(gè)位:SRTC_ENV(bit0),此位為1的話就使能STC計(jì)數(shù)器。
最后來(lái)看一下寄存器SNVS_SRTCMR和SNVS_SRTCLR,這兩個(gè)寄存器保存著RTC的秒數(shù),按照NXP官方的《6UL參考手冊(cè)》中的說(shuō)法,SNVS_SRTCMR保存著高15位,SNVS_SRTCLR保存著低32位,因此SRTC的計(jì)數(shù)器一共是47位。
但是!我在編寫(xiě)驅(qū)動(dòng)的時(shí)候發(fā)現(xiàn)按照手冊(cè)上說(shuō)的去讀取計(jì)數(shù)器值是錯(cuò)誤的!具體表現(xiàn)就是時(shí)間是混亂的,因此我在查找了NXP提供的SDK包中的fsl_snvs_hp.c以及Linux內(nèi)核中的rtc-snvs.c這兩個(gè)驅(qū)動(dòng)文件以后發(fā)現(xiàn)《6UL參考手冊(cè)》上對(duì)SNVS_SRTCMR和SNVS_SRTCLR的解釋是錯(cuò)誤的,經(jīng)過(guò)查閱這兩個(gè)文件,得到如下結(jié)論:
①、SRTC計(jì)數(shù)器是32位的,不是47位!
②、SNVS_SRTCMR的bit14:0這15位是SRTC計(jì)數(shù)器的高15位。
③、SNVS_SRTCLR的bit31:bit15這17位是SRTC計(jì)數(shù)器的低17位。
按照上面的解釋去讀取這兩個(gè)寄存器就可以得到正確的時(shí)間,如果要調(diào)整時(shí)間的話也是向這兩個(gè)寄存器寫(xiě)入要設(shè)置的時(shí)間值對(duì)應(yīng)的秒數(shù)就可以了,但是要修改這兩個(gè)寄存器的話要先關(guān)閉SRTC。
關(guān)于SNVS中和RTC有關(guān)的寄存器就介紹到這里,關(guān)于這些寄存器詳細(xì)的描述,請(qǐng)參考《I.MX6UL參考手冊(cè)》第2931頁(yè)的46.7小節(jié)。本章我們使用I.MX6U的SNVS_LP的SRTC,配置步驟如下:
1、初始化SNVS_SRTC
初始化SNVS_LP中的SRTC。
2、設(shè)置RTC時(shí)間
第一次使用RTC肯定要先設(shè)置時(shí)間。
3、使能RTC
配置好RTC并設(shè)置好初始時(shí)間以后就可以開(kāi)啟RTC了。
25.2硬件原理分析
本試驗(yàn)用到的資源如下:
、指示燈LED0。
、RGB LCD接口。
③、SRTC。
SRTC需要外接一個(gè)32.768KHz的晶振,在I.MX6U-ALPHA核心板上就有這個(gè)32.768KHz的晶振,原理圖如圖25.2.1所示:
圖25.2.1外接32.768KHz晶振
25.3實(shí)驗(yàn)程序編寫(xiě)
本實(shí)驗(yàn)對(duì)應(yīng)的例程路徑為:開(kāi)發(fā)板光盤(pán)-> 1、裸機(jī)例程->16_rtc。
25.3.1修改文件MCIMX6Y2.h
在第十三章移植的NXP官方SDK包是針對(duì)I.MX6ULL編寫(xiě)的,因此文件MCIMX6Y2.h中的結(jié)構(gòu)體SNVS_Type里面的寄存器是不全的,我們需要在其中加入本章實(shí)驗(yàn)所需要的寄存器,修改SNVS_Type為如下所示:
示例代碼25.3.1.1 SNVS_Type結(jié)構(gòu)體
1typedefstruct{
2 __IO uint32_t HPLR;
3 __IO uint32_t HPCOMR;
4 __IO uint32_t HPCR;
5 __IO uint32_t HPSICR;
6 __IO uint32_t HPSVCR;
7 __IO uint32_t HPSR;
8 __IO uint32_t HPSVSR;
9 __IO uint32_t HPHACIVR;
10 __IO uint32_t HPHACR;
11 __IO uint32_t HPRTCMR;
12 __IO uint32_t HPRTCLR;
13 __IO uint32_t HPTAMR;
14 __IO uint32_t HPTALR;
15 __IO uint32_t LPLR;
16 __IO uint32_t LPCR;
17 __IO uint32_t LPMKCR;
18 __IO uint32_t LPSVCR;
19 __IO uint32_t LPTGFCR;
20 __IO uint32_t LPTDCR;
21 __IO uint32_t LPSR;
22 __IO uint32_t LPSRTCMR;
23 __IO uint32_t LPSRTCLR;
24 __IO uint32_t LPTAR;
25 __IO uint32_t LPSMCMR;
26 __IO uint32_t LPSMCLR;
27}SNVS_Type;
25.3.2編寫(xiě)實(shí)驗(yàn)程序
本章實(shí)驗(yàn)在上一章例程的基礎(chǔ)上完成,更改工程名字為“rtc”,然后在bsp文件夾下創(chuàng)建名為“rtc”的文件夾,然后在bsp/rtc中新建bsp_rtc.c和bsp_rtc.h這兩個(gè)文件。在bsp_rtc.h中輸入如下內(nèi)容:
示例代碼25.3.2.1 bsp_rtc.h文件代碼
1 #ifndef _BSP_RTC_H
2 #define _BSP_RTC_H
3/***************************************************************
4 Copyright ? zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
5文件名 : bsp_rtc.h
6作者 : 左忠凱
7版本 : V1.0
8描述 : RTC驅(qū)動(dòng)頭文件。
9其他 : 無(wú)
10論壇 : http://www.openedv.com
11日志 : 初版V1.0 2019/1/3 左忠凱創(chuàng)建
12 ***************************************************************/
13 #include "imx6ul.h"
14
15/* 相關(guān)宏定義 */
16 #define SECONDS_IN_A_DAY (86400) /* 一天86400秒 */
17 #define SECONDS_IN_A_HOUR (3600) /* 一個(gè)小時(shí)3600秒 */
18 #define SECONDS_IN_A_MINUTE (60) /* 一分鐘60秒 */
19 #define DAYS_IN_A_YEAR (365) /* 一年365天 */
20 #define YEAR_RANGE_START (1970) /* 開(kāi)始年份1970年 */
21 #define YEAR_RANGE_END (2099) /* 結(jié)束年份2099年 */
22
23/* 時(shí)間日期結(jié)構(gòu)體 */
24struct rtc_datetime
25{
26unsignedshort year; /* 范圍為:1970 ~ 2099 */
27unsignedchar month; /* 范圍為:1 ~ 12 */
28unsignedchar day; /* 范圍為:1 ~ 31 (不同的月,天數(shù)不同).*/
29unsignedchar hour; /* 范圍為:0 ~ 23 */
30unsignedchar minute; /* 范圍為:0 ~ 59 */
31unsignedchar second; /* 范圍為:0 ~ 59 */
32};
33
34/* 函數(shù)聲明 */
35void rtc_init(void);
36void rtc_enable(void);
37void rtc_disable(void);
38unsignedint rtc_coverdate_to_seconds(struct rtc_datetime
*datetime);
39unsignedint rtc_getseconds(void);
40void rtc_setdatetime(struct rtc_datetime *datetime);
41void rtc_getdatetime(struct rtc_datetime *datetime);
42
43 #endif
第16到21行定義了一些宏,比如一天多少秒、一小時(shí)多少秒等等,這些宏將用于將秒轉(zhuǎn)換為時(shí)間,或者將時(shí)間轉(zhuǎn)換為秒。第24行定義了一個(gè)結(jié)構(gòu)體rtc_datetime,此結(jié)構(gòu)體用于描述日期和時(shí)間參數(shù)。剩下的就是一些函數(shù)聲明了,很簡(jiǎn)單。
在文件bsp_rtc.c中輸入如下內(nèi)容:
示例代碼25.3.2.2 bsp_rtc.c文件代碼
/***************************************************************
Copyright ? zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_rtc.c
作者 : 左忠凱
版本 : V1.0
描述 : RTC驅(qū)動(dòng)文件。
其他 : 無(wú)
論壇 : http://www.openedv.com
日志 : 初版V1.0 2019/1/3 左忠凱創(chuàng)建
***************************************************************/
1 #include "bsp_rtc.h"
2 #include "stdio.h"
3
4/*
5 * @description :初始化RTC
6 */
7void rtc_init(void)
8{
9/*
10 * 設(shè)置HPCOMR寄存器
11 * bit[31] 1 : 允許訪問(wèn)SNVS寄存器,一定要置1
12 */
13 SNVS->HPCOMR |=(1<<31);
14
15 #if0
16struct rtc_datetime rtcdate;
17
18 rtcdate.year =2018U;
19 rtcdate.month =12U;
20 rtcdate.day =13U;
21 rtcdate.hour =14U;
22 rtcdate.minute =52;
23 rtcdate.second =0;
24 rtc_setDatetime(&rtcdate); /* 初始化時(shí)間和日期 */
25 #endif
26 rtc_enable(); /* 使能RTC */
27}
28
29/*
30 * @description : 開(kāi)啟RTC
31 */
32void rtc_enable(void)
33{
34/*
35 * LPCR寄存器bit0置1,使能RTC
36 */
37 SNVS->LPCR |=1<<0;
38while(!(SNVS->LPCR &0X01)); /* 等待使能完成 */
39
40}
41
42/*
43 * @description : 關(guān)閉RTC
44 */
45void rtc_disable(void)
46{
47/*
48 * LPCR寄存器bit0置0,關(guān)閉RTC
49 */
50 SNVS->LPCR &=~(1<<0);
51while(SNVS->LPCR &0X01); /* 等待關(guān)閉完成*/
52}
53
54/*
55 * @description : 判斷指定年份是否為閏年,閏年條件如下:
56 * @param – year : 要判斷的年份
57 * @return : 1 是閏年,0 不是閏年
58 */
59unsignedchar rtc_isleapyear(unsignedshort year)
60{
61unsignedchar value=0;
62
63if(year %400==0)
64 value =1;
65else
66{
67if((year %4==0)&&(year %100!=0))
68 value =1;
69else
70 value =0;
71}
72return value;
73}
74
75/*
76 * @description : 將時(shí)間轉(zhuǎn)換為秒數(shù)
77 * @param – datetime : 要轉(zhuǎn)換日期和時(shí)間。
78 * @return : 轉(zhuǎn)換后的秒數(shù)
79 */
80unsignedint rtc_coverdate_to_seconds(struct rtc_datetime *datetime)
81{
82unsignedshort i =0;
83unsignedint seconds =0;
84unsignedint days =0;
85unsignedshort monthdays[]={0U,0U,31U,59U,90U,120U,151U,
181U,212U,243U,273U,304U,334U};
86
87for(i =1970; i < datetime->year; i++)
88{
89 days += DAYS_IN_A_YEAR; /* 平年,每年365天 */
90if(rtc_isleapyear(i)) days +=1; /* 閏年多加一天 */
91}
92
93 days += monthdays[datetime->month];
94if(rtc_isleapyear(i)&&(datetime->month >=3)) days +=1;
95
96 days += datetime->day -1;
97
98 seconds = days * SECONDS_IN_A_DAY +
99 datetime->hour * SECONDS_IN_A_HOUR +
100 datetime->minute * SECONDS_IN_A_MINUTE +
101 datetime->second;
102
103return seconds;
104}
105
106/*
107 * @description : 設(shè)置時(shí)間和日期
108 * @param – datetime : 要設(shè)置的日期和時(shí)間
109 * @return : 無(wú)
110 */
111void rtc_setdatetime(struct rtc_datetime *datetime)
112{
113
114unsignedint seconds =0;
115unsignedint tmp = SNVS->LPCR;
116
117 rtc_disable(); /* 設(shè)置寄存器HPRTCMR和HPRTCLR前要先關(guān)閉RTC */
118/* 先將時(shí)間轉(zhuǎn)換為秒 */
119 seconds = rtc_coverdate_to_seconds(datetime);
120 SNVS->LPSRTCMR =(unsignedint)(seconds >>17);/* 設(shè)置高16位 */
121 SNVS->LPSRTCLR =(unsignedint)(seconds <<15);/* 設(shè)置地16位 */
122
123/* 如果此前RTC是打開(kāi)的在設(shè)置完RTC時(shí)間以后需要重新打開(kāi)RTC */
124if(tmp &0x1)
125 rtc_enable();
126}
127
128/*
129 * @description : 將秒數(shù)轉(zhuǎn)換為時(shí)間
130 * @param - seconds : 要轉(zhuǎn)換的秒數(shù)
131 * @param – datetime : 轉(zhuǎn)換后的日期和時(shí)間
132 * @return : 無(wú)
133 */
134void rtc_convertseconds_to_datetime(unsignedint seconds,
struct rtc_datetime *datetime)
135{
136unsignedint x;
137unsignedint secondsRemaining, days;
138unsignedshort daysInYear;
139
140/* 每個(gè)月的天數(shù) */
141unsignedchar daysPerMonth[]={0U,31U,28U,31U,30U,31U,
30U,31U,31U,30U,31U,30U,31U};
142
143 secondsRemaining = seconds;/* 剩余秒數(shù)初始化 */
144 days = secondsRemaining / SECONDS_IN_A_DAY +1;
145 secondsRemaining = secondsRemaining % SECONDS_IN_A_DAY;
146
147/* 計(jì)算時(shí)、分、秒 */
148 datetime->hour = secondsRemaining / SECONDS_IN_A_HOUR;
149 secondsRemaining = secondsRemaining % SECONDS_IN_A_HOUR;
150 datetime->minute = secondsRemaining /60;
151 datetime->second = secondsRemaining % SECONDS_IN_A_MINUTE;
152
153/* 計(jì)算年 */
154 daysInYear = DAYS_IN_A_YEAR;
155 datetime->year = YEAR_RANGE_START;
156while(days > daysInYear)
157{
158/* 根據(jù)天數(shù)計(jì)算年 */
159 days -= daysInYear;
160 datetime->year++;
161
162/* 處理閏年 */
163if(!rtc_isleapyear(datetime->year))
164 daysInYear = DAYS_IN_A_YEAR;
165else/*閏年,天數(shù)加一 */
166 daysInYear = DAYS_IN_A_YEAR +1;
167}
168/*根據(jù)剩余的天數(shù)計(jì)算月份 */
169if(rtc_isleapyear(datetime->year))/* 如果是閏年的話2月加一天 */
170 daysPerMonth[2]=29;
171for(x =1; x <=12; x++)
172{
173if(days <= daysPerMonth[x])
174{
175 datetime->month = x;
176break;
177}
178else
179{
180 days -= daysPerMonth[x];
181}
182}
183 datetime->day = days;
184}
185
186/*
187 * @description : 獲取RTC當(dāng)前秒數(shù)
188 * @param : 無(wú)
189 * @return : 當(dāng)前秒數(shù)
190 */
191unsignedint rtc_getseconds(void)
192{
193unsignedint seconds =0;
194
195 seconds =(SNVS->LPSRTCMR <<17)|(SNVS->LPSRTCLR >>15);
196return seconds;
197}
198
199/*
200 * @description : 獲取當(dāng)前時(shí)間
201 * @param – datetime : 獲取到的時(shí)間,日期等參數(shù)
202 * @return : 無(wú)
203 */
204void rtc_getdatetime(struct rtc_datetime *datetime)
205{
206unsignedint seconds =0;
207 seconds = rtc_getseconds();
208 rtc_convertseconds_to_datetime(seconds, datetime);
209}
文件bsp_rtc.c里面一共有9個(gè)函數(shù),依次來(lái)看一下這些函數(shù)的意義。函數(shù)rtc_init明顯是初始化rtc的,主要是使能RTC,也可以在rtc_init函數(shù)里面設(shè)置時(shí)間。函數(shù)rtc_enable和rtc_disable分別是RTC的使能和禁止函數(shù)。函數(shù)rtc_isleapyear用于判斷某一年是否為閏年。函數(shù)rtc_coverdate_to_seconds負(fù)責(zé)將給定的日期和時(shí)間信息轉(zhuǎn)換為對(duì)應(yīng)的秒數(shù)。函數(shù)rtc_setdatetime用于設(shè)置時(shí)間,也就是設(shè)置寄存器SNVS_LPSRTCMR和SNVS_LPSRTCLR。函數(shù)rtc_convertseconds_to_datetime用于將給定的秒數(shù)轉(zhuǎn)換為對(duì)應(yīng)的時(shí)間值。函數(shù)rtc_getseconds獲取SRTC當(dāng)前秒數(shù),其實(shí)就是讀取寄存器SNVS_LPSRTCMR和SNVS_LPSRTCLR,然后將其結(jié)合成47位的值。最后一個(gè)函數(shù)rtc_getdatetime是獲取時(shí)間值。
我們?cè)趍ain函數(shù)里面先初始化RTC,然后進(jìn)入3S倒計(jì)時(shí),如果這3S內(nèi)按下了KEY0按鍵,那么就設(shè)置SRTC的日期。如果3S倒計(jì)時(shí)結(jié)束以后沒(méi)有按下KEY0,也就是沒(méi)有設(shè)置SRTC時(shí)間的話就進(jìn)入while循環(huán),然后讀取RTC的時(shí)間值并且顯示在LCD上,在文件main.c中輸入如下所示內(nèi)容:
示例代碼25.3.2.3 main.c文件代碼
/**************************************************************
Copyright ? zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : mian.c
作者 : 左忠凱
版本 : V1.0
描述 : I.MX6U開(kāi)發(fā)板裸機(jī)實(shí)驗(yàn)17 RTC實(shí)時(shí)時(shí)鐘實(shí)驗(yàn)
其他 : 本實(shí)驗(yàn)學(xué)習(xí)如何編寫(xiě)I.MX6U內(nèi)部的RTC驅(qū)動(dòng),使用內(nèi)部RTC可以實(shí)現(xiàn)
一個(gè)實(shí)時(shí)時(shí)鐘。
論壇 : http://www.openedv.com
日志 : 初版V1.0 2019/1/15 左忠凱創(chuàng)建
**************************************************************/
1 #include "bsp_clk.h"
2 #include "bsp_delay.h"
3 #include "bsp_led.h"
4 #include "bsp_beep.h"
5 #include "bsp_key.h"
6 #include "bsp_int.h"
7 #include "bsp_uart.h"
8 #include "bsp_lcd.h"
9 #include "bsp_lcdapi.h"
10 #include "bsp_rtc.h"
11 #include "stdio.h"
12
13/*
14 * @description : main函數(shù)
15 * @param : 無(wú)
16 * @return : 無(wú)
17 */
18int main(void)
19{
20 unsignedchar key =0;
21 int t =0;
22 int i =3; /* 倒計(jì)時(shí)3S */
23 char buf[160];
24 struct rtc_datetime rtcdate;
25 unsignedchar state = OFF;
26
27 int_init(); /* 初始化中斷(一定要最先調(diào)用!) */
28 imx6u_clkinit(); /* 初始化系統(tǒng)時(shí)鐘 */
29 delay_init(); /* 初始化延時(shí) */
30 clk_enable(); /* 使能所有的時(shí)鐘 */
31 led_init(); /* 初始化led */
32 beep_init(); /* 初始化beep */
33 uart_init(); /* 初始化串口,波特率115200 */
34 lcd_init(); /* 初始化LCD */
35 rtc_init(); /* 初始化RTC */
36
37 tftlcd_dev.forecolor = LCD_RED;
38 lcd_show_string(50,10,400,24,24, /* 顯示字符串 */
(char*)"ALPHA-IMX6UL RTC TEST");
39 tftlcd_dev.forecolor = LCD_BLUE;
40 memset(buf,0,sizeof(buf));
41
42 while(1)
43 {
44 if(t==100)/* 1s時(shí)間到了 */
45 {
46 t=0;
47 printf("will be running %d s......r", i);
48
49 lcd_fill(50,40,370,70, tftlcd_dev.backcolor);/* 清屏 */
50 sprintf(buf,"will be running %ds......", i);
51 lcd_show_string(50,40,300,24,24, buf);
52 i--;
53 if(i <0)
54 break;
55 }
56
57 key = key_getvalue();
58 if(key == KEY0_VALUE)
59 {
60 rtcdate.year =2018;
61 rtcdate.month =1;
62 rtcdate.day =15;
63 rtcdate.hour =16;
64 rtcdate.minute =23;
65 rtcdate.second =0;
66 rtc_setdatetime(&rtcdate);/* 初始化時(shí)間和日期 */
67 printf("rn RTC Init finishrn");
68 break;
69 }
70
71 delayms(10);
72 t++;
73 }
74 tftlcd_dev.forecolor = LCD_RED;
75 lcd_fill(50,40,370,70, tftlcd_dev.backcolor);/* 清屏 */
76 lcd_show_string(50,40,200,24,24,(char*)"Current Time:");
77 tftlcd_dev.forecolor = LCD_BLUE;
78
79 while(1)
80 {
81 rtc_getdatetime(&rtcdate);
82 sprintf(buf,"%d/%d/%d %d:%d:%d",rtcdate.year, rtcdate.month,
rtcdate.day, rtcdate.hour, rtcdate.minute, rtcdate.second);
83 lcd_fill(50,70,300,94, tftlcd_dev.backcolor);
84 lcd_show_string(50,70,250,24,24,(char*)buf);/* 顯示字符串 */
85
86 state =!state;
87 led_switch(LED0,state);
88 delayms(1000);/* 延時(shí)一秒 */
89 }
90 return0;
91}
第35行調(diào)用函數(shù)rtc_init初始化RTC。
第42到73行是倒計(jì)時(shí)3S,如果在這3S 內(nèi)按下了KEY0按鍵就會(huì)調(diào)用函數(shù)rtc_setdatetime設(shè)置當(dāng)前的時(shí)間。如果3S到技術(shù)結(jié)束以后沒(méi)有按下KEY0那就表示不需要設(shè)置時(shí)間,跳出循環(huán),執(zhí)行下面的代碼。
第79到89行就是主循環(huán),此循環(huán)每隔1S調(diào)用函數(shù)rtc_getdatetime獲取一次時(shí)間值,并且通過(guò)串口打印給SecureCRT或者在LCD上顯示。
25.4編譯下載驗(yàn)證
25.4.1 編寫(xiě)Makefile和鏈接腳本
修改Makefile中的TARGET為rtc,然后在在INCDIRS和SRCDIRS中加入“bsp/rtc”,修改后的Makefile如下:
示例代碼25.4.1 Makefile代碼
1 CROSS_COMPILE ?= arm-linux-gnueabihf-
2 TARGET ?=rtc
3
4/* 省略掉其它代碼...... */
5
6 INCDIRS := imx6ul
7 stdio/include
8 bsp/clk
9 bsp/led
10 bsp/delay
11 bsp/beep
12 bsp/gpio
13 bsp/key
14 bsp/exit
15 bsp/int
16 bsp/epittimer
17 bsp/keyfilter
18 bsp/uart
19 bsp/lcd
20 bsp/rtc
21
22 SRCDIRS := project
23 stdio/lib
24 bsp/clk
25 bsp/led
26 bsp/delay
27 bsp/beep
28 bsp/gpio
29 bsp/key
30 bsp/exit
31 bsp/int
32 bsp/epittimer
33 bsp/keyfilter
34 bsp/uart
35 bsp/lcd
36 bsp/rtc
37
38/* 省略掉其它代碼...... */
39
40 clean:
41 rm -rf $(TARGET).elf $(TARGET).dis $(TARGET).bin $(COBJS)$(SOBJS)
第2行修改變量TARGET為“rtc”,也就是目標(biāo)名稱為“rtc”。
第20行在變量INCDIRS中添加RTC驅(qū)動(dòng)頭文件(.h)路徑。
第36行在變量SRCDIRS中添加RTC驅(qū)動(dòng)驅(qū)動(dòng)文件(.c)路徑。
鏈接腳本保持不變。
25.4.2編譯下載
使用Make命令編譯代碼,編譯成功以后使用軟件imxdownload將編譯完成的rtc.bin文件下載到SD卡中,命令如下:
chmod 777 imxdownload //給予imxdownload可執(zhí)行權(quán)限,一次即可
./imxdownload rtc.bin /dev/sdd //燒寫(xiě)到SD卡中
燒寫(xiě)成功以后將SD卡插到開(kāi)發(fā)板的SD卡槽中,然后復(fù)位開(kāi)發(fā)板。程序一開(kāi)始進(jìn)入3S倒計(jì)時(shí),如圖25.4.2.1所示:
圖24.4.2.13秒鐘倒計(jì)時(shí)
如果在倒計(jì)數(shù)結(jié)束之前按下KEY0,那么RTC就會(huì)被設(shè)置為我們代碼中設(shè)置的時(shí)間和日期值,RTC運(yùn)行如圖24.4.2.2所示:
圖24.4.2.2設(shè)置有的時(shí)間
我們?cè)趍ain函數(shù)中設(shè)置的時(shí)間是2018年1月15日,16點(diǎn)23分0秒,在倒計(jì)數(shù)結(jié)束之前按下KEY0按鍵設(shè)置RTC,圖24.4.2.2中的時(shí)間就是我們?cè)O(shè)置以后的時(shí)間。
總結(jié)
以上是生活随笔為你收集整理的25 linux ndk 头文件_正点原子Linux第二十五章RTC实时时钟实验的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java compare 返回值_关于J
- 下一篇: python table数据抓取_Pyt