PY32F003F18之RTC

news2024/10/6 10:39:20

一、RTC振荡器

PY32F003F18实时时钟的振荡器是内部RC振荡器,频率为32.768KHz。它也可以使用HSE时钟,不建议使用。HAL库提到LSE振荡器,但PY32F003F18实际上没有这个振荡器。

缺点:CPU掉电后,需要重新配置RTC,这个确实不太友好,有点像是鸡肋,在要求不严格的场合,凑合使用吧。

RTC时钟框图如下:

二、RTC的HAL库有一个不是很严重的bug

 PY32F003F18的HAL库润年函数中有一个BUG,不是很严重,因为2400年是一个闰年,它把年定义为字节型变量,是没有办法分辨出是不是闰年。

闰年的计算方法:年数能被4整除,但不能被100年整除,为闰年;若年数能400年整除,也为闰年

HAL库确实不大好,它喜欢用全局变量来实现其功能,让人受不了。我改了,让它适合自己需要的。HAL处的好处,就是我们可以从中抠出自己需要的部分,修修改改,就可以了,比HAL库的灵活多了。时刻不忘黑它一把,因为人云亦云的人太多了。

三、非完全HAL库测试程序

如果你觉得HAL库,就用HAL中的程序,也是可以的。

#include "RTC.h"
#include "LED.h"
#include "stdio.h"  //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()

uint8_t Century;//世纪,21世纪用20表示
RTC_DateTypeDef  RTC_DateStructureure;//用来保存读到的"年月日"
RTC_TimeTypeDef  RTC_TimeStructureure;//用来保存读到的"时分秒"
RTC_AlarmTypeDef RTC_AlarmStructureure;

void RTC_Init(void);
void RTC_Display(void);

//函数功能:读"RTC计数寄存器"
uint32_t Read_RTC_Time_Counter(void)
{
  uint16_t high1 = 0U, high2 = 0U, low = 0U;
  uint32_t timecounter = 0U;

  high1 = READ_REG(RTC->CNTH & RTC_CNTH_RTC_CNT);//读"RTC计数寄存器高位RTC_CNTH"
  low   = READ_REG(RTC->CNTL & RTC_CNTL_RTC_CNT);//读"RTC计数寄存器低位RTC_CNTL"
  high2 = READ_REG(RTC->CNTH & RTC_CNTH_RTC_CNT);//读"RTC计数寄存器高位RTC_CNTH"

  if (high1 != high2)
  {//读"RTC计数寄存器低位RTC_CNTL"时,发现"RTC计数寄存器高位RTC_CNTH"中的数据发生改变了
    //In this case the counter roll over during reading of CNTL and CNTH registers,
    //read again CNTL register then return the counter value
    timecounter = (((uint32_t) high2 << 16U) | READ_REG(RTC->CNTL & RTC_CNTL_RTC_CNT));
  }
  else
  {
    //No counter roll over during reading of CNTL and CNTH registers, 
		//counter value is equal to first value of CNTL and CNTH
    timecounter = (((uint32_t) high1 << 16U) | low);
  }

  return timecounter;
}

//函数功能:
//等待RTC写操作结束
//返回0,表示退出RTC配置模式,开始更新RTC寄存器
HAL_StatusTypeDef Enter_RTC_Init_Mode(void)
{
  uint32_t tickstart = 0U;

  tickstart = HAL_GetTick();
  /* Wait till RTC is in INIT state and if Time out is reached exit */
  while ( (RTC->CRL & RTC_CRL_RTOFF) == (uint32_t)RESET )
  {//读"RTC控制寄存器RTC_CRL"中的RTOFF,若RTOFF=0,则上一次对RTC寄存器的写操作仍在进行
    if ((HAL_GetTick() - tickstart) >  RTC_TIMEOUT_VALUE)
    {//RTC_TIMEOUT_VALUE=2000,最大等待时间为2000ms
      return HAL_TIMEOUT;
    }
  }

  _HAL_RTC_WRITEPROTECTION_DISABLE(RTC);
	//将"RTC控制寄存器RTC_CRL"中的CNF=0,退出配置模式,开始更新RTC寄存器
	//Disable the write protection for RTC registers

  return HAL_OK;
}

