上次實(shí)驗(yàn)完成了對(duì)實(shí)時(shí)時(shí)鐘的基本功能——計(jì)時(shí)的實(shí)驗(yàn),這次在計(jì)時(shí)的基礎(chǔ)上對(duì)RTC的可編程鬧鐘的功能進(jìn)行測(cè)試。
RTC 單元提供兩個(gè)可編程鬧鐘,即鬧鐘 A 和鬧鐘 B。
可通過(guò)將 RTC_CR 寄存器中的 ALRAE 和 ALRBE 位置 1 來(lái)使能可編程鬧鐘功能。如果日歷亞秒、秒、分鐘、小時(shí)、日期或日分別與鬧鐘寄存器RTC_ALRMASSR/RTC_ALRMAR 和RTC_ALRMBSSR/RTC_ALRMBR 中編程的值相匹配,則 ALRAF 和 ALRBF 標(biāo)志會(huì)被置為1??赏ㄟ^(guò) RTC_ALRMAR 和 RTC_ALRMBR 寄存器的 MSKx 位以及 RTC_ALRMASSR 和RTC_ALRMBSSR 寄存器的 MASKSSx 位單獨(dú)選擇各日歷字段??赏ㄟ^(guò) RTC_CR 寄存器中的 ALRAIE 和 ALRBIE 位使能鬧鐘中斷。
鬧鐘 A 和鬧鐘 B(如果已通過(guò) RTC_CR 寄存器中的位 OSEL[0:1] 使能)可連接到 RTC_ALARM輸出??赏ㄟ^(guò) RTC_CR 寄存器的 POL 位配置 RTC_ALARM 極性。
要對(duì)可編程的鬧鐘(鬧鐘 A 或鬧鐘 B)進(jìn)行編程或更新,必須執(zhí)行類似的步驟:
- 將 RTC_CR 寄存器中的 ALRAE 或 ALRBE 位清零以禁止鬧鐘 A 或鬧鐘 B。
- 輪詢 RTC_ISR 寄存器中的 ALRAWF 或 ALRBWF 位,直到其中一個(gè)置 1,以確保鬧鐘寄存器可以訪問(wèn)。大約需要 2 個(gè) RTCCLK 時(shí)鐘周期(由于時(shí)鐘同步)。
- 編程鬧鐘 A 或鬧鐘 B 寄存器(RTC_ALRMASSR/RTC_ALRMAR 或 RTC_ALRMBSSR/RTC_ALRMBR)。
- 將 RTC_CR 寄存器中的 ALRAE 或 ALRBE 位置 1 以再次使能鬧鐘 A 或鬧鐘 B。
注意:約 2 個(gè) RTCCLK 時(shí)鐘周期(由于時(shí)鐘同步)后,將執(zhí)行對(duì) RTC_CR 寄存器的更改。
寫程序前先簡(jiǎn)單了解下鬧鐘相關(guān)的寄存器:
RTC鬧鐘A寄存器 (RTC_ALRMAR)
位 31 MSK4:鬧鐘 A 日期掩碼 (Alarm A date mask)
0:如果日期/日匹配,則鬧鐘 A 置 1
1:在鬧鐘 A 比較中,日期/日無(wú)關(guān)
位 30 WDSEL:星期幾選擇 (Week day selection)
0:DU[3:0] 代表日期的個(gè)位
1:DU[3:0] 代表星期幾。DT[1:0] 為無(wú)關(guān)位。
位 29:28 DT[1:0]:日期的十位(BCD 格式)
位 27:24 DU[3:0]:日期的個(gè)位或日(BCD 格式)
位 23 MSK3:鬧鐘 A 小時(shí)掩碼 (Alarm A hours mask)
0:如果小時(shí)匹配,則鬧鐘 A 置 1?
1:在鬧鐘 A 比較中,小時(shí)無(wú)關(guān)
位 22 PM :AM/PM 符號(hào) (AM/PM notation)
0:AM 或 24 小時(shí)制
1:PM
位 21:20 HT[1:0]:小時(shí)的十位(BCD 格式)
位 19:16 HU[3:0]:小時(shí)的個(gè)位(BCD 格式)
位 15 MSK2:鬧鐘 A 分鐘掩碼 (Alarm A minutes mask)
0:如果分鐘匹配,則鬧鐘 A 置 1
1:在鬧鐘 A 比較中,分鐘無(wú)關(guān)
位 14:12 MNT[2:0]:分鐘的十位(BCD 格式)
位 11:8 MNU[3:0]:分鐘的個(gè)位(BCD 格式)
位 7 MSK1:鬧鐘 A 秒掩碼 (Alarm A seconds mask)
0:如果秒匹配,則鬧鐘 A 置 1
1:在鬧鐘 A 比較中,秒無(wú)關(guān)
位 6:4 ST[2:0]:秒的十位(BCD 格式)
位 3:0 SU[3:0]:秒的個(gè)位(BCD 格式)
鬧鐘B寄存器RTC_ALRMBR與鬧鐘A寄存器RTC_ALRMAR的寄存器功能一樣,這里不再進(jìn)行介紹。
RTC鬧鐘配置函數(shù)和中斷處理函數(shù)
void RTC_AlarmConfig(u8 Alarm_sel,u8 Alarm_set,u8 Alarm_day,u8 Alarm_hour,u8 Alarm_minute)
{
u32 prigroup = 0;
u32 priority = 0;
u32 temp = 0;
//1.解除保護(hù)
//寫密鑰:先寫0xca,再寫0x53
RTC- >WPR = 0XCA;
RTC- >WPR = 0X53;
switch(Alarm_set)
{
case SPECIAL_DAY:
temp |= Alarm_day< 24; //設(shè)置具體星期
break;
case WORK_DAY:
case ALL_DAY:
temp |= (u32)(1< 31);
break;
case DISABLE_DAY:
break;
}
temp |= 1< 30; //用星期來(lái)匹配
temp |= ((Alarm_hour/10)< 4 | (Alarm_hour%10))< 16 | 1< 23;
temp |= ((Alarm_minute/10)< 4 | (Alarm_minute%10))< 8 | 1< 15;
temp |= 1< 7;
//關(guān)閉鬧鐘,等待鬧鐘可寫入
if(Alarm_sel == ALARM_A)
{
RTC- >CR &= ~(1< 8);
while((RTC- >ISR & (1< 0)) == 0){}
RTC- >ALRMAR = temp;
RTC- >CR |= 1< 8; //開啟鬧鐘A
//開鬧鐘A的中斷
RTC- >CR |= 1< 12;
//清中斷標(biāo)記
RTC- >ISR &= ~(1< 8);
}
else if(Alarm_sel == ALARM_B)
{
RTC- >CR &= ~(1< 9);
while((RTC- >ISR & (1< 1)) == 0){}
RTC- >ALRMBR = temp;
RTC- >CR |= 1< 9; //開啟鬧鐘B
//開鬧鐘B的中斷
RTC- >CR |= 1< 13;
//清中斷標(biāo)記
RTC- >ISR &= ~(1< 9);
}
//鬧鐘中斷對(duì)應(yīng)于外部中斷線,因此要設(shè)置外部中斷線(17)
EXTI- >IMR |= 1< 17;
EXTI- >RTSR |= 1< 17; //鬧鐘中斷需設(shè)置為上升沿
//清中斷標(biāo)記
EXTI- >PR |= 1< 17;
prigroup = NVIC_GetPriorityGrouping();
priority = NVIC_EncodePriority(prigroup,1,2);
NVIC_SetPriority(RTC_Alarm_IRQn,priority);
NVIC_EnableIRQ(RTC_Alarm_IRQn);
switch(Alarm_set)
{
case SPECIAL_DAY:
break;
case WORK_DAY:
temp = (RTC- >DR & 0x0000e000) >>13;
if(temp >5)
{
if(Alarm_sel == ALARM_A)
RTC- >CR &= ~(1< 8);
else if(Alarm_sel == ALARM_B)
RTC- >CR &= ~(1< 9);
}
else
{
if(Alarm_sel == ALARM_A)
RTC- >CR |= 1< 8;
else if(Alarm_sel == ALARM_B)
RTC- >CR |= 1< 9;
}
break;
case ALL_DAY:
break;
case DISABLE_DAY:
if(Alarm_sel == ALARM_A)
RTC- >CR &= ~(1< 8);
else if(Alarm_sel == ALARM_B)
RTC- >CR &= ~(1< 9);
break;
}
//2. 再次保護(hù)
RTC- >WPR = 0XFF; //寫任意值,再次保護(hù)
}
//中斷處理
void RTC_Alarm_IRQHandler()
{
EXTI- >PR |= 1< 17;
//中斷處理
if(RTC- >ISR & (1< 8))
{
RTC- >ISR &= ~(1< 8);
//鬧鐘A中斷處理
LED_Toggle(DS1);
}
else if(RTC- >ISR & (1< 9))
{
RTC- >ISR &= ~(1< 9);
//鬧鐘B中斷處理
}
}
由于鬧鐘的編寫比較簡(jiǎn)單,這里就不多加描述了,接下來(lái)編寫主函數(shù)進(jìn)行測(cè)試。
#include "stm32f4xx.h"
#include "usart.h"
#include "delay.h"
#include "stdio.h"
#include "RTC.h"
#include "led.h"
typedef struct
{
u8 shi;
u8 fen;
u8 miao;
u8 nian;
u8 yue;
u8 ri;
u8 xingqi;
}TIME_Typedef;
TIME_Typedef time = {1};
int main()
{
LED_Init();
Usart1_Init(115200);
RTC_Init(23,59,50,19,7,9,2);
RTC_AlarmConfig(ALARM_A,SPECIAL_DAY,3,0,0);
while(1)
{
time.shi = ((RTC- >TR & 0x300000) >>20)*10 + ((RTC- >TR & 0xf0000) >>16);
time.fen = ((RTC- >TR & 0x7000) >>12)*10 + ((RTC- >TR & 0xf00) >>8);
time.miao = ((RTC- >TR & 0x70) >>4)*10 + (RTC- >TR & 0xf);
printf("%d:%d:%drn",time.shi,time.fen,time.miao);
Delay_ms(1000);
}
}
初始時(shí)間設(shè)為23:59:50,鬧鐘時(shí)間設(shè)為0:0:0。運(yùn)行程序,經(jīng)過(guò)10秒鐘后,鬧鐘進(jìn)入中斷,LED燈實(shí)現(xiàn)翻轉(zhuǎn),RTC鬧鐘實(shí)驗(yàn)測(cè)試成功。
-
寄存器
+關(guān)注
關(guān)注
31文章
5433瀏覽量
124244 -
計(jì)時(shí)器
+關(guān)注
關(guān)注
1文章
432瀏覽量
33681 -
中斷處理
+關(guān)注
關(guān)注
0文章
94瀏覽量
11245 -
BCD編碼
+關(guān)注
關(guān)注
0文章
9瀏覽量
6135 -
RTC
+關(guān)注
關(guān)注
2文章
621瀏覽量
68742
發(fā)布評(píng)論請(qǐng)先 登錄
STM32 RTC實(shí)時(shí)時(shí)鐘(一)

RTC實(shí)時(shí)時(shí)鐘簡(jiǎn)介
如何去實(shí)現(xiàn)STM32的實(shí)時(shí)時(shí)鐘RTC的時(shí)間計(jì)算部分
如何去使用STM32的實(shí)時(shí)時(shí)鐘RTC呢
RTC是什么?RTC實(shí)時(shí)時(shí)鐘實(shí)驗(yàn)
STM32F2技術(shù)培訓(xùn)_實(shí)時(shí)時(shí)鐘_RTC
ALIENTEK_MINISTM32_實(shí)驗(yàn)11_RTC實(shí)時(shí)時(shí)鐘實(shí)驗(yàn)
STM32 RTC實(shí)時(shí)時(shí)鐘資料下載

淺談RTC實(shí)時(shí)時(shí)鐘特征與原理
STM32CubeMX | 40 - 實(shí)時(shí)時(shí)鐘RTC的使用(日歷和鬧鐘)

stm32f4 RTC實(shí)時(shí)時(shí)鐘解析

STM32CubeMX系列|RTC實(shí)時(shí)時(shí)鐘

評(píng)論