STM32初学-外部RTC时钟芯片DS3231

news2024/11/25 7:10:58

        RTC(Real_Time Clock)即实时时钟,它是电子产品中不可或缺的东西。其最直接的作用就是时钟功能。细心的朋友可以发现,当我们的电脑或者手机没联网时,仍然可以正常显示日期与时钟,这就是RTC的功劳。

        RTC的运行无需网络连接,只需一个频率固定的振荡源和一个计数器,就能实现精准的计时。假如有一个振荡源,其每秒固定振荡1000次,那我们就可以用计数器对振荡进行计数,每振荡1000次,代表时间过去了1s,然后复位计数器并开始新的计数,同时,秒寄存器加1。如此循环,就能实现时钟的走时。

21ad4e7542c24f098061485fea6c9146.png

        在单片机的某些使用场景下,RTC时钟是不可或缺的,例如使用了文件系统,就必须启用RTC时钟,用于更新文件的时间。

        STM32内置了RTC时钟模块,只要配置好参数,就能启用RTC。RTC的时钟振荡源可以来自内部也可以来自外部。内部时钟源由HCLK经过分频得到,外部时钟源则由石英晶振提供。

973457b0641540aaa604c7e12f8583a6.png

         内部时钟源是由高频晶振分频得到,所以其精度计时不高,为了准确计时,一般采用外部时钟源。外部时钟源一般选用32.768KHz的石英晶振。这种参数的石英晶振一秒钟能振荡32768次,正好对应2^16。

b98f599ebe9bc4ec1b60da566ec7fa39.jpeg

        然而,即使采用了外部晶振的RTC,其精度仍然是有限的。因为晶振外置,线路上的寄生电容电感、温度都会影响晶振频率,短时间可能看不出误差,但是时间一长,其误差就大了。

        如果想进一步减小RTC的误差,则需要使用RTC时钟芯片。时钟芯片的优势在于其内部带有温度补偿功能,能通过检测环境温度来对晶振进行误差补偿,减小计时误差。且时钟芯片的年、月、日等时间数据单独存储在内部的RAM中,对单片机来说,只要通过串口读取特定寄存器地址的数据就能得到时间参数,而无需再去计算。现在流行的时钟芯片很多,如DS1302、 DS1307。但是这些芯片仍需要外置晶振才能工作,所以仍存在误差。

        所以一种在内部集成晶振的时钟芯片应运而生。DS3231就是这样一种时钟芯片。其精度最高可以达到±2ppm。实测6个月在常温下连续运行,误差不超过1分钟。

61f5e66528d448859fee62d6a3aed26b.png

     DS3231采用快速IIC通信进行数据传输,最高时钟频率400KHz。还带有闹钟,复位等功能。224a5ac113814714a5bbfbb80213de94.png

 DS3231有两种封装,引脚功能一样,16pin的封装只是多了八个空引脚。

如下是其应用电路。9fb591b6e7464754a250edaffc08b806.png

        可以看到该芯片有两个电源输入,一个是VCC,另一个是Vbat。VCC我们可以与单片机共用3.3V电源,Vbat则接到一颗纽扣电池的正极。当单片机供电断开后,DS3231仍能靠纽扣电池供电维持计时功能,但是无法进行IIC通信,也就是不能读取时间数据,恢复VCC供电后,IIC通信随之被唤醒。

        INT是个漏极开路的输出,如果想输出高电平则需要外接上拉电阻,该引脚可连接到单片机IO口作为单片机的外部中断源。

        32kHz是一个固定输出32KHz频率方波的IO口,也可做为单片机的计时源。同为开漏输出。

        RST是芯片的复位脚,如果没有特别需要,可以直接悬空。该芯片无需复位也能直接初始化。

软件部分                                                          

        这里我使用的是STM32F4,F1的芯片也是兼容的,只是需要把头文件改成F1的。IIC通信采用软件模拟。iic的软件模拟可参考文章(STM32单片机-IIC通信(软件模拟)),这里我就不详细讲IIC软件模拟的原理了。接下来我们看程序。

