当前位置:首页 > 公众号精选 > 嵌入式云IOT技术圈
[导读]          点击 蓝字,关注我们!     开篇前先宣布一件很重大的事情,本公众号作者最近已经成为韦东山系列 产品授权的官方代理了,韦山老师亲笔签名的授权证书,如果以后大家有需要学习,可以随时加我微信咨询,也可以推荐学员来咨询,支持正版,拒绝盗版,

    

    

点击 蓝字,关注我们!


    开篇前先宣布一件很重大的事情,本公众号作者最近已经成为韦东山系列

产品授权的官方代理了,韦山老师亲笔签名的授权证书,如果以后大家有需要学习,可以随时加我微信咨询,也可以推荐学员来咨询,支持正版,拒绝盗版,在此谢谢大家啦。

视频购买链接:

接下来进入正文。

调试过程基于STM32F429如下型号。


    之前做项目用了正点原子的RTC例程,结果在应用的过程中就出问题了。

原子RTC的例程如下:

//RTC初始化//返回值:0,初始化成功;// 2,进入初始化模式失败;u8 RTC_Init(void){  RTC_Handler.Instance=RTC; RTC_Handler.Init.HourFormat=RTC_HOURFORMAT_24;//RTC设置为24小时格式  RTC_Handler.Init.AsynchPrediv=0X7F; //RTC异步分频系数(1~0X7F) RTC_Handler.Init.SynchPrediv=0XFF; //RTC同步分频系数(0~7FFF)  RTC_Handler.Init.OutPut=RTC_OUTPUT_DISABLE;  RTC_Handler.Init.OutPutPolarity=RTC_OUTPUT_POLARITY_HIGH; RTC_Handler.Init.OutPutType=RTC_OUTPUT_TYPE_OPENDRAIN; if(HAL_RTC_Init(&RTC_Handler)!=HAL_OK) return 2;  if(HAL_RTCEx_BKUPRead(&RTC_Handler,RTC_BKP_DR0)!=0X5050)//是否第一次配置 {  RTC_Set_Time(23,59,56,RTC_HOURFORMAT12_PM); //设置时间 ,根据实际时间修改 RTC_Set_Date(15,12,27,7); //设置日期 HAL_RTCEx_BKUPWrite(&RTC_Handler,RTC_BKP_DR0,0X5050);//标记已经初始化过了 } return 0;}
//RTC底层驱动,时钟配置//此函数会被HAL_RTC_Init()调用//hrtc:RTC句柄void HAL_RTC_MspInit(RTC_HandleTypeDef* hrtc){ RCC_OscInitTypeDef RCC_OscInitStruct; RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
__HAL_RCC_PWR_CLK_ENABLE();//使能电源时钟PWR HAL_PWR_EnableBkUpAccess();//取消备份区域写保护 RCC_OscInitStruct.OscillatorType=RCC_OSCILLATORTYPE_LSE;//LSE配置 RCC_OscInitStruct.PLL.PLLState=RCC_PLL_NONE; RCC_OscInitStruct.LSEState=RCC_LSE_ON; //RTC使用LSE HAL_RCC_OscConfig(&RCC_OscInitStruct);
PeriphClkInitStruct.PeriphClockSelection=RCC_PERIPHCLK_RTC;//外设为RTC PeriphClkInitStruct.RTCClockSelection=RCC_RTCCLKSOURCE_LSE;//RTC时钟源为LSE HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); __HAL_RCC_RTC_ENABLE();//RTC时钟使能}

    故障现象一、RTC设置日期和时间成功,按复位键读取刚刚设置的日期和时间也是成功的,但断电后时间就复位成原始值,也就是RTC_Init函数里下面这段默认的日期和时间

 if(HAL_RTCEx_BKUPRead(&RTC_Handler,RTC_BKP_DR0)!=0X5050)//是否第一次配置 {  RTC_Set_Time(23,59,56,RTC_HOURFORMAT12_PM); //设置时间 ,根据实际时间修改 RTC_Set_Date(15,12,27,7); //设置日期 HAL_RTCEx_BKUPWrite(&RTC_Handler,RTC_BKP_DR0,0X5050);//标记已经初始化过了    }

