STM32的鬧鐘真是鬧心啊......
由於方案變化,這個星期要用到STM32的鬧鐘,就是讓程序天天固定時間醒來,完成任務後繼續睡眠,也能夠根據狀況任務的完成狀況定下一次的醒來時間。
根本點:
一、鬧鐘固定時間醒;
二、指定下一次醒來的時間(不指定就是明天的同一時間醒來執行任務)。
看似很簡單,我想確定就是半天的功夫了。
星期一開始幹,在網上查看教程,結果所有是標準庫的,方法繁瑣,個人工程文件是HAL庫的,是同事幫我生成的,我只負責寫代碼。
結果可想而知,無功而返,折騰到星期二晚上依然不見起鬧,轉念一想,仍是看系統的HAL代碼,這樣很見效果,鬧鐘能夠按時起鬧了。
星期三和星期四作其餘工做就沒寫,星期五要完成指定下一次的醒來時間,想也簡單,把上次的代碼寫成函數直接調用就好了,結果由於一行代碼的順序錯誤調試了大半天,最後才找到緣由。ide
鬧鐘起鬧。
/ RTC init function /
void MX_RTC_Init(void)
{
RTC_TimeTypeDef sTime;
RTC_DateTypeDef sDate;
RTC_AlarmTypeDef sAlarm;
/*Initialize RTC Only
/
hrtc.Instance = RTC;//全局的實例
hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
hrtc.Init.AsynchPrediv = 127;
hrtc.Init.SynchPrediv = 255;
hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
if (HAL_RTC_Init(&hrtc) != HAL_OK)
{
_Error_Handler(FILE, LINE);
}
/*Initialize RTC and set the Time and Date
/
sTime.Hours = 0x12;
sTime.Minutes = 0x13;
sTime.Seconds = 0x03;
sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sTime.StoreOperation = RTC_STOREOPERATION_RESET;
if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
{
_Error_Handler(FILE, LINE);
}函數
sDate.WeekDay = RTC_WEEKDAY_FRIDAY;
sDate.Month = RTC_MONTH_MAY;
sDate.Date = 0x05;
sDate.Year = 0x13;ui
if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
{
_Error_Handler(FILE, LINE);
}調試
/**Enable the Alarm A */
sAlarm.AlarmTime.Hours = 0x12;
sAlarm.AlarmTime.Minutes = 0x14;
sAlarm.AlarmTime.Seconds = 0x0;
sAlarm.AlarmTime.SubSeconds = 0x0;
sAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET;
sAlarm.AlarmMask = RTC_ALARMMASK_DATEWEEKDAY|RTC_ALARMMASK_HOURS
|RTC_ALARMMASK_MINUTES;
sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL;
sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
sAlarm.AlarmDateWeekDay = 0x1;
sAlarm.Alarm = RTC_ALARM_A;
if (HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BCD) != HAL_OK)
{
_Error_Handler(FILE, LINE);
}code
/**Enable the WakeUp */
if (HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 0, RTC_WAKEUPCLOCK_RTCCLK_DIV16) != HAL_OK)
{
_Error_Handler(FILE, LINE);
}orm
}教程
我把起鬧時間在系統初始化就指定了。
上面代碼在RTC.c文件中。事件
void HAL_RTC_AlarmIRQHandler(RTC_HandleTypeDef hrtc)
{
/ Get the AlarmA interrupt source enable status /
if(__HAL_RTC_ALARM_GET_IT_SOURCE(hrtc, RTC_IT_ALRA) != RESET)
{
/ Get the pending status of the AlarmA Interrupt /
if(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAF) != RESET)
{
/ AlarmA callback */
HAL_RTC_AlarmAEventCallback(hrtc);
RTC_Alarm_IRQHandler();it
/* Clear the AlarmA interrupt pending bit */ __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF); }
}io
/ Get the AlarmB interrupt source enable status /
if(__HAL_RTC_ALARM_GET_IT_SOURCE(hrtc, RTC_IT_ALRB) != RESET)
{
/ Get the pending status of the AlarmB Interrupt /
if(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBF) != RESET)
{
/ AlarmB callback /
HAL_RTCEx_AlarmBEventCallback(hrtc);
/* Clear the AlarmB interrupt pending bit */ __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRBF); }
}
/ Clear the EXTI's line Flag for RTC Alarm /
__HAL_RTC_ALARM_EXTI_CLEAR_FLAG();
/ Change RTC state /
hrtc->State = HAL_RTC_STATE_READY;
}
上面我寫了中斷函數
RTC_Alarm_IRQHandler();
裏面是執行我寫的任務代碼。
中斷代碼:
//RTC鬧鐘中斷事件
void RTC_Alarm_IRQHandler(void)
{
RTC_HandleTypeDef *hrtcTMP;
hrtcTMP=&hrtc;//獲取當前的RTC實例
switch(YCWorkStatus){ case 0://沒有開始 break; case 1://進行中 SendBuffer[20]=0x11; SendBuffer[21]=0x11; SendBuffer[22]=0x11; SendBuffer[23]=0x11; SendBuffer[24]=0x11; SendBuffer[25]=0x11; IRQHandlerCount=IRQHandlerCount+1; SendBuffer[26]=IRQHandlerCount; break; case 2://完成 __HAL_RTC_ALARMA_DISABLE(hrtcTMP);//使鬧鐘A不能 __HAL_RTC_ALARM_CLEAR_FLAG(hrtcTMP, RTC_FLAG_ALRAF);//清理標誌 break; default: //不支持的命令 break; }
}
下面就是main裏面的主要代碼:
int main(void)
{
HAL_Init();//初始化HAL庫
SystemClock_Config();//配置系統時鐘
/ 初始化外圍設置 /
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC_Init();
MX_LPUART1_UART_Init();
MX_USART1_UART_Init();
MX_RTC_Init();
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3, GPIO_PIN_SET); //打開LORA電源PB3(1) HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4, GPIO_PIN_RESET); //M0 M1同時配置0處於工做狀態(M0) HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5, GPIO_PIN_RESET); //(M1)
HAL_Delay (1000);//延時10毫秒
HAL_UART_Transmit(&hlpuart1,SendBuffer,sizeof(SendBuffer),10); //串口1向LORA發送整個緩衝區
YCWorkStatus=1; RTC_HandleTypeDef *hrtcTMP; hrtcTMP=&hrtc;//獲取當前的RTC實例
while (1)
{
GetCurrentDateTime();
MainSendCount=MainSendCount+1;
HAL_UART_Transmit(&hlpuart1,SendBuffer,sizeof(SendBuffer),10); //串口1向LORA發送整個緩衝區
HAL_Delay (200);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_15, GPIO_PIN_SET);HAL_Delay (200); //P15閃爍
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_15, GPIO_PIN_RESET);HAL_Delay (200); //P15閃爍
SendBuffer[40]=MainSendCount; if(MainSendCount>=255){ MainSendCount=0; } if(IRQHandlerCount>=2){ HAL_NVIC_DisableIRQ(RTC_IRQn); IRQHandlerCount=0; SendBuffer[20]=0x99; SendBuffer[21]=0x99; SendBuffer[22]=0x99; SendBuffer[23]=0x99; SendBuffer[24]=0x99; SendBuffer[25]=0x99; GetCurrentDateTime();//獲得當前的時間和日期 ITMP=(uint8_t)CurrentTime.Minutes+2; RTC_Set_AlarmA(CurrentTime.Hours,ITMP,0); SendBuffer[51]=CurrentTime.Minutes; SendBuffer[52]=ITMP; //__HAL_RCC_APB1_RELEASE_RESET(); //__HAL_RCC_APB2_RELEASE_RESET(); //__HAL_RTC_ALARMA_DISABLE(hrtcTMP);//使鬧鐘A不能 //__HAL_RTC_ALARM_DISABLE_IT(hrtcTMP,RTC_IT_ALRA);//使鬧鐘A中斷不能 //__HAL_RTC_ALARM_CLEAR_FLAG(hrtcTMP, RTC_FLAG_ALRAF);//清理標誌 //__HAL_RTC_WAKEUPTIMER_DISABLE(hrtcTMP); //__HAL_RTC_ALARM_ENABLE_IT // //HAL_NVIC_EnableIRQ(RTC_IRQn); //__HAL_RCC_RTC_DISABLE(); //HAL_NVIC_DisableIRQ(RTC_IRQn); //__HAL_RTC_ALARM_EXTI_DISABLE_IT(); //__HAL_RTC_ALARM_EXTI_CLEAR_FLAG(); //__HAL_RTC_ALARM_EXTI_DISABLE_IT(); }
}
}程序執行正確,按時醒來,根據指定時間下一次再醒來。