1,我使用的是PB8和PB9分别做为IIC的SCL与SDA。如果想使用其他IO,稍微修改下就行。

#include<stm32f4xx.h>

/********************软件模拟IIC*********************/
/*****************PB8=SCL,PB9=SDA*****************/


#define	DS3231_ADDRESS_Write	0xD0
#define	DS3231_ADDRESS_Read		0xD1


/**************DS3231内部寄存器地址***************/

#define DS3231_SEC        0x00  // 秒
#define DS3231_MIN        0x01  //分
#define DS3231_HOUR       0x02	//时
#define DS3231_WEEK       0x03	//周
#define DS3231_DATE       0x04	//日
#define DS3231_MONTH      0x05	//月
#define DS3231_YEAR       0x06	//年

#define DS3231_AL1SEC     0x07
#define DS3231_AL1MIN     0x08
#define DS3231_AL1HOUR    0x09
#define DS3231_AL1WDAY    0x0A

#define DS3231_AL2MIN     0x0B
#define DS3231_AL2HOUR    0x0C
#define DS3231_AL2WDAY    0x0D

#define DS3231_CONTROL          0x0E
#define DS3231_STATUS           0x0F
#define DS3231_AGING_OFFSET     0x0F
#define DS3231_TMP_High         0x11
#define DS3231_TMP_LOW          0x12

/******DS3231内部寄存器地址******/
/**************END**************/


#define Read_IIC_SDA GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_9)		//定义Read_IIC_SDA为PB11的输入值

#define IIC_SCL_H() GPIO_SetBits(GPIOB,GPIO_Pin_8)					//定义IIC_SCL_H()函数为将RES(PB10)置高电平	
#define IIC_SCL_L() GPIO_ResetBits(GPIOB,GPIO_Pin_8)				//定义IIC_SCL_L()函数为将RES(PB10)置低电平	

#define IIC_SDA_H() GPIO_SetBits(GPIOB,GPIO_Pin_9)					//定义IIC_SDA_H()函数为将RES(PB11)置高电平	
#define IIC_SDA_L() GPIO_ResetBits(GPIOB,GPIO_Pin_9)				//定义IIC_SDA_L()函数为将RES(PB11)置低电平	


 //最后读取到的时间数据将赋值到下面这几个变量
u8 RTC_Sec,RTC_Min,RTC_Hour,RTC_Week,RTC_Date,RTC_Month;   
u16 RTC_Year;


void IIC2_SoftInit(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8 | GPIO_Pin_9; 			//10--SCL   11--SDA;PB10 PB11
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;			//OD开漏
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;			//上拉
    GPIO_Init(GPIOB, &GPIO_InitStructure);
}

/******* 设置SDA为输出*******/

void SDA_OUT(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin= GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;	//推挽输出
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;			//OD开漏
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;			//上拉
    GPIO_Init(GPIOB, &GPIO_InitStructure);
}

/******* 设置SDA为输入*******/

void SDA_IN(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin= GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN;		//上拉输入
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;			//OD开漏
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;			//上拉
	GPIO_Init(GPIOB, &GPIO_InitStructure);
}
 
 
 
 void IIC_Start(void)			//起始信号
{
    SDA_OUT();			//把SDA作为输出,初始化为推挽输出
    IIC_SDA_H();		//SDA输出高电平
    IIC_SCL_H();		//SCL输出高电平
    Delay_us(2);
    IIC_SDA_L();		//SDA输出低点评
    Delay_us(2);
    IIC_SCL_L();		//SCL输出低电平
    Delay_us(2);
}

void IIC_Stop(void)		//停止信号
{
    IIC_SCL_H();		//SCL输出高电平
    IIC_SDA_L();		//SDA输出低点评
    Delay_us(2);
    IIC_SDA_H();		//SDA输出高电平
    Delay_us(2);
}


