STM32的鬧鐘

STM32的鬧鐘真是鬧心啊......
因爲方案變化,這個星期要用到STM32的鬧鐘,就是讓程序每天固定時間醒來,完成任務後繼續睡眠,也可以根據情況任務的完成情況定下一次的醒來時間。
根本點:
1、鬧鐘固定時間醒;
2、指定下一次醒來的時間(不指定就是明天的同一時間醒來執行任務)。
看似很簡單,我想肯定就是半天的功夫了。
星期一開始幹,在網上查看教程,結果全部是標準庫的,方法繁瑣,我的工程文件是HAL庫的,是同事幫我生成的,我只負責寫代碼。
結果可想而知,無功而返,折騰到星期二晚上依然不見起鬧,轉念一想,還是看系統的HAL代碼,這樣很見效果,鬧鐘可以按時起鬧了。
星期三和星期四做其他工作就沒寫,星期五要完成指定下一次的醒來時間,想也簡單,把上次的代碼寫成函數直接調用就行了,結果因爲一行代碼的順序錯誤調試了大半天,最後才找到原因。

鬧鐘起鬧。
/ 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;

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);
}

/**Enable the WakeUp 
*/

if (HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 0, RTC_WAKEUPCLOCK_RTCCLK_DIV16) != HAL_OK)
{
_Error_Handler(FILE, LINE);
}

}

我把起鬧時間在系統初始化就指定了。
上面代碼在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();

  /* Clear the AlarmA interrupt pending bit */
  __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF);
}

}

/ 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();

                            }

}

}
程序執行正確,按時醒來,根據指定時間下一次再醒來。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章