通过单步调试跟踪发现。

__IO uint32_t ret = 0 ;ret = HAL_RTCEx_BKUPRead(&RTC_Handler, RTC_BKP_DR0) ;

    ret的返回值并不是已经标记过的值0x5050,于是查看手册关于RTC备份寄存器的说明:

    问题定位:断电后再次读取的数值为0x0000 0000,而并不是我之前写入的0x5050,说明VBAT供电出现了问题,于是重新调整了电路,问题解决。


    故障现象二、RTC设置日期和时间后,读取并不是设置后的日期和时间,而是设置之前的数值

    单步调试跟踪发现问题出现在初始化的过程中,发生了硬件超时,此时发现,读出的ISR的值为0x80。

那咱们现在就要重点看看RTC_ISR这个寄存器了。

#define RTC_ISR_INITF                        ((uint32_t)0x00000040)


    也就是说当访问该寄存器数值的时候,&上RTC_ISR_INITF值不能等于0,我们再继续往下看手册。

我们看到,当第6位为1时,RTC才为初始化状态,可ISR=0x80,明显第6位为0,也就是说RTC工作不正常了。
两个原因:
1、要不RTC坏了(机率太小,除非芯片内部出现故障了,因为这是内部RTC)
2、外部晶振出问题了。(机率很大)
于是更改代码,配置为内部RTC时钟:

//RTC底层驱动,时钟配置//此函数会被HAL_RTC_Init()调用//hrtc:RTC句柄void HAL_RTC_MspInit(RTC_HandleTypeDef* hrtc){ RCC_OscInitTypeDef RCC_OscInitStruct; RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
__HAL_RCC_PWR_CLK_ENABLE();//使能电源时钟PWR HAL_PWR_EnableBkUpAccess();//取消备份区域写保护
/* RCC_OscInitStruct.OscillatorType=RCC_OSCILLATORTYPE_LSE;//LSE配置 RCC_OscInitStruct.PLL.PLLState=RCC_PLL_NONE; RCC_OscInitStruct.LSEState=RCC_LSE_ON; //RTC使用LSE */ //20190710 启用内部晶振 yangyuanxin RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI; RCC_OscInitStruct.LSIState = RCC_LSI_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; HAL_RCC_OscConfig(&RCC_OscInitStruct); /* PeriphClkInitStruct.PeriphClockSelection=RCC_PERIPHCLK_RTC;//外设为RTC PeriphClkInitStruct.RTCClockSelection=RCC_RTCCLKSOURCE_LSE;//RTC时钟源为LSE */ PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC; PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSI; HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
__HAL_RCC_RTC_ENABLE();//RTC时钟使能}

问题成功解决!

故障现象三、调用RTC设置日期和时间,在使用的过程中出现卡死现象

    我调用的是HAL_RTC_GetTime来获取时间,调用HAL_RTC_GetDate来获取日期。

我调用API的顺序是:

HAL_RTC_GetDate(xxxxx);

HAL_RTC_GetTime(xxxxx);

    结果软件卡死,针对这问题我折腾了很久都找不出问题的根源,后来详细看了API上的注释说明。

1、获取当前的时间 HAL_RTC_GetTime