//函数功能:
//等待RTC写操作结束
//返回0,表示RTC写操作结束
HAL_StatusTypeDef Exit_RTC_Init_Mode(void)
{
  uint32_t tickstart = 0U;

  _HAL_RTC_WRITEPROTECTION_ENABLE(RTC);
	//将"RTC控制寄存器RTC_CRL"中的CNF=1,进入RTC配置模式
	
	tickstart = HAL_GetTick();
  while ((RTC->CRL & RTC_CRL_RTOFF) == RTC_CRL_RTOFF)
  {//读"RTC控制寄存器RTC_CRL"中的RTOFF,若RTOFF=1,则上一次对RTC寄存器的写操作已经完成
    if ((HAL_GetTick() - tickstart) >  RTC_RTOFF_RESET_TIMEOUT_VALUE)
    {//RTC_RTOFF_RESET_TIMEOUT_VALUE=4,最大等待时间为4ms
      break;
    }
  }

  tickstart = HAL_GetTick();
  while ((RTC->CRL & RTC_CRL_RTOFF) == (uint32_t)RESET)
  {//读"RTC控制寄存器RTC_CRL"中的RTOFF,若RTOFF=0,则上一次对RTC寄存器的写操作仍在进行
    if ((HAL_GetTick() - tickstart) >  RTC_TIMEOUT_VALUE)
    {//RTC_TIMEOUT_VALUE=2000,最大等待时间为2000ms
      return HAL_TIMEOUT;
    }
  }

  return HAL_OK;
}

//函数功能:将TimeCounter写入"RTC计数寄存器"
HAL_StatusTypeDef Write_RTC_Time_Counter( uint32_t TimeCounter )
{
  HAL_StatusTypeDef status = HAL_OK;

  if (Enter_RTC_Init_Mode() != HAL_OK)
  {//等待RTC写操作结束
    //返回0,表示退出RTC配置模式,开始更新RTC寄存器
    status = HAL_ERROR;
  }
  else
  {
    WRITE_REG(RTC->CNTH, (TimeCounter >> 16U));
		//写"RTC计数寄存器高位RTC_CNTH"
		//Set RTC COUNTER MSB word
    WRITE_REG(RTC->CNTL, (TimeCounter & RTC_CNTL_RTC_CNT));
		//写"RTC计数寄存器低位RTC_CNTL"
		//Set RTC COUNTER LSB word
    if (Exit_RTC_Init_Mode() != HAL_OK)
    {//等待RTC写操作结束
      status = HAL_ERROR;
    }
  }

  return status;
}

//函数功能:读"RTC闹钟寄存器"
uint32_t Read_RTC_Alarm_Counter(void)
{
  uint16_t high1 = 0U, low = 0U;

  high1 = READ_REG(RTC->ALRH & RTC_CNTH_RTC_CNT);
	//读"RTC闹钟寄存器高位RTC_ALRH"
  low   = READ_REG(RTC->ALRL & RTC_CNTL_RTC_CNT);
	//读"RTC闹钟寄存器低位RTC_ALRL"

  return (((uint32_t) high1 << 16U) | low);
}

//函数功能:将AlarmCounter写入"RTC闹钟寄存器"
HAL_StatusTypeDef Write_RTC_Alarm_Counter( uint32_t AlarmCounter)
{
  HAL_StatusTypeDef status = HAL_OK;

  /* Set Initialization mode */
  if (Enter_RTC_Init_Mode() != HAL_OK)
  {//等待RTC写操作结束
   //返回0,表示退出RTC配置模式,开始更新RTC寄存器
    status = HAL_ERROR;
  }
  else
  {
    WRITE_REG(RTC->ALRH, (AlarmCounter >> 16U));
		//写"RTC闹钟寄存器高位RTC_ALRH",Set RTC COUNTER MSB word
    WRITE_REG(RTC->ALRL, (AlarmCounter & RTC_ALRL_RTC_ALR));
		//写"RTC闹钟寄存器低位RTC_ALRL",Set RTC COUNTER LSB word

    /* Wait for synchro */
    if (Exit_RTC_Init_Mode() != HAL_OK)
    {//等待RTC写操作结束
      status = HAL_ERROR;
    }
  }

  return status;
}