u8 IIC_Wait_Ask(void)		//等待应答信号
{
    u8 count;
    IIC_SDA_H();
	Delay_us(2);
	SDA_IN();
	Delay_us(2);
    IIC_SCL_H();
    Delay_us(2);
    while(Read_IIC_SDA)
    {
        count++;
        if(count>250)
        {
            IIC_Stop();				//如果长时间无应答,则认为从站故障,终止数据传输,并返回1
            return 1;
        }   
    }
    IIC_SCL_L();
    Delay_us(1);
    return 0;
}



void IIC_Ack(void)		//应答信号
{
    IIC_SCL_L();
    SDA_OUT();
    IIC_SDA_L();
    Delay_us(2);
    IIC_SCL_H();
    Delay_us(2);
    IIC_SCL_L();
}

void IIC_NAck(void)		//主机不产生应答信号NACK
{
    IIC_SCL_L();
    SDA_OUT();
    IIC_SDA_H();
    Delay_us(2);
    IIC_SCL_H();
    Delay_us(2);
    IIC_SCL_L();
}



void IIC_WriteByte(u8 data)			//写1Byte数据,每个数据都是以写1Byte作为基本单位
{
    u8 i;
    SDA_OUT();						//SDA切换到数据输出模式
	Delay_us(2);
    for(i=0;i<8;i++)				//循环传输1Byte数据,即8bit
    {
        IIC_SCL_L();				//SCL置低电平,为下个Bit数据做准备
		Delay_us(2);
        if(data & 0x80)     		//MSB,如果date的第八位为1
            IIC_SDA_H();			//则SDA置高
        else
            IIC_SDA_L();			//否则置低
		Delay_us(1);
        IIC_SCL_H();				//SCL拉高,产生一个时钟信号,从机读取SDA状态
        Delay_us(2);				//延时,丛机在这段时间读取SDA状态
        IIC_SCL_L();				//延时后拉低SCL,为下个Bit数据做准备
        data<<=1;					//date左移1位,下一bit变成第八位
    }
}

//读1个字节,ack=1时,发送ACK,ack=0,发送nACK   



u8 IIC_Read_Byte(const unsigned char ack)
{
	u8 i,receive=0;
	SDA_IN();			//SDA设置为输入
	Delay_us(2);
    for(i=0;i<8;i++ )
	{
		IIC_SCL_L(); 
		Delay_us(2);
		IIC_SCL_H();
        receive<<=1;
		Delay_us(2);
        if(Read_IIC_SDA)
			receive++;   
		Delay_us(2); 
    }					 
    if (!ack)
        IIC_NAck();		//发送nACK
    else
        IIC_Ack();		 //发送ACK   
    return receive;
}


void IIC_DS3231_ByteWrite(u8 WriteAddr,u8 date)
{
	IIC_Start();		//起始信号
	IIC_WriteByte(DS3231_ADDRESS_Write);		//DS3231设备地址,写
	IIC_Wait_Ask();				//等待应答
	IIC_WriteByte(WriteAddr);	//寄存器地址
	IIC_Wait_Ask();				//等待应答
	IIC_WriteByte(date);		//写入数据
	IIC_Wait_Ask();				//等待应答
	IIC_Stop();					//结束信号
}

u8 IIC_DS3231_ByteRead(u8 ReadAddr)
{
	u8 data = 0;
	IIC_Start();										//产生起始位
	IIC_WriteByte(DS3231_ADDRESS_Write); 				//发送从机地址(写模式D0)
	IIC_Wait_Ask();				//等待应答
	IIC_WriteByte(ReadAddr);							//发送寄存器地址
	IIC_Wait_Ask();				//等待应答
	IIC_Start();										//重复起始信号
	IIC_WriteByte(DS3231_ADDRESS_Read);		//发送从机地址(读模式)
	IIC_Wait_Ask();							//等待应答
	data = IIC_Read_Byte(0);				//读取数据,参数设为0 --- NACK
	IIC_Stop();
	return data;
}