/** * @brief Gets RTC current time. * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains * the configuration information for RTC. * @param sTime: Pointer to Time structure * @param Format: Specifies the format of the entered parameters. * This parameter can be one of the following values: * @arg RTC_FORMAT_BIN: Binary data format  * @arg RTC_FORMAT_BCD: BCD data format * @note You can use SubSeconds and SecondFraction (sTime structure fields returned) to convert SubSeconds * value in second fraction ratio with time unit following generic formula: * Second fraction ratio * time_unit= [(SecondFraction-SubSeconds)/(SecondFraction+1)] * time_unit * This conversion can be performed only if no shift operation is pending (ie. SHFP=0) when PREDIV_S >= SS * @note You must call HAL_RTC_GetDate() after HAL_RTC_GetTime() to unlock the values  * in the higher-order calendar shadow registers to ensure consistency between the time and date values. * Reading RTC current time locks the values in calendar shadow registers until current date is read. * @retval HAL status */HAL_StatusTypeDef HAL_RTC_GetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format){ uint32_t tmpreg = 0;
/* Check the parameters */ assert_param(IS_RTC_FORMAT(Format)); /* Get subseconds structure field from the corresponding register */ sTime->SubSeconds = (uint32_t)(hrtc->Instance->SSR); /* Get SecondFraction structure field from the corresponding register field*/ sTime->SecondFraction = (uint32_t)(hrtc->Instance->PRER & RTC_PRER_PREDIV_S);
/* Get the TR register */ tmpreg = (uint32_t)(hrtc->Instance->TR & RTC_TR_RESERVED_MASK); /* Fill the structure fields with the read parameters */ sTime->Hours = (uint8_t)((tmpreg & (RTC_TR_HT | RTC_TR_HU)) >> 16); sTime->Minutes = (uint8_t)((tmpreg & (RTC_TR_MNT | RTC_TR_MNU)) >>8); sTime->Seconds = (uint8_t)(tmpreg & (RTC_TR_ST | RTC_TR_SU)); sTime->TimeFormat = (uint8_t)((tmpreg & (RTC_TR_PM)) >> 16); /* Check the input parameters format */ if(Format == RTC_FORMAT_BIN) { /* Convert the time structure parameters to Binary format */ sTime->Hours = (uint8_t)RTC_Bcd2ToByte(sTime->Hours); sTime->Minutes = (uint8_t)RTC_Bcd2ToByte(sTime->Minutes); sTime->Seconds = (uint8_t)RTC_Bcd2ToByte(sTime->Seconds); } return HAL_OK;}

2、获取当前的日期 HAL_RTC_GetDate

/** * @brief Gets RTC current date. * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains * the configuration information for RTC. * @param sDate: Pointer to Date structure * @param Format: Specifies the format of the entered parameters. * This parameter can be one of the following values: * @arg RTC_FORMAT_BIN: Binary data format  * @arg RTC_FORMAT_BCD: BCD data format * @note You must call HAL_RTC_GetDate() after HAL_RTC_GetTime() to unlock the values  * in the higher-order calendar shadow registers to ensure consistency between the time and date values. * Reading RTC current time locks the values in calendar shadow registers until Current date is read. * @retval HAL status */HAL_StatusTypeDef HAL_RTC_GetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format){ uint32_t datetmpreg = 0;
/* Check the parameters */ assert_param(IS_RTC_FORMAT(Format)); /* Get the DR register */ datetmpreg = (uint32_t)(hrtc->Instance->DR & RTC_DR_RESERVED_MASK);
/* Fill the structure fields with the read parameters */ sDate->Year = (uint8_t)((datetmpreg & (RTC_DR_YT | RTC_DR_YU)) >> 16); sDate->Month = (uint8_t)((datetmpreg & (RTC_DR_MT | RTC_DR_MU)) >> 8); sDate->Date = (uint8_t)(datetmpreg & (RTC_DR_DT | RTC_DR_DU)); sDate->WeekDay = (uint8_t)((datetmpreg & (RTC_DR_WDU)) >> 13);
/* Check the input parameters format */ if(Format == RTC_FORMAT_BIN) { /* Convert the date structure parameters to Binary format */ sDate->Year = (uint8_t)RTC_Bcd2ToByte(sDate->Year); sDate->Month = (uint8_t)RTC_Bcd2ToByte(sDate->Month); sDate->Date = (uint8_t)RTC_Bcd2ToByte(sDate->Date); } return HAL_OK;}

结果看到注释里note的这段英文:

@note You must call HAL_RTC_GetDate() after HAL_RTC_GetTime() to unlock the values

in the higher-order calendar shadow registers to ensure consistency between the time and date values.

Reading RTC current time locks the values in calendar shadow registers until Current date is read.

    也就是说,调用顺序应该是先调用HAL_RTC_GetTime,再调用HAL_RTC_GetDate,否则不能解锁,即被锁死。