//函数功能:返回0表示闰年
uint8_t Is_LeapYear(uint16_t nYear)
{
	uint16_t y;

	y=Century;//2023年9月26日
	y=y*100;//2023年9月26日
	nYear=y+nYear;//2023年9月26日

  if ((nYear % 4U) != 0U)
  {
    return 0U;
  }

  if ((nYear % 100U) != 0U)
  {
    return 1U;
  }

  if ((nYear % 400U) == 0U)
  {
    return 1U;
  }
  else
  {
    return 0U;
  }
}

//函数功能;读取星期几的值
uint8_t Read_RTC_WeekDay(uint32_t nYear, uint8_t nMonth, uint8_t nDay)
{
  uint32_t year = 0U, weekday = 0U;

  year = 2000U + nYear;

  if (nMonth < 3U)
  {
    /*D = { [(23 x month)/9] + day + 4 + year + [(year-1)/4] - [(year-1)/100] + [(year-1)/400] } mod 7*/
    weekday = (((23U * nMonth) / 9U) + nDay + 4U + year + ((year - 1U) / 4U) - ((year - 1U) / 100U) + ((year - 1U) / 400U)) % 7U;
  }
  else
  {
    /*D = { [(23 x month)/9] + day + 4 + year + [year/4] - [year/100] + [year/400] - 2 } mod 7*/
    weekday = (((23U * nMonth) / 9U) + nDay + 4U + year + (year / 4U) - (year / 100U) + (year / 400U) - 2U) % 7U;
  }

  return (uint8_t)weekday;
}

void Update_RTC_Date(RTC_DateTypeDef *update_RTCDate, uint32_t DayElapsed)
{
  uint32_t year = 0U, month = 0U, day = 0U;
  uint32_t loop = 0U;

  /* Get the current year*/
  year = update_RTCDate->Year;

  /* Get the current month and day */
  month = update_RTCDate->Month;
  day = update_RTCDate->Date;

  for (loop = 0U; loop < DayElapsed; loop++)
  {
    if ((month == 1U) || (month == 3U) || (month == 5U) || (month == 7U) || \
        (month == 8U) || (month == 10U) || (month == 12U))
    {
      if (day < 31U)
      {
        day++;
      }
      /* Date structure member: day = 31 */
      else
      {
        if (month != 12U)
        {
          month++;
          day = 1U;
        }
        /* Date structure member: day = 31 & month =12 */
        else
        {
          month = 1U;
          day = 1U;
          year++;
        }
      }
    }
    else if ((month == 4U) || (month == 6U) || (month == 9U) || (month == 11U))
    {
      if (day < 30U)
      {
        day++;
      }
      /* Date structure member: day = 30 */
      else
      {
        month++;
        day = 1U;
      }
    }
    else if (month == 2U)
    {
      if (day < 28U)
      {
        day++;
      }
      else if (day == 28U)
      {
        if (Is_LeapYear(year))//不闰年
        {//返回0表示闰年
          day++;
        }
        else //闰年
        {
          month++;
          day = 1U;
        }
      }
      else if (day == 29U)
      {
        month++;
        day = 1U;
      }
    }
  }

	if(year>=100)//2023年9月26日
	{
		Century++;
		year=year-100;
	}

  /* Update year */
  update_RTCDate->Year = year;

  /* Update day and month */
  update_RTCDate->Month = month;
  update_RTCDate->Date = day;

  /* Update day of the week */
  update_RTCDate->WeekDay = Read_RTC_WeekDay(year, month, day);
	//读取星期几的值
}