void IIC_DS3231_ReadAll(void)		//读取所有时间数据并转换
{
	u8 Data_Sec,Data_Min,Data_Hour,Data_Week,Data_Date,Data_Month,Data_Year;
	u8 Low,High;
	
	Data_Sec= IIC_DS3231_ByteRead(DS3231_SEC);			//读取数据秒
	Data_Min = IIC_DS3231_ByteRead(DS3231_MIN);			//读取数据分
	Data_Hour = IIC_DS3231_ByteRead(DS3231_HOUR);		//读取数据时
	Data_Week = IIC_DS3231_ByteRead(DS3231_WEEK);		//读取数据周
	Data_Date = IIC_DS3231_ByteRead(DS3231_DATE);			//读取数据日
	Data_Month = IIC_DS3231_ByteRead(DS3231_MONTH);		//读取数据月
	Data_Year = IIC_DS3231_ByteRead(DS3231_YEAR);		//读取数据年
	
	Low=Data_Sec&0x0f;						//取低四位
	High=(( Data_Sec& 0xf0) >> 4);			//取高四位
	RTC_Sec=High*10+Low;					//转换秒(高四位*10+低四位)
	
	Low=Data_Min&0x0f;
	High=(( Data_Min& 0xf0) >> 4);
	RTC_Min=High*10+Low;					//转换分
	
	Low=Data_Hour&0x0f;
	High=(( Data_Hour& 0x30) >> 4);
	RTC_Hour=High*10+Low;					//转换时(高两位*10+低四位)

	RTC_Week=Data_Week;						//转换周(不需要转换)
	
	Low=Data_Date&0x0f;
	High=(( Data_Date& 0xf0) >> 4);
	RTC_Date=High*10+Low;					//转换日
	
	Low=Data_Month&0x0f;
	High=(( Data_Month& 0x10) >> 4);
	RTC_Month=High*10+Low;					//转换月
	
	Low=Data_Year&0x0f;
	High=(( Data_Year& 0xf0) >> 4);
	RTC_Year=((Data_Month>>7)+20)*100+High*10+Low;	//转换年(世纪*100+高四位*10+低四位)		
}

void IIC_DS3231_WriteAll(u16 Year,u8 Month,u8 Date,u8 Week,u8 Hour,u8 Min,u8 Sec)
{	
	u8 Sec_Date,Min_Date,Hour_Date,Week_Date,Date_Date,Month_Date,Year_Date;
	u8 H_Bit,L_Bit;
	
	H_Bit=(Sec/10)<<4;			//取高四位
	L_Bit=Sec%10;				//取低四位
	Sec_Date=H_Bit|L_Bit;		//合并成八位
	
	H_Bit=(Min/10)<<4;
	L_Bit=Min%10;
	Min_Date=H_Bit|L_Bit;
	
	H_Bit=Hour/10;
	L_Bit=Hour%10;
	Hour_Date=(H_Bit<<4)|L_Bit;
		
	Week_Date=Week;
	
	H_Bit=Date/10;
	L_Bit=Date%10;
	Date_Date=(H_Bit<<4)|L_Bit;
	
	if(Year/100==20)
	{	
		H_Bit=Month/10;
		L_Bit=Month%10;
		Month_Date=(H_Bit<<4)|L_Bit;
		
		H_Bit=(Year-2000)/10;
		L_Bit=(Year-2000)%10;
		Year_Date=(H_Bit<<4)|L_Bit;
		
	}
	else
	{
		H_Bit=Month/10+8;		//05h第8位如果是1,则为22世纪
		L_Bit=Month%10;
		Month_Date=(H_Bit<<4)|L_Bit;
		
		H_Bit=(Year-2100)/10;
		L_Bit=(Year-2100)%10;
		Year_Date=(H_Bit<<4)|L_Bit;
	}
	IIC_DS3231_ByteWrite(DS3231_YEAR,Year_Date);	
	IIC_DS3231_ByteWrite(DS3231_MONTH,Month_Date);
	IIC_DS3231_ByteWrite(DS3231_DATE,Date_Date);
	IIC_DS3231_ByteWrite(DS3231_WEEK,Week_Date);
	IIC_DS3231_ByteWrite(DS3231_HOUR,Hour_Date);
	IIC_DS3231_ByteWrite(DS3231_MIN,Min_Date);
	IIC_DS3231_ByteWrite(DS3231_SEC,Sec_Date);
	
}

