打印
[其他ST产品]

STM32的闹钟

[复制链接]
48|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
 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__);
  }

}

使用特权

评论回复
沙发
工程师犹饿死|  楼主 | 2024-2-27 17:47 | 只看该作者
 我把起闹时间再系统初始化就指定了。
  上面代码在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;
}

使用特权

评论回复
板凳
工程师犹饿死|  楼主 | 2024-2-27 17:47 | 只看该作者
上面我写了中断函数
  RTC_Alarm_IRQHandler();
  里面是执行我写的任务代码。这个在stm32L0xx_hal_rtc.c中

  中断代码:
//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;
                }
}

使用特权

评论回复
地板
工程师犹饿死|  楼主 | 2024-2-27 17:48 | 只看该作者
下面就是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();       
                }                       
  }
}

使用特权

评论回复
5
工程师犹饿死|  楼主 | 2024-2-27 17:48 | 只看该作者
 程序执行正确了,按时醒来,根据指定时间下一次再醒来。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

64

主题

808

帖子

0

粉丝