HAL_StatusTypeDef Read_RTC_Time(RTC_DateTypeDef *update_RTCDate, RTC_TimeTypeDef *sTime)
{
  uint32_t counter_time = 0U, counter_alarm = 0U, days_elapsed = 0U, hours = 0U;

  counter_time = Read_RTC_Time_Counter();//读"RTC计数寄存器",总秒数
  hours = counter_time / 3600U;//计算有多少小时
  sTime->Minutes  = (uint8_t)((counter_time % 3600U) / 60U);//计算分钟数值
  sTime->Seconds  = (uint8_t)((counter_time % 3600U) % 60U);//计算秒数值

  if (hours >= 24U)
  {
    days_elapsed = (hours / 24U);//计算"天"
    sTime->Hours = (hours % 24U);//计算今天的"小时时间"

    counter_alarm = Read_RTC_Alarm_Counter();
		//读"RTC闹钟寄存器"
		//Read Alarm counter in RTC registers

    /* Calculate remaining time to reach alarm (only if set and not yet expired)*/
    if ((counter_alarm != 0xFFFFFFFF) && (counter_alarm > counter_time))
    {//RTC_ALARM_RESETVALUE=0xFFFFFFFFU
      counter_alarm -= counter_time;//计算"距离报警时间的差值"
    }
    else
    {
      /* In case of counter_alarm < counter_time */
      /* Alarm expiration already occurred but alarm not deactivated */
      counter_alarm = 0xFFFFFFFF;
			//RTC_ALARM_RESETVALUE=0xFFFFFFFFU
    }

    /* Set updated time in decreasing counter by number of days elapsed */
    counter_time -= (days_elapsed * 24U * 3600U);//计算"今天的总秒数"

    /* Write time counter in RTC registers */
    if (Write_RTC_Time_Counter(counter_time) != HAL_OK)
    {//将"今天的总秒数"counter_time写入"RTC计数寄存器"
      return HAL_ERROR;
    }

    /* Set updated alarm to be set */
    if (counter_alarm != 0xFFFFFFFF)
    {//RTC_ALARM_RESETVALUE=0xFFFFFFFFU
      counter_alarm += counter_time;
			//报警时间 = "距离报警时间的差值" + "今天的总秒数"
      if (Write_RTC_Alarm_Counter(counter_alarm) != HAL_OK)
      {//将AlarmCounter写入"RTC闹钟寄存器"
        return HAL_ERROR;
      }
    }
    else
    {
      /* Alarm already occurred. Set it to reset values to avoid unexpected expiration */
      if (Write_RTC_Alarm_Counter(counter_alarm) != HAL_OK)
      {//将AlarmCounter写入"RTC闹钟寄存器"
        return HAL_ERROR;
      }
    }

    /* Update date */
    Update_RTC_Date(update_RTCDate, days_elapsed);
  }
  else
  {
    sTime->Hours = hours;
  }

  return HAL_OK;
}

HAL_StatusTypeDef Read_RTC_Date(RTC_DateTypeDef *update_RTCDate,RTC_DateTypeDef *sDate)
{
  RTC_TimeTypeDef stime = {0U};

  /* Call HAL_RTC_GetTime function to update date if counter higher than 24 hours */
  if (Read_RTC_Time(update_RTCDate, &stime) != HAL_OK)
  {
    return HAL_ERROR;
  }

  /* Fill the structure fields with the read parameters */
  sDate->WeekDay  = update_RTCDate->WeekDay;
  sDate->Year     = update_RTCDate->Year;
  sDate->Month    = update_RTCDate->Month;
  sDate->Date     = update_RTCDate->Date;

  return HAL_OK;
}