void DS3231_Init(void)		//DS3231初始化
{
	IIC_DS3231_ByteWrite(0x0E,0x40);		//使能1Hz方波,使能振荡器	
	IIC_DS3231_ByteWrite(0x0F,0x00);		//启动振荡器
	Delay_ms(100);    //延时等待完全起振
}

 延时函数,IIC软件模拟需要用到延时函数,这里我采用的是滴答定时器进行延时,需要注意,F1 与F4的延时函数不能共用,因为主频不一样。

/****************************************************************
 * Function:    Delay_us
 * Description: Microsecond delay.
 * Input:       nus
 * Output:
 * Return:
*****************************************************************/
void Delay_us(u16 nus)
{ 
  //Delay_Init();
	u32 temp;
    SysTick->LOAD = SystemCoreClock / 8000000 * nus;  /* Time load (SysTick-> LOAD is 24bit) */
    SysTick->VAL = 0x000000;                          /* Empty counter */
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;         /* Start the countdown */

    do
    {
		temp = SysTick->CTRL;
    }
    while(temp&0x01 && !(temp&(1<<16)));        /* Wait time is reached */

    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;  /* Close Counter */
    SysTick->VAL = 0x000000;                    /* Empty counter */
}

/****************************************************************
 * Function:    Delay_ms
 * Description: Millisecond delay.
 * Input:       nms
 * Output:
 * Return:
*****************************************************************/
void Delay_ms(u16 nms)
{
	u32 temp;
	while(nms > 500)	//24位定时器最大计数值2^24=16777216,计时器时钟频率初始化为21MHz,最大计时时间为16777216/21000000=0.798s=798ms,所以需要多次复位
	{
		
		SysTick->LOAD = SystemCoreClock / 8000 * 500; /* Time load (SysTick-> LOAD is 24bit) */
		SysTick->VAL = 0x000000;                      /* Empty counter */
		SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;     /* Start the countdown */

		do
		{
			temp = SysTick->CTRL;
		}
		while(temp&0x01 && !(temp&(1<<16)));        /* Wait time is reached */

		SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;  /* Close Counter */
		SysTick->VAL = 0x000000;                    /* Empty counter */
    
		nms -= 500;
	}
  
	SysTick->LOAD = SystemCoreClock / 8000 * nms; /* Time load (SysTick-> LOAD is 24bit) */
	SysTick->VAL = 0x000000;                      /* Empty counter */
	SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;     /* Start the countdown */

	do
	{
		temp = SysTick->CTRL;
	}
	while(temp&0x01 && !(temp&(1<<16)));        /* Wait time is reached */

	SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;  /* Close Counter */
	SysTick->VAL = 0x000000;                    /* Empty counter */
}

嘀嗒定时器初始化:在启用延时函数前必须对定时器进行初始化,配置对应的参数。这里我用主频HCLK的八分频做为其定时频率,即21MHz。也就是一秒钟对应定时器的21000000。

void Delay_Init(void)			//嘀嗒计时器初始化,用于Delay函数
{
    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);		//计数器频率:168M/8=21MHZ
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;  				/* Disability SysTick counter */
}

main函数:初始化延时函数,初始化DS3231 ,讲时间写入DS3231,讲时间读取出来

#include<stm32f4xx.h>    //F4头文件

void main(void)
{
    Delay_Init();                //嘀嗒定时器初始化,必须初始化,延时依靠嘀嗒计时器

    DS3231_Init();		//DS3231初始化,唤醒DS3231,并启动振荡器
    IIC_DS3231_WriteAll(2023,10,1,1,12,00,00);   //设置时间函数,实例为2023年10月1日12:00:00
    IIC_DS3231_ReadAll();        //读取DS3231所有时间数据
}

