RTC代表的是實時時鐘的意思。因為它提供的時鐘基準(zhǔn)比較準(zhǔn)確所以用處還是很多的。本文章主要講解基于STM32F103上的RTC鬧鐘中斷功能以及用鬧鐘中斷喚醒STM32的待機模式。
需要注意RTC的幾個要點:1.RTC的值被設(shè)定后它就會一直按照設(shè)定的基準(zhǔn)時間自己遞增,如果你的硬件設(shè)備上發(fā)現(xiàn)一個紐扣電池,那就是給RTC功能供電用的。因此就算關(guān)閉掉設(shè)備的主電源,RTC的運行也是不受影響的,當(dāng)然如果扣掉紐扣電池或者不帶紐扣電池它就不工作了。2.每次STM32復(fù)位后這個RTC值它重新計數(shù)還是繼續(xù)計數(shù)要考慮清楚3.RTC的值是有上限的,它的最大值就是2的32次方減一,這個數(shù)字很大因此不用太關(guān)心。
本文章的第一個例程是讓RTC一次設(shè)定值后一秒遞增一個單位,每過40秒就觸發(fā)一個鬧鐘并進入中斷,每經(jīng)過一秒就將秒數(shù)輸出到計算機上。下面就是RTC的初始化配置。(第一個程序從正點原子的程序上修改得來)
u8 RTC_Init()
{
u8 temp = 0;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP|RCC_APB1Periph_PWR,ENABLE);//電源時鐘和背部時鐘
PWR_BackupAccessCmd(ENABLE); //允許背部區(qū)域?qū)?/p>
if (BKP_ReadBackupRegister(BKP_DR1) != 0xC0B4)
{
BKP_DeInit();
RCC_LSEConfig(RCC_LSE_ON);
while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
{
temp++;
delay_ms(10);
}
if(temp>=250)return 1;
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
RCC_RTCCLKCmd(ENABLE);
RTC_WaitForLastTask();
RTC_WaitForSynchro();
RTC_ITConfig(RTC_IT_SEC|RTC_IT_ALR, ENABLE); //打開RTC的秒中斷和鬧鐘中斷
RTC_WaitForLastTask();
RTC_EnterConfigMode(); //進入配置RTC模式
RTC_SetPrescaler(32767);
RTC_SetCounter(0); //初始值設(shè)定為0s
RTC_WaitForLastTask();
RTC_SetAlarm(40); //鬧鐘值設(shè)定為40s
RTC_WaitForLastTask(); //等待上述配置完成
RTC_ExitConfigMode(); //退出配置模式
BKP_WriteBackupRegister(BKP_DR1, 0XC0B4);
PWR_BackupAccessCmd(DISABLE); //不允許背部區(qū)域?qū)懖僮?/p>
}
else
{
PWR_BackupAccessCmd(DISABLE);
RTC_WaitForSynchro();
RTC_ITConfig(RTC_IT_SEC|RTC_IT_ALR,ENABLE); //打開RTC的秒中斷和鬧鐘中斷
RTC_WaitForLastTask();
}
NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn; //RTC全局中斷的中斷配置
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
return 0;
}
//此初始化函數(shù)在主函數(shù)中的用法
while(RTC_Init())
{
printf("INIT Programing is ERROR!!\r\n");
}
if (BKP_ReadBackupRegister(BKP_DR1) != 0xC0B4) 的意思就是讓STM32上電后自檢是不是第一次運行這個程序。BKP_ReadBackupRegister(BKP_DR1)代表讀取BKP_DR1的值,如果第一次運行這個程序那這個值一定是0X0000,值和0XC0B4不相等就進入配置初始化程序。BKP_WriteBackupRegister(BKP_DR1, 0XC0B4)代表往BKP_DR1這個寄存器中寫入0XC0B4,注意BKP_DR1這個值被寫入之后就算復(fù)位他也不會被清除成0000。這樣的話就算復(fù)位或者重新上電,初始程序也不會再執(zhí)行一遍,所以RTC的值就不會再重新設(shè)置了。如果想要RTC的值重新從0開始計數(shù),那就可以吧0XC0B4改成一個新的數(shù)字,重新下載一次程序就可以了。
接下來的時鐘配置選擇打開外部低速時鐘LSE,它向RTC提供時鐘頻率。它頻率為是32.768KHZ.我們需要分頻后使用它。分成1HZ。
根據(jù)上圖1HZ = 32768/(32767+1) 所以RTC_SetPrescaler(32767)就能明白什么意思了吧。
為RTC提供時鐘頻率還是有兩種選擇的,這里我們用一種就夠了。
RTC_WaitForLastTask()和RTC_WaitForSynchro()都是等待最近的寫操作完成的意思,在RTC配置的時候這兩條尤其第一條都是很重要的,如果添加位置不當(dāng)或缺失程序有時候會卡在一個地方。
接下來打開RTC的秒中斷和鬧鐘中斷。在接下來就是對RTC的一些具體配置比如初始值和計數(shù)頻率以及鬧鐘數(shù)值的配置。按照ST的說法:
要用到RTC_WaitForLastTask()和RTC_EnterConfigMode(進入配置)和RTC_ExitConfigMode(退出配置); 這三個庫函數(shù)。
最后往BKP_DR1這個寄存器中寫入0XC0B4代表第一次RTC配置已經(jīng)完成。當(dāng)程序復(fù)位或者設(shè)備重新上電后它都不會在進入這個配置程序了。還要關(guān)閉背部寄存器的寫操作允許位。
else的程序就是第二次運行這個程序的時候執(zhí)行的命令。主要是打開RTC的兩個中斷。
之后的程序就是配置RTC全局中斷。這個中斷包括了鬧鐘和秒中斷。還有一個返回值要在主程序里面才能明白他的意義,簡單來說返回0代表RTC的配置沒有問題,返回1則相反。可以不用返回值的方法,因為一般沒問題。
下面就是RTC全局中斷的介紹:
void RTC_IRQHandler()
{
if(RTC_GetITStatus(RTC_IT_ALR)!=RESET) //是否鬧鐘中斷發(fā)生
{
printf("THE ALARM READY =%d \r\n",RTC_GetCounter());//輸出此時的秒數(shù)
RTC_ClearITPendingBit(RTC_IT_ALR);
PWR_BackupAccessCmd(ENABLE);
RTC_EnterConfigMode();
RTC_WaitForLastTask();
RTC_SetAlarm(40+RTC_GetCounter()); //配置下次鬧鐘為40s后
RTC_WaitForLastTask();
RTC_ExitConfigMode();
PWR_BackupAccessCmd(DISABLE);
}
if(RTC_GetITStatus(RTC_IT_SEC)!=RESET) //是否秒中斷發(fā)生
{
printf("Time is =%d \r\n",RTC_GetCounter()); //輸出此時的秒數(shù)
}
RTC_ClearITPendingBit(RTC_IT_SEC|RTC_IT_OW); //清除秒中斷標(biāo)志位和溢出位
RTC_WaitForLastTask();
}
下面就是程序運行的結(jié)果。
要注意的一點就是在中斷函數(shù)里面如果把判斷秒中斷的函數(shù)寫在了判斷鬧鐘中斷的前面,就會得到THE ALARM READY=41。。。還有一點就是就算沒有寫反,下一次鬧鐘的時間是81秒,如圖
下面就是待機喚醒:
待機模式是功耗最低的一種模式。外部復(fù)位(NRST 引腳)、 IWDG 復(fù)位、 WKUP 引腳上的上升沿或 RTC 鬧鐘事件
發(fā)生時,STM32從待機模式退出。其中外部復(fù)位和WKUP的方法比較簡單。主要講一下RTC鬧鐘喚醒。
這兩個程序一個是讓STM32的一個管腳接按鍵,按鍵按下的時候STM32進入待機狀態(tài),當(dāng)40秒的鬧鐘到來時喚醒STM32.
另一個是當(dāng)按鍵按下時候進入待機狀態(tài),鬧鐘設(shè)置為5S秒后,鬧鐘來臨時喚醒STM32.
void RTC_Init()
{
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP|RCC_APB1Periph_PWR,ENABLE);
PWR_WakeUpPinCmd(ENABLE);
PWR_BackupAccessCmd(ENABLE);
BKP_DeInit();
RCC_LSEConfig(RCC_LSE_ON);
while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
{
}
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
RCC_RTCCLKCmd(ENABLE);
RTC_WaitForLastTask();
RTC_WaitForSynchro();
RTC_ITConfig(RTC_IT_SEC, ENABLE);
RTC_WaitForLastTask();
RTC_EnterConfigMode();
RTC_SetCounter(0); //設(shè)置計數(shù)初始值
RTC_WaitForLastTask();
RTC_SetPrescaler(32767);
RTC_WaitForLastTask();
RTC_SetAlarm(40); //鬧鐘定時40S
RTC_WaitForLastTask();
RTC_ExitConfigMode();
NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn; //RTC全局中斷 它的優(yōu)先級要小于按鍵
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void EXTIX_Init(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource5);//配置按鍵PC5為外部中斷
EXTI_InitStructure.EXTI_Line=EXTI_Line5;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; //外部中斷的優(yōu)先級高于RTC
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void EXTI9_5_IRQHandler() //按鍵對應(yīng)的外部中斷
{
EXTI_ClearITPendingBit(EXTI_Line5);
PWR_EnterSTANDBYMode(); //進入待機模式
}
void RTC_IRQHandler() //RTC的中斷
{
if(RTC_GetITStatus(RTC_IT_SEC)!=RESET)
{
printf("TIME IS =%d \r\n",RTC_GetCounter());
}
RTC_ClearITPendingBit(RTC_IT_SEC|RTC_IT_OW);
RTC_WaitForLastTask();
}
以上的例程就是讓STM32運行模式下每秒都講時間顯示到計算機上,在按下連接PC5的按鍵后STM32進入待機模式,計時40秒后鬧鐘觸發(fā),STM32退出待機模式。要注意的是本程序沒有設(shè)置保存RTC的值,因此每次從待機退出后時間從零開始重新計數(shù)。而且按鍵觸發(fā)待機模式要在STM32上電40S之前,否則40S之后鬧鐘錯過沒法喚醒STM32.
13秒時候按下按鍵等待計數(shù)到40S的時候都是在待機過程中所以STM32串口沒法發(fā)送數(shù)據(jù)。40s鬧鐘來臨時計數(shù)又從0開始,退出待機模式相當(dāng)于復(fù)位。
第二個例程當(dāng)按鍵按下時候進入待機狀態(tài),鬧鐘設(shè)置為5S秒后,鬧鐘來臨時喚醒STM32.運行的時候?qū)⒚霐?shù)顯示到計算機。本程序在上面那個上更改少些地方即可。
void RTC_Init()
{
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP|RCC_APB1Periph_PWR,ENABLE);
PWR_WakeUpPinCmd(ENABLE);
PWR_BackupAccessCmd(ENABLE);
if(PWR_GetFlagStatus(PWR_FLAG_SB)!=RESET) //如果現(xiàn)在處于待機模式
{
PWR_ClearFlag(PWR_FLAG_SB); //清除待機模式
RTC_ITConfig(RTC_IT_SEC, ENABLE); //打開RTC中斷
RTC_WaitForSynchro();
}
else
{
BKP_DeInit();
RCC_LSEConfig(RCC_LSE_ON);
while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
{
}
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
RCC_RTCCLKCmd(ENABLE);
RTC_WaitForLastTask();
RTC_WaitForSynchro();
RTC_ITConfig(RTC_IT_SEC, ENABLE);
RTC_WaitForLastTask();
RTC_EnterConfigMode();
RTC_SetCounter(0);
RTC_WaitForLastTask();
RTC_SetPrescaler(32767);
RTC_WaitForLastTask();
//RTC_SetAlarm(35); //取消這個鬧鐘設(shè)置
RTC_WaitForLastTask();
RTC_ExitConfigMode();
}
NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void EXTI9_5_IRQHandler()
{
EXTI_ClearITPendingBit(EXTI_Line5);
RTC_ClearFlag(RTC_FLAG_SEC);
while(RTC_GetFlagStatus(RTC_FLAG_SEC)==RESET);
RTC_SetAlarm(RTC_GetCounter()+5); //鬧鐘在此時刻加上5秒
RTC_WaitForLastTask();
PWR_EnterSTANDBYMode(); //進入待機模式
}
其他的地方不需要更改。
這個程序的運行結(jié)果,可以看到在450s的時候進入待機模式5S之后程序接著運行。
時間并不是從0開始。
上一篇:STM32 RTC 讀寫不正確
下一篇:STM32F1RCC時鐘配置總結(jié)
推薦閱讀
史海拾趣
隨著技術(shù)的不斷積累和市場需求的擴大,聚洵半導(dǎo)體在產(chǎn)品研發(fā)上取得了顯著突破。公司不僅繼續(xù)深化在運算放大器領(lǐng)域的研發(fā),還成功擴展了產(chǎn)品線,涵蓋了模擬開關(guān)、電壓基準(zhǔn)、線性穩(wěn)壓器、電平轉(zhuǎn)換器等多種產(chǎn)品。這些產(chǎn)品廣泛應(yīng)用于通訊網(wǎng)絡(luò)、消費電子、工業(yè)控制等多個領(lǐng)域,滿足了市場多樣化的需求。同時,聚洵還獲得了多項技術(shù)專利和榮譽,如集成電路布圖設(shè)計專利和發(fā)明專利等,進一步鞏固了其在行業(yè)中的地位。
隨著環(huán)保意識的不斷提高和可持續(xù)發(fā)展理念的普及,杰力也開始注重環(huán)保和可持續(xù)發(fā)展方面的工作。公司采用環(huán)保材料和生產(chǎn)工藝,降低產(chǎn)品對環(huán)境的污染和破壞。同時,杰力還積極參與各類環(huán)保公益活動和社會責(zé)任項目,為推動電子行業(yè)的可持續(xù)發(fā)展做出貢獻(xiàn)。這些努力使得杰力在行業(yè)中樹立了良好的環(huán)保形象和社會責(zé)任感。
隨著公司規(guī)模的擴大和產(chǎn)品線的豐富,杰力開始積極拓展市場。公司參加各類電子展會和論壇,與國內(nèi)外客戶建立聯(lián)系和合作。同時,杰力還加強了品牌宣傳和推廣力度,通過媒體廣告、網(wǎng)絡(luò)營銷等方式提高品牌知名度和美譽度。這些努力使得杰力的產(chǎn)品在國內(nèi)外市場上獲得了更廣泛的認(rèn)可和應(yīng)用。
面對日益嚴(yán)峻的環(huán)保壓力,F(xiàn)iltran Ltd積極響應(yīng)可持續(xù)發(fā)展號召,將環(huán)保理念融入產(chǎn)品設(shè)計中。公司研發(fā)出了一系列綠色濾波器產(chǎn)品,采用可回收材料制造,并在生產(chǎn)過程中減少能源消耗和廢棄物排放。這些環(huán)保產(chǎn)品不僅滿足了市場對高性能濾波器的需求,還贏得了客戶的廣泛贊譽和信任。Filtran Ltd因此成為了電子行業(yè)環(huán)保實踐的典范。
為了進一步擴大市場份額,Directed Energy Inc積極尋求與全球范圍內(nèi)的合作伙伴建立合作關(guān)系。通過與知名電子產(chǎn)品制造商、分銷商和解決方案提供商的合作,公司成功將其產(chǎn)品推向了全球各地。這些合作伙伴不僅為Directed Energy Inc帶來了更多的商業(yè)機會,還幫助公司更好地了解不同市場的需求和趨勢,從而不斷調(diào)整和優(yōu)化產(chǎn)品策略。
隨著公司規(guī)模的擴大和產(chǎn)品線的豐富,Delock公司開始積極拓展國際市場。公司先是在歐美等發(fā)達(dá)國家設(shè)立了辦事處和分銷中心,隨后又逐步進入亞洲、非洲等新興市場。為了更好地滿足全球用戶的需求,Delock公司還針對不同地區(qū)的市場特點進行產(chǎn)品定制和營銷策略的調(diào)整。這一系列的全球化戰(zhàn)略讓Delock公司的產(chǎn)品在全球范圍內(nèi)獲得了廣泛的認(rèn)可和應(yīng)用。
請教:電路中使用了2段8位波段開關(guān),目的為了16選一,想找一個16選一的單刀多擲的波段開關(guān),不知道有沒有,請高手指點!… 查看全部問答∨ |
|
單片機是MSP430F149 液晶顯示屏是OCMJ15×20D. 液晶屏相關(guān)信息http://www.ec66.com/market/manual/OCMJ-D.pdf 程序如下: #include #define uchar unsigned char #define uint unsigned int ...… 查看全部問答∨ |
|
我出學(xué)驅(qū)動,用的是driverstudio3.2 配置好了各個方面之后,用向?qū)闪艘粋€驅(qū)動程序(按照書上說的做的),可是生成后一編譯就出現(xiàn)了 --------------------Configuration: TestDriver - Win32 Checked-------------------- Linking with DDK li ...… 查看全部問答∨ |
EMC上海研發(fā)中心招聘高級驅(qū)動開發(fā)工程師 Layered Driver Senior Software Engineer Responsibilities · Participate in feature requirements, design, implementation, testing, support and measurement of productivity based on established ...… 查看全部問答∨ |
我看ti的例子中有這樣定義: #ifdef __cplusplus #pragma DATA_SECTION(\\"AdcRegsFile\\" #else #pragma DATA_SECTION(AdcRegs,\\"AdcRegsFile\\" #endif volatile struct ADC_REGS AdcRegs; 諸如此類。 我理解為,將那些寄 ...… 查看全部問答∨ |
/********************************************************* 程序功能:MCU的片內(nèi)ADC對P6.0端口的電壓進行轉(zhuǎn)換 將模擬電壓值顯示在1602液晶上。 ************************************************** ...… 查看全部問答∨ |
設(shè)計資源 培訓(xùn) 開發(fā)板 精華推薦
- 利用STM32MP1和STM32MP2在嵌入式 Linux 平臺上部署有效的安全保護機制
- 超小但強大:MCU 的小尺寸封裝和集成如何幫助優(yōu)化空間受限的設(shè)計
- 德州儀器推出全球超小型 MCU,助力微型應(yīng)用創(chuàng)新
- Microchip推出電動兩輪車(E2W)生態(tài)系統(tǒng),加速電動出行創(chuàng)新
- 意法半導(dǎo)體推出STM32U3微控制器,面向遠(yuǎn)程、智能和可持續(xù)應(yīng)用,拓展超低功耗系列創(chuàng)新
- (一) ECloudIDE入門STM32-CubeMX工程創(chuàng)建與導(dǎo)入
- (二)ECloudIDE入門STM32-官方寄存器版例程使用
- Simulink STM32F407VGT6實現(xiàn)硬件在環(huán)
- openharmony:hilog_lite組件移植
- 英偉達(dá)芯片路線圖分析:Rubin GPU、Rubin Ultra 及 Feynman 架構(gòu)
- 自研芯片獲新進展,理想純電車型能否靠AI「翻身」?
- 新能源汽車智能座艙技術(shù)
- 今年落地L3級自動駕駛!放手一搏的廣汽,能否逆風(fēng)翻盤?
- 英偉達(dá)的開源人形機器人通用模型,IsaacGR00TN1會帶來什么?
- 2025固態(tài)電池全景圖:方興未艾,技術(shù)競逐
- 2025年NVIDIA自動駕駛安全報告
- 地平線2024年報:中國智能駕駛芯片龍頭破局!
- 從長城APP奔潰聊聊汽車是否應(yīng)過度智能化?
- DeepSeek動搖不了英偉達(dá)的“芯片帝國”?
- 【最后1天】MPS 有獎傾訴|說出哪些年讓你頭大的電感應(yīng)用問題,贏【頸部按摩儀、智能音箱】
- #Micropython大作戰(zhàn)#第三彈:搶樓!大家一起來整理micropython資料
- 新思科技技術(shù)日:硬件加速驗證解決方案專場 火熱報名中!
- 【免費試用】DFRobot micro:bit編程小車-麥昆
- 用心分享,一起成長!EEWORLD月月有獎優(yōu)秀主題/回復(fù)第28期開始啦~
- 限時秒殺,100本專業(yè)書籍——TI 中國大學(xué)計劃20周年
- 有獎問答 | TE 互連解決方案助力智慧城市智能監(jiān)控
- 泰克直播:帶您了解您所不知道的示波器使用技巧
- 齊聚一堂 恩智浦教大家玩轉(zhuǎn)新一代物聯(lián)網(wǎng)應(yīng)用 觀看視頻答題有好禮!
- 基于LTC7821設(shè)計可使DC-DC轉(zhuǎn)換器解決方案的尺寸減小50%
- 韓國開發(fā)全新鋰離子電池涂層,有望提升電動車?yán)m(xù)航里程
- 時鐘相位噪聲測量中雜散的討論及應(yīng)用
- 緯湃科技開發(fā)出新型控制器 采用單個控制器取代ECU
- 設(shè)計與實現(xiàn)一個光學(xué)心率監(jiān)測(HRM)系統(tǒng)
- PLC數(shù)據(jù)采集的實現(xiàn)方法
- 人機界面(HMI)的典型應(yīng)用
- 變頻器現(xiàn)場調(diào)試的注意事項
- AI戰(zhàn)斗機實力明顯,戰(zhàn)爭武器“未雨綢繆”的思考
- 半導(dǎo)體設(shè)備行業(yè)蒙上一層陰影,國產(chǎn)光刻機渡劫難