void RTC_Init(void)
{
	RTC_HandleTypeDef RTC_HandleStructureure;
  RCC_OscInitTypeDef        RCC_OscInit_Structureure;
  RCC_PeriphCLKInitTypeDef  PeriphClkInit_Structureure;
  
	Century=20;//世纪,21世纪用20表示

  RTC_HandleStructureure.Instance = RTC;                       //选择RTC
  RTC_HandleStructureure.Init.AsynchPrediv = RTC_AUTO_1_SECOND; //RTC一秒时基自动计算

//HAL_RTC_MspInit函数开始//
  RCC_OscInit_Structureure.OscillatorType =  RCC_OSCILLATORTYPE_LSI;

  RCC_OscInit_Structureure.LSIState = RCC_LSI_ON;
	HAL_RCC_OscConfig(&RCC_OscInit_Structureure);

  PeriphClkInit_Structureure.PeriphClockSelection = RCC_PERIPHCLK_RTC;
  PeriphClkInit_Structureure.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
	HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit_Structureure);

  __HAL_RCC_RTCAPB_CLK_ENABLE();
	//使能RTC APB外部设备时钟,Enable RTC peripheral Clocks
  __HAL_RCC_RTC_ENABLE();//使能RTC时钟,Enable RTC Clock

  HAL_NVIC_SetPriority(RTC_IRQn, 0x01, 0);
	//设置RTC中断优先级为0x01,0无意义
  NVIC_EnableIRQ(RTC_IRQn);//使能RTC中断

  __HAL_RTC_OVERFLOW_ENABLE_IT(&RTC_HandleStructureure, RTC_IT_OW);//使能溢出中断,Overflow interrupt
  __HAL_RTC_ALARM_ENABLE_IT(&RTC_HandleStructureure, RTC_IT_ALRA);//使能报警中断,Alarm interrupt
  __HAL_RTC_SECOND_ENABLE_IT(&RTC_HandleStructureure, RTC_IT_SEC);//使能秒中断,Second interrupt
//HAL_RTC_MspInit函数结束//

	HAL_RTC_Init(&RTC_HandleStructureure);//RTC初始化

/设置日期: 2023/9/27 星期三/
  RTC_DateStructureure.Year = 23;
  RTC_DateStructureure.Month =9;
  RTC_DateStructureure.Date = 27;
  RTC_DateStructureure.WeekDay = RTC_WEEKDAY_WEDNESDAY;
	HAL_RTC_SetDate(&RTC_HandleStructureure, &RTC_DateStructureure, RTC_FORMAT_BIN);
	//设置RTC日期

/设置时间: 09:00:00/
  RTC_TimeStructureure.Hours = 9;
  RTC_TimeStructureure.Minutes =00;
  RTC_TimeStructureure.Seconds = 00;
	HAL_RTC_SetTime(&RTC_HandleStructureure, &RTC_TimeStructureure, RTC_FORMAT_BIN);
	//设置RTC时间

/设置RTC闹钟,时间到09:01:00产生中断/
  RTC_AlarmStructureure.AlarmTime.Hours = 9;
  RTC_AlarmStructureure.AlarmTime.Minutes = 1;
  RTC_AlarmStructureure.AlarmTime.Seconds = 00;
	HAL_RTC_SetAlarm_IT(&RTC_HandleStructureure, &RTC_AlarmStructureure, RTC_FORMAT_BIN);
}

void RTC_Display(void)
{
	Read_RTC_Time(&RTC_DateStructureure,&RTC_TimeStructureure);
//	Read_RTC_Date(&RTC_DateStructureure,&RTC_DateStructureure);

//	RTC_HandleTypeDef RTC_HandleStructureure;

//	RTC_HandleStructureure.Instance = RTC;//选择RTC
//  printf("RTC_IT_SEC\r\n");
//  HAL_RTC_GetTime(&RTC_HandleStructureure, &RTC_TimeStructureure, RTC_FORMAT_BIN);//读取"RTC时间"
//  HAL_RTC_GetDate(&RTC_HandleStructureure, &RTC_DateStructureure, RTC_FORMAT_BIN);//读取"RTC日期"
  printf("%02d%02d-%02d-%02d %02d:%02d:%02d\r\n", Century,RTC_DateStructureure.Year,RTC_DateStructureure.Month,RTC_DateStructureure.Date,RTC_TimeStructureure.Hours, RTC_TimeStructureure.Minutes, RTC_TimeStructureure.Seconds);
	//显示时间格式为 : YY-MM-DD hh:mm:ss
	if(RTC_DateStructureure.WeekDay==RTC_WEEKDAY_SUNDAY) printf("Sunday\r\n");
	if(RTC_DateStructureure.WeekDay==RTC_WEEKDAY_MONDAY) printf("Monday\r\n");
	if(RTC_DateStructureure.WeekDay==RTC_WEEKDAY_TUESDAY) printf("Tuesday\r\n");
	if(RTC_DateStructureure.WeekDay==RTC_WEEKDAY_WEDNESDAY) printf("Wednesday\r\n");
	if(RTC_DateStructureure.WeekDay==RTC_WEEKDAY_THURSDAY) printf("Thursday\r\n");
	if(RTC_DateStructureure.WeekDay==RTC_WEEKDAY_FRIDAY) printf("Friday\r\n");
	if(RTC_DateStructureure.WeekDay==RTC_WEEKDAY_SATURDAY) printf("Saturday\r\n");
}

