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

                            }

}

}
程序执行正确,按时醒来,根据指定时间下一次再醒来。

上一篇:关于ubuntu18.x和windows10时间不同步解决方法


下一篇:Linux内核配置编译及Makefile简单分析