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();
  里面是执行我写的任务代码。这个在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;
		}
}

  下面就是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();	
		}			
  }
}

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

  • 2
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值