//函数功能;RTC中断服务函数
void RTC_IRQHandler(void)
{
	if (_HAL_RTC_SECOND_GET_FLAG(RTC,RTC_FLAG_SEC))
	{
		if (_HAL_RTC_SECOND_GET_FLAG(RTC, RTC_FLAG_OW))
		{//RTC计数器溢出中断
/HAL_RTCEx_RTCEventCallback函数开始/
      printf("%s","\r\nRTC Overflow!!!\r\n");
/HAL_RTCEx_RTCEventCallback函数结束/

      _HAL_RTC_OVERFLOW_CLEAR_FLAG(RTC, RTC_FLAG_OW);
			//清除溢出中断
		}
		else
		{//RTC产生秒中断
/HAL_RTCEx_RTCEventCallback函数开始/
        MCU_LED_Toggle();
/HAL_RTCEx_RTCEventCallback函数结束/
		}
		_HAL_RTC_SECOND_CLEAR_FLAG(RTC, RTC_FLAG_SEC);
	}

	if (_HAL_RTC_ALARM_GET_FLAG(RTC, RTC_FLAG_ALRAF) != (uint32_t)RESET)
	{//RTC产生报警中断
/HAL_RTC_AlarmAEventCallback函数开始/
		printf("%s","\r\nRTC Alarm!!!\r\n");
/HAL_RTC_AlarmAEventCallback函数结束/
		_HAL_RTC_ALARM_CLEAR_FLAG(RTC, RTC_FLAG_ALRAF);
		//Clear the Alarm interrupt pending bit
	}
}
#ifndef __RTC_H
#define __RTC_H

#include "py32f0xx_hal.h"

#define _HAL_RTC_SECOND_GET_FLAG(__INSTANCE__, __FLAG__)        (((((__INSTANCE__)->CRL) & (__FLAG__)) != RESET)? SET : RESET)
#define _HAL_RTC_OVERFLOW_CLEAR_FLAG(__INSTANCE__, __FLAG__)      ((__INSTANCE__)->CRL) = ~(__FLAG__)
#define _HAL_RTC_SECOND_CLEAR_FLAG(__INSTANCE__, __FLAG__)      ((__INSTANCE__)->CRL) = ~(__FLAG__)
#define _HAL_RTC_ALARM_GET_FLAG(__INSTANCE__, __FLAG__)        (((((__INSTANCE__)->CRL) & (__FLAG__)) != RESET)? SET : RESET)
#define _HAL_RTC_ALARM_CLEAR_FLAG(__INSTANCE__, __FLAG__)      ((__INSTANCE__)->CRL) = ~(__FLAG__)
//#define _HAL_RTC_ALARM_ENABLE_IT(__INSTANCE__, __INTERRUPT__)  SET_BIT((__INSTANCE__)->CRH, (__INTERRUPT__))

#define _HAL_RTC_WRITEPROTECTION_ENABLE(__INSTANCE__)          CLEAR_BIT((__INSTANCE__)->CRL, RTC_CRL_CNF)
//将"RTC控制寄存器RTC_CRL"中的CNF=1,进入RTC配置模式

#define _HAL_RTC_WRITEPROTECTION_DISABLE(__INSTANCE__)         SET_BIT((__INSTANCE__)->CRL, RTC_CRL_CNF)
//将"RTC控制寄存器RTC_CRL"中的CNF=0,退出配置模式,开始更新RTC寄存器
extern void RTC_Init(void);
extern void RTC_Display(void);

#endif /* __RTC_H */
#include "py32f0xx_hal.h"
#include "SystemClock.h"
#include "delay.h"
#include "LED.h"
#include "SystemClock.h"
#include "USART2.h"
#include "stdio.h"  //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()
#include "string.h" //使能strcpy(),strlen(),memset()
#include "RTC.h"