最终读取转换后的时钟数据分别为这些变量:u8 RTC_Sec,RTC_Min,RTC_Hour,RTC_Week,RTC_Date,RTC_Month;   
u16 RTC_Year;

可以通过串口打印,或者其他方式显示出当前时间。

这里我将时间显示到LCD屏幕上。

如果觉得本文有用,就点个赞吧~

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

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

相关文章

python创建exe文件

1、搭建环境 pip install pyinstaller 2、准备测试代码 exe_test.py import timeprint("hello") print("hello") print("hello") print("hello")time.sleep(5) 注&#xff1a;添加sleep以便在执行exe文件的时候能看到结果 3、生…

在Windows操作系统上安装PostgreSQL数据库

在Windows操作系统上安装PostgreSQL数据库 一、在Windows操作系统上安装PostgreSQL数据库 一、在Windows操作系统上安装PostgreSQL数据库 点击 PostgreSQL可跳转至PostGreSQL的官方下载地址。 &#xff08;1&#xff09; &#xff08;2&#xff09;选择安装的目录&#xff…

入门人工智能 —— 使用 Python 进行文件读写,并完成日志记录功能(4)

入门人工智能 —— 使用 Python 进行文件读写&#xff08;4&#xff09; 入门人工智能 —— 使用 Python 进行文件读写打开文件读取文件内容读取整个文件逐行读取文件内容读取所有行并存储为列表 写入文件内容关闭文件 日志记录功能核心代码&#xff1a;完整代码&#xff1a;运…

小工具——筛选图像小工具

最近在公司手动筛图片&#xff0c;需要将某些含有检测目标的图像手动筛选出来用于做新模型的测试。我最开始是两个文件夹&#xff0c;来回复制粘贴&#xff0c;后来感觉这种效率太低了&#xff0c;就随手写了一个图像筛查小工具。代码如下&#xff1a; import sys from PyQt5.…

图论-图的深度优先遍历-Java

回顾力扣144/94//145/102/589/590/429&#xff0c;熟练掌握递归和非递归写法。 图论不强调非递归。 使用邻接表 1个连通分量 Graph.java package Chapt02_DFS; import java.io.File; import java.io.IOException; import java.util.TreeSet; import java.util.Scanner;///…

66.C++多态与虚函数

目录 1.什么是多态 2.多态的分类 3.对象转型 3.1 向上转型&#xff1a; 3.2 向下转型&#xff1a; 4.虚函数 1.什么是多态 生活中的多态&#xff0c;是指的客观的事物在人脑中的主观体现。例如&#xff0c;在路上看到⼀只哈士奇&#xff0c;你可以看做是哈士奇&#xf…

Unity实战(10):如何将某个相机的画面做成贴图(RenderTexture)

目录 前言 一、创建物体、材质与相机 二、将RenderTexture赋给材质 2.1 修改rt1的一些属性 2.2 将rtMat1材质的shader改为Unlit/Texture&#xff0c;并将rt1赋给这个材质 三、效果呈现 前言 本文记录如何将某个相机的画面做成贴图&#xff0c;即游戏某些场景中小地图做法…

时序预测 | MATLAB实现ICEEMDAN-iMPA-BiLSTM时间序列预测

时序预测 | MATLAB实现ICEEMDAN-iMPA-BiLSTM时间序列预测 目录 时序预测 | MATLAB实现ICEEMDAN-iMPA-BiLSTM时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 ICEEMDAN-iMPA-BiLSTM功率/风速预测 基于改进的自适应经验模态分解改进海洋捕食者算法双向长短期记忆…

基于SSM的农产品推广应用网站

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用Vue技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

华为云云耀云服务器L实例评测|centos系统搭建git私服

搭建git私服 前言一、云服务器二、服务器安装git三、服务器git配置1.创建文件用于存放公钥2.设置文件权限3.配置本地公钥 四、服务器部署git仓库四、git仓库到本地总结 前言 之前一直想搭建一个属于自己的git私服&#xff0c;然后没赶上厂商的活动&#xff0c;这次正好赶上华为…

学习笔记——树上哈希