改一下获取日期和时间的顺序:

//获取日期和时间int Get_Date_Time(void){// //先调用GetTime,再调用GetDate,否则会发生锁死 if(HAL_OK == HAL_RTC_GetTime(&RTC_Handler, &RTC_TimeStruct, RTC_FORMAT_BIN) && HAL_OK == HAL_RTC_GetDate(&RTC_Handler, &RTC_DateStruct, RTC_FORMAT_BIN)) { current_init_time.year = RTC_DateStruct.Year + 2000; current_init_time.month = RTC_DateStruct.Month ; current_init_time.day = RTC_DateStruct.Date ; current_init_time.hour = RTC_TimeStruct.Hours ; current_init_time.minute = RTC_TimeStruct.Minutes ; return 0 ; }
return -1 ;}


问题解决!
    所以说,有时候我们口里念的年月日时分秒,也会在程序里,先获取日期,再获取时间,然而HAL库的规则恰恰是相反的,这一点要注意了,别被坑了。

END


“在看”我吗?





免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

在微控制器领域,MSP430与STM32无疑是两颗璀璨的明星。它们各自凭借其独特的技术特点和广泛的应用领域,在市场上占据了重要的位置。本文将深入解析MSP430与STM32之间的区别,探讨它们在不同应用场景下的优势和局限...

关键字: MSP430 STM32 单片机

STM32是由意法半导体公司(STMicroelectronics)推出的基于ARM Cortex-M内核的32位微控制器系列,以其高性能、低功耗、丰富的外设接口和强大的生态系统深受广大嵌入式开发者喜爱。本文将详细介绍S...

关键字: STM32 单片机

STM32与51单片机之间有什么差异呢?两者可以说是一场科技与性能的较量了。在科技飞速发展的今天,微控制器(MCU)已广泛应用于各类电子设备和系统中,发挥着举足轻重的作用。其中,STM32和51单片机作为两种常见的微控制...

关键字: STM32 51单片机 MCU

电磁铁是一种利用电流产生磁场的装置,具有快速响应、易于控制等特点,在工业自动化、电子设备、科学实验等领域有着广泛的应用。STM32是一款功能强大的微控制器,具有高性能、低功耗、易于编程等优点,是控制电磁铁的理想选择。本文...

关键字: 电磁铁 微控制器 STM32

边缘人工智能的实现涉及到三个基本 要素:安全性,连接性、自主性,而其中自主性是AI能力的体现,也是边缘AI有别于其他传统的物联网的关键。而通过ST Edge AI套件,就可以帮助各种不同类型的开发者实现覆盖全硬件平台的全...

关键字: 边缘人工智能 AI STM32

今天,小编将在这篇文章中为大家带来STM32单片机最小系统的有关报道,通过阅读这篇文章,大家可以对它具备清晰的认识,主要内容如下。

关键字: 单片机 单片机最小系统 STM32

STM32是一款由STMicroelectronics生产的微控制器系列,具有高性能、低功耗和丰富的外设资源。其中,串口通信是一种常用的通信方式,可以实现与其他设备之间的数据传输。

关键字: STM32 串口通信 微控制器

STM32是一种广泛使用的微控制器,具有丰富的通信接口。其中,串口通信是STM32与其他设备或系统进行数据交换的重要方式之一。本文将详细介绍STM32串口通信的原理、应用及常见故障。

关键字: STM32 串口通信

由于目前缺乏相应的监测技术,地下电缆线路出现异常运行状态无法被及时发现,久而久之易演变成大故障,最终只能通过更换地下电缆进行修复,耗费大量的人力、物力。鉴于此,开发了一种基于STM32的地下电缆异常状态检测系统,利用热传...

关键字: STM32 地下电缆

交通灯控制器是用于控制交通信号灯运行的设备,它可以根据交通流量、行人需求以及其他因素,动态地调整信号灯的变化时间和绿灯时长,以保证交通的流畅和安全。

关键字: 交通信号灯 STM32
关闭
关闭