const char CPU_Reset_REG[]="\r\nCPU reset!\r\n";
int main(void)
{
	HSE_Config();
//	HAL_Init();//systick初始化
  delay_init();
	HAL_Delay(1000);

	USART2_Init(115200);
//PA0是为USART2_TX,PA1是USART2_RX
//中断优先级为0x01
//波特率为115200,数字为8位,停止位为1位,无奇偶校验,允许发送和接收数据,只允许接收中断,并使能串口
	printf("%s",CPU_Reset_REG);

	MCU_LED_Init();
	RTC_Init();

  while (1)
  {
		delay_ms(1000);
		RTC_Display();
  }
}

四、误差分析

误差: 每10分钟误差6秒。1%的误差,还行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1045024.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Docker版部署RocketMQ开启ACL验证

一、拉取镜像 docker pull apache/rocketmq:latest 二、准备挂载目录 mkdir /usr/local/rocketmq/data mkdir /usr/local/rocketmq/conf 三、运行 docker run \ -d \ -p 9876:9876 \ -v /usr/local/rocketmq/data/logs:/home/rocketmq/logs \ -v /usr/local/rocketmq/data…

数字化工厂系统能给企业品牌带来什么价值

数字化工厂管理系统是指通过数字技术和自动化系统来实现生产过程的数字化和智能化的工厂。它对品牌的价值主要体现在提高效率、降低成本、提升品质和增强灵活性四个方面。 首先&#xff0c;数字化工厂能够显著提高生产效率。传统工厂生产过程中存在很多手工操作和人为干预&…

pyspark.sql.dataframe.DataFrame 怎么转pandas DataFrame

pyspark.sql.dataframe.DataFrame 怎么转pandas DataFrame 要将 PySpark 的 pyspark.sql.dataframe.DataFrame 转换为 Pandas DataFrame&#xff0c;可以使用 toPandas() 方法。以下是一个示例&#xff1a; from pyspark.sql import SparkSession# 创建 SparkSession 对象 sp…

SAP移动端解决方案参考

企业在实现SAP移动化时遇到的一些挑战&#xff0c;如果我们利用自己开发团队来进行应用程序的开发&#xff0c;可能会陷入规划&#xff0c;开发&#xff0c;调试&#xff0c;测试的循环中&#xff0c;最后仍一无所获。那如果企业寻找第三方咨询公司进行开发的话&#xff0c;又担…

分享5款无广告免费的高效软件

​ 有句老话这样讲&#xff0c;工欲善其事&#xff0c;必先利其器&#xff0c;好的工具可以让你工作起来事半功倍。今日为大家推荐5款神器软件&#xff0c;提升你的工作效率。 1.数据恢复——EasyRecovery ​ EasyRecovery是一款数据恢复工具,它可以恢复从硬盘或移动存储设备…

多个短视频如何合并为一个长视频?原来靠它

随着电子设备的流行&#xff0c;越来越多的用户喜欢制作视频来记录生活&#xff0c;以便将美好回忆永久保存方便日后观看。通常&#xff0c;人们更倾向于将多个短视频合并为一个长视频&#xff0c;因为这样更容易存储。那么&#xff0c;怎样才能将多个短视频合并为一个长视频呢…

c++ 使用rapidjson对数据序列化和反序列化(vs2109)

RapidJSON是腾讯开源的一个高效的C JSON解析器及生成器&#xff0c;它是只有头文件的C库&#xff0c;综合性能是最好的。 1. 安装 在NuGet中为项目安装tencent.rapidjson 2. 引用头文件 #include <rapidjson/document.h> #include <rapidjson/memorystream.h> #…

成都瀚网科技有限公司:抖店精选联盟怎么用?

抖音精选联盟是抖音电商平台提供的一项服务&#xff0c;旨在为商家提供更多的推广机会和销售渠道。然而&#xff0c;很多人对于如何使用抖店精选联盟以及如何开通这项服务不太了解。本文将为您详细介绍抖店精选联盟的使用和激活流程。 第一节&#xff1a;如何使用抖店精选联盟 …

可以动态改变刻度背景色的车速仪表盘