普通子树哈希 树上的很多东西都是转化成链上问题的&#xff0c;比如树上哈希 树上哈希&#xff0c;主要是用于树的同构这个东西上的 什么是树的同构&#xff1f; 如图&#xff0c;不考虑节点编号&#xff0c;三棵树是同构的 将树转化成链&#xff0c;一般有两种方式&#xf…

mongodb安装全过程详解

mongodb安装全过程详解 安装mongodb环境安装mongodb shell 安装mongodb环境 进入mongodb官网下载社区版服务器 点击跳转下载地址 选择适应自己系统的版本&#xff0c;然后下载 下图为下载后的文件&#xff0c;双击进行安装 需要注意的两个点 ①选择完整安装 ②不下载mongo…

C语言——指针进阶(二)

目录 七.函数指针数组 八.指向函数指针数组的指针 九.回调函数 结尾 七.函数指针数组 说白了函数指针数组就是函数指针名字后面添加[ ]&#xff0c;二者结合成为数组。 那么这个函数指针数组到底有什么用呢&#xff1f;先不用着急&#xff0c;下面用一个计算器功能代码为大…

【Linux】——网络基础:http协议

目录 前言 应用层 认识协议 协议的概念 传输结构化数据 序列化和反序列化 网络版本计算器 服务器端Server 客户端Client 协议定制 其它 运行效果 HTTP协议 HTTP的简介 认识URL urlencode和urldecode HTTP协议格式 HTTP请求 HTTP响应 HTTP的方法 GET和POST…

时序分解 | MATLAB实现基于LMD局部均值分解的信号分解分量可视化

时序分解 | MATLAB实现基于LMD局部均值分解的信号分解分量可视化 目录 时序分解 | MATLAB实现基于LMD局部均值分解的信号分解分量可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 LMD局部均值分解 直接替换Excel即可运行包含频谱图相关系数图 Matlab语言 1.算法新颖…

UMA 2 - Unity Multipurpose Avatar☀️七.UMA API介绍

文章目录 🟥 UMA Data DNA参数引用位置🟥 UMA API介绍🟥 UMA Data DNA参数引用位置 我们想通过代码去控制如图所示参数,达到捏脸的目的.下面就是可以控制的代码: _dna["headSize"].Set(1); _avatar.BuildCharacter();我们观察发现操控代码类似Material去设置…

01_瑞萨GUI(LVGL)移植实战教程之软件和硬件准备

本系列教程配套出有视频教程&#xff0c;观看地址&#xff1a;https://www.bilibili.com/video/BV1gV4y1e7Sg 1. 软件和硬件准备 1.1 本节要点 本节学习如何搭建开发环境&#xff0c;硬件接线&#xff0c;为我们后续的学习做好基础必要的准备。 1.2资料准备 本文档所有用到…

flink 端到端一致性

背景 我们经常会混淆flink提供的状态一致性保证和数据端到端一致性保证的关系&#xff0c;总以为他们表达的是同一个意思&#xff0c;事实上&#xff0c;他们不是一个含义&#xff0c;flink只能保证其维护的内部状态的一致性&#xff0c;而数据端到端的一致性需要数据源&#…

Python下载、安装及如何配置Pycharm(Windows 11)详细教程

本文介绍在Windows 11系统Python的下载、安装及配置Pycharm 一、下载 官网地址&#xff1a;https://www.python.org/downloads/windows/ 1、选择Python 3.10.5版本下载 二、安装 1、选择自定义安装 2、全部默认勾选&#xff0c;点击Next 3、自定义安装路径 建议勾选inst…

il2cpp分析-gobal-metadata.dat解密

gobal-metadata.dat解密 工具:010Editor,IDA 7.5,Jadx,VS Code 样本Last Island of Survival_6.3_Apkpure.xapk 分析Il2cpp文件 打开ida,把libil2cpp拖到ida中按快捷键ShiftF12等待字符串分析完后,搜索global-metadata.dat 双击搜索出来的结果 点击aGlobalMetadata 然后…