最近做的项目的主页面需要用到一个仪表盘来动态显示车速&#xff0c;同时改变对应的背景色 仪表盘 开始是想着使用echarts&#xff0c;修修改改拿来用&#xff0c;但是人家客户有规定&#xff0c;必须搞个差不多的&#xff0c;那没办法&#xff0c;自 己动手搞个吧 截图如下&am…

【目标检测】——Gold-YOLO为啥能超过YOLOV8

华为 https://arxiv.org/pdf/2309.11331.pdf 文章的出发点&#xff1a;FPN中的信息传输问题 1. 简介 基于全局信息融合的概念&#xff0c;提出了一种新的收集和分发机制&#xff08;GD&#xff09;&#xff0c;用于在YOLO中进行有效的信息交换。通过全局融合多层特征并将全局信…

AIGC玩转卡通化技术实践

FaceChain写真开源项目插播&#xff1a; 最新 FaceChain支持多人合照写真、上百种单人写真风格&#xff0c;项目信息汇总&#xff1a;ModelScope 魔搭社区 。 github开源直达&#xff08;觉得有趣的点个star哈。&#xff09;&#xff1a;https://github.com/modelscope/…

护眼灯显色指数应达多少?眼科医生推荐灯光显色指数多少合适

台灯的显色指数是其非常重要的指标&#xff0c;它可以表示灯光照射到物体身上&#xff0c;物体颜色的真实程度&#xff0c;一般用平均显色指数Ra来表示&#xff0c;Ra值越高&#xff0c;灯光显色能力越强。常见的台灯显色指数最低要求一般是在Ra80以上即可&#xff0c;比较好的…

Spring进阶(AOP的应用)—— 动态代理AOP后controller层的private方法访问失效的问题

前言 动态代理&#xff0c;面向切面编程AOP&#xff08;Aspect Oriented Programming&#xff09;作为spring中的一个重点和难点&#xff0c;需要不断深入理解&#xff0c;并且在项目中学习如何灵活应用。 本篇博客介绍动态代理AOP在实际应用中遇到的private方法访问失效的问…

亚马逊电动玩具UL696的测试报告办理

在亚马逊平台销售的电子产品&#xff0c;要符合指定的标准&#xff0c;如果不合格很容易发生起火&#xff0c;爆炸等危及消费者生命财产的安全&#xff0c;因此很多客户因为缺少UL报告&#xff0c;导致产品被下架&#xff0c;销售权被移除等问题&#xff0c;也少不了同行之间的…

leetCode 63.不同路径II 动态规划 + 空间复杂度优化 一维dp

63. 不同路径 II - 力扣&#xff08;LeetCode&#xff09; 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish”&…

.NET Core nuget 组件的安装、更新、卸载

上面的 NuGet\ 是可以省略的。 更新 Update-Package xxx 卸载 Uninstall-Package xxx Uninstall-Package Newtonsoft.Json

400G QSFP-DD FR4 与 400G QSFP-DD FR8光模块:哪个更适合您的网络需求?

QSFP-DD 光模块随着光通信市场规模的不断增长已成为400G市场中客户需求量最高的产品。其中400G QSFP-DD FR4和400G QSFP-DD FR8光模块都是针对波分中距离传输&#xff08;2km&#xff09;的解决方案&#xff0c;它们之间有什么不同&#xff1f;应该如何选择应用&#xff1f;飞速…

SpringBoot 学习(二)配置

2. SpringBoot 配置 2.1 配置文件类型 配置文件用于修改 SpringBoot 的默认配置。 2.1.1 properties 文件 **properties ** 是属性文件后缀。 文件名&#xff1a;application.properties 只能保存键值对。 基础语法&#xff1a;keyvalue namewhy注入配置类 Component //…

Java基于SpringBoot的民宿管理系统,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 文章目录 开发环境&#xff1a;后端&#xff1a;前端&#xff1a;数据库&#xff1a; 系统架构&#xff1a…

Vue computed计算属性购物车实例

效果演示 对于computed的计算属性可以通过这个购物车例子来了解&#xff0c;笔者最近很是疲累&#xff0c;真的不想过多解释了&#xff0c;还请读者自行看代码研究。 参考代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"U…