STM32速成笔记—RTC

news2024/12/23 13:26:16

文章目录

  • 一、RTC简介
  • 二、STM32的RTC
    • 2.1 主要特性
    • 2.2 RTC框图介绍
  • 三、访问后备区域步骤
  • 四、RTC配置步骤
  • 五、RTC程序配置
    • 5.1 RTC结构体定义
    • 5.2 RTC初始化函数
    • 5.3 设置年月日,时分秒
    • 5.4 判断闰年函数
    • 5.5 获取当前年月日,时分秒
    • 5.6 获取星期几
    • 5.7 中断服务函数
  • 六、拓展

一、RTC简介

RTC(Real Time Clock)实时时钟,它是一个独立的定时器。RTC模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。

RTC模块和时钟配置都是在后备区域,无论单片机处于何种状态,只要保证后备区正常供电,RTC就会一直工作。

二、STM32的RTC

2.1 主要特性

  • 可编程的预分频系数:分频系数最高为2^20
  • 32位的可编程计数器,可用于较长时间段的测量
  • 可以选择以下三种RTC的时钟源
    ─ HSE时钟除以128
    ─ LSE振荡器时钟
    ─ LSI振荡器时钟
  • 3个专门的可屏蔽中断
    ─ 闹钟中断,用来产生一个软件可编程的闹钟中断
    ─ 秒中断,用来产生一个可编程的周期性中断信号(最长可达1秒)
    ─ 溢出中断,指示内部可编程计数器溢出并回转为0的状态

2.2 RTC框图介绍

RTC框图

  • RTCCLK通常选择低功耗32.768kHz外部晶振(LSE)
  • RTC预分频器通常设置为32768,LES时钟经过RTC预分频器,输入频率变为1Hz,也就是1秒
  • RTC_CNT输入时钟为1Hz时,1s加1次
  • RTC_ALR是用来做闹钟的,RTC_CNT的值会与RTC_ALR的值进行比较,二者相等时,会产生闹钟中断

三、访问后备区域步骤

STM32系统复位之后,对后备寄存器和RTC的访问被禁止,这是为了防止对后备区域(BKP)的意外写操作。执行以下操作,可以访问后备区域寄存器

  • 设置寄存器RCC_APB1ENR的PWREN和BKPEN位,使能电源和后备接口时钟
  • 设置寄存器PWR_CR的DBP位,使能对后备寄存器和RTC的访问

完成上面的设置之后,就可以操作后备寄存器。第一次通过APB1总线访问RTC时,需要等待APB1和RTC同步,确保读取出来的RTC的寄存器值是正确的。如果同步之后,一直没有关闭APB1和RTC外设接口,就不需要再同步了。

如果内核需要对RTC寄存器写入数据,在内核发送指令后,RTC会在3个RTCCLK时钟之后,开始写入数据。每次写入时,必须要检查RTC关闭操作标志位RTOFF是否置1来判断是否写操作完成。

四、RTC配置步骤

  • 使能电源时钟和后备域时钟,开启RTC后备寄存器写访问
  • 复位备份区域,开启外部低速振荡器(LSE)
  • 选择RTC时钟,并使能
  • 设置RTC的分频系数,配置RTC时钟
  • 更新配置,设置RTC中断分组
  • 编写RTC中断服务函数

五、RTC程序配置

5.1 RTC结构体定义

// RTC结构体
typedef struct 
{
	// 时分秒
	u8 hour;
	u8 min;
	u8 sec;
	
	// 年月日周
	u16 w_year;
	u8  w_month;
	u8  w_date;
	u8  week;		 
}_calendar;

5.2 RTC初始化函数

/*
 *==============================================================================
 *函数名称:RTC_Init
 *函数功能:初始化RTC
 *输入参数:无
 *返回值:0:成功;1:失败
 *备  注:无
 *==============================================================================
 */
u8 RTC_Init (void)
{
	u8 temp=0;   // 超时监控变量
	// 结构体定义
	NVIC_InitTypeDef NVIC_InitStructure;
	
	// 使能PWR和BKP外设时钟  
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); 
	PWR_BackupAccessCmd(ENABLE);   // 使能后备寄存器访问
	
	// 检测是否是第一次配置RTC
	// 配置时会想RTC寄存器写入0xA0A0,如果读出的数据不是0xA0A0,认为是第一次配置RTC
	if (BKP_ReadBackupRegister(BKP_DR1) != 0xA0A0)
	{ 			
		BKP_DeInit();   // 复位备份区域 	
		RCC_LSEConfig(RCC_LSE_ON);   // 设置外部低速晶振(LSE),使用外设低速晶振
		
		// 等待低速晶振就绪
		while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET&&temp<250)
		{
			temp++;
			delay_ms(10);
		}
		// 初始化时钟失败,晶振有问题	
		if(temp>=250)
		{
			return 1;
		}			
		
		RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);   // 设置RTC时钟(RTCCLK),选择LSE作为RTC时钟    
		RCC_RTCCLKCmd(ENABLE);   // 使能RTC时钟  
		RTC_WaitForLastTask();   // 等待最近一次对RTC寄存器的写操作完成
		
		RTC_WaitForSynchro();   // 等待RTC寄存器同步
		RTC_ITConfig(RTC_IT_SEC, ENABLE);   // 使能RTC秒中断
		RTC_WaitForLastTask();   // 等待最近一次对RTC寄存器的写操作完成
		
		RTC_EnterConfigMode();   // 允许配置	
		RTC_SetPrescaler(32767);   // 设置RTC预分频的值
		RTC_WaitForLastTask();   // 等待最近一次对RTC寄存器的写操作完成
		
		RTC_Set_Date(2023,6,26,11,15,00);   // 设置初始时间	
		RTC_ExitConfigMode();   // 退出配置模式  
		BKP_WriteBackupRegister(BKP_DR1, 0XA0A0);   // 向指定的后备寄存器中写入用户程序数据
	}
	// 系统继续计时
	else
	{
		RTC_WaitForSynchro();   // 等待最近一次对RTC寄存器的写操作完成
		RTC_ITConfig(RTC_IT_SEC, ENABLE);   // 使能RTC秒中断
		RTC_WaitForLastTask();   // 等待最近一次对RTC寄存器的写操作完成
	}
	
  // 配置RTC中断分组
	NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;   // RTC全局中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;   // 先占优先级1位,从优先级3位
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;   // 先占优先级0位,从优先级4位
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;   // 使能该通道中断
	NVIC_Init(&NVIC_InitStructure);   // 根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
	
	RTC_Get_CurDate();   // 获取当前时间	
	return 0;   // 配置成功
}

初始化函数使用时,可以用while等待初始化成功,但是需要增加一个超时检测,这里简单给出一个写法,如果1s内,RTC没有初始化成功,直接跳过

	u32 tempVar = 0;   // 初始化RTC时的超时计数变量
	
	while (RTC_Init() && tempVar < 100)   // RTC初始化
	{
		delay_ms (10);
		// 10ms自加1
		tempVar = tempVar + 1;
	}

5.3 设置年月日,时分秒

/*
 *==============================================================================
 *函数名称:RTC_Set_Date
 *函数功能:设置RTC的年月日,时分秒
 *输入参数:无
 *返回值:0:成功;1:失败
 *备  注:时间范围为1970年到2099年,可修改
 *==============================================================================
 */
u8 RTC_Set_Date (u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec)
{
	u16 t;
	u32 seccount=0;
	
	// 判断是否为合法年份
	if(syear < 1970 || syear > 2099)
	{
		return 1;
	}
	
	for(t = 1970;t < syear;t ++)   // 把所有年份的秒钟相加
	{
		// 闰年的秒钟数
		if(Is_Leap_Year(t))
		{
			seccount += 31622400;
		}
		// 平年的秒钟数
		else
		{
			seccount += 31536000;
		}
	}
	
	smon -= 1;
	
	for(t = 0;t < smon;t ++)   // 把前面月份的秒钟数相加
	{
		seccount += (u32)mon_table[t] * 86400;   // 月份秒钟数相加
		// 闰年2月份增加一天的秒钟数
		if(Is_Leap_Year(syear) && t == 1)
		{
			seccount += 86400;
		}			
	}
	seccount += (u32)(sday-1) * 86400;   // 把前面日期的秒钟数相加 
	
	seccount += (u32)hour * 3600;   // 小时秒钟数
	
	seccount += (u32)min*60;   // 分钟秒钟数
	
	seccount += sec;   // 最后的秒钟加上去

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);   // 使能PWR和BKP外设时钟  
	PWR_BackupAccessCmd(ENABLE);   // 使能RTC和后备寄存器访问
	
	RTC_SetCounter(seccount);   // 设置RTC计数器的值

	RTC_WaitForLastTask();   // 等待最近一次对RTC寄存器的写操作完成  	
	return 0;	    
}

5.4 判断闰年函数

/*
 *==============================================================================
 *函数名称:Is_Leap_Year
 *函数功能:判断输入年份是否为闰年
 *输入参数:无
 *返回值:0:不是闰年;1:是闰年
 *备  注:四年一闰;百年不闰,四百年再闰
 *==============================================================================
 */
u8 Is_Leap_Year (u16 year)
{
	// 是否能被4整除
	if(year % 4 == 0)
	{
		// 是否能被100整除
		if(year % 100 == 0) 
		{
			// 如果以00结尾,还要能被400整除 
			if(year % 400 == 0)
			{
				return 1;
			}
			// 是100的倍数,但是不是400的倍数
			else
			{
				return 0;
			}				
		}
		// 是4的倍数,不是100的倍数
		else
		{
			return 1; 
		}			
	}
	// 不是4的倍数
	else
	{
		return 0;	
	}
}

5.5 获取当前年月日,时分秒

/*
 *==============================================================================
 *函数名称:RTC_Get_CurDate
 *函数功能:获取当前年月日,时分秒
 *输入参数:无
 *返回值:0:成功;1:失败
 *备  注:无
 *==============================================================================
 */
u8 RTC_Get_CurDate (void)
{
	// 存储上一次的总天数值,用来监测时间变化是否超过一天
	static u16 daycnt = 0;
	u32 timecount = 0; 
	// 临时计算变量
	u32 temp = 0;
	u16 temp1 = 0;
	
	timecount = RTC_GetCounter();   // 获取当前总秒数
	
 	temp = timecount / 86400;   // 得到总天数
	
	// 超过一天了
	if(daycnt != temp)
	{
		daycnt = temp;   // 更新当前总天数值
		
		temp1 = 1970;   // 从1970年开始,计算当前年份
		while(temp >= 365)
		{
			// 是闰年
			if(Is_Leap_Year(temp1))
			{
				// 已经过完了366天
				if(temp >= 366)
				{
					temp -= 366;   // 闰年的天数
				}
				// 刚过完365天,当前是第366天
				else
				{
					temp1 ++;   // 年份加1
					break;
				}
			}
			// 是平年
			else
			{
				temp -= 365;   // 平年的天数
			}
			temp1 ++;   // 年份加1
		}
		
		calendar.w_year = temp1;   // 得到年份
		temp1=0;   // 清零临时计算变量
		
		// 此时temp为小于一年的天数,开始计算当前月份
		while(temp >= 28)   // 超过了一个月
		{
			// 当年是闰年的2月份
			if(Is_Leap_Year(calendar.w_year) && temp1 == 1)
			{
				// 是闰年的二月份且天数大于等于29天
				if(temp >= 29)
				{
					temp -= 29;   // 闰年的2月份天数
				}
				// 是闰年的2月份,天数小于闰年2月份天数
				else
				{
					break;
				}
			}
			// 是平年
			else 
			{
				// 查询月份天数表
				if(temp >= mon_table[temp1])
				{
					// 超过当月天数,减去
					temp -= mon_table[temp1];
				}
				else
				{
					break;
				}
			}
			temp1 ++;   // 月份加1
		}
		// 加1是因为月份表索引是0~11
		calendar.w_month = temp1 + 1;   // 得到月份
		// 当前日期为已经过去的天数加1
		calendar.w_date = temp + 1;   // 得到日期 
	}
	temp = timecount % 86400;   // 得到秒钟数   	   
	calendar.hour = temp / 3600;   // 小时
	calendar.min = (temp % 3600) / 60;   // 分钟	
	calendar.sec = (temp % 3600) % 60;   // 秒钟
	calendar.week = RTC_Get_Week(calendar.w_year,calendar.w_month,calendar.w_date);   // 获取星期
	
	return 0;
}

5.6 获取星期几

该函数设计是根据蔡勒公式设计,程序如下

/*
 *==============================================================================
 *函数名称:RTC_Get_Week
 *函数功能:获取当前是星期几
 *输入参数:year:当前年;month:当前月;day:当前日
 *返回值:星期几
 *备  注:无
 *==============================================================================
 */
u8 RTC_Get_Week (u16 year,u8 month,u8 day)
{	
	u16 temp;
	u8 yearH,yearL;
	
	yearH = year / 100;
	yearL = year % 100;
	
	// 如果为21世纪,年份数加100  
	if (yearH > 19)
	{
		yearL += 100;
	}
	
	// 所过闰年数只算1900年之后的  
	temp = yearL + yearL / 4;
	temp = temp % 7; 
	temp = temp + day + table_week[month - 1];
	
	if (yearL % 4 == 0 && month < 3)
	{
		temp --;
	}
	
	return(temp % 7);
}

5.7 中断服务函数

/*
 *==============================================================================
 *函数名称:RTC_IRQHandler
 *函数功能:RTC中断服务函数
 *输入参数:无
 *返回值:无
 *备  注:更新时间
 *==============================================================================
 */
void RTC_IRQHandler(void)
{
	// 秒中断
	if (RTC_GetITStatus(RTC_IT_SEC) != RESET)
	{							
		RTC_Get_CurDate();   // 获取当前时间
		// 串口打印当前时间
		printf("RTC Time:%d-%d-%d %d:%d:%d   Week:%d\n",calendar.w_year,calendar.w_month,calendar.w_date,
		        calendar.hour,calendar.min,calendar.sec,calendar.week);
 	}		  								 
	RTC_ClearITPendingBit(RTC_IT_SEC | RTC_IT_OW);   //清除秒中断标志位
	RTC_WaitForLastTask();   // 等待最近一次对RTC寄存器的写操作完成 						 	   	 
}

六、拓展

在实际使用时,通常会通过网络授时,也就是利用WIFI模块连接网络,请求API获得初始时间。但是可能会存在些许差异。比如请求API后,获得的时间为2023.06.26.14:48:00。实际单片机解析出时间时已经过去了几秒或者十几秒,或者其他问题导致了实际解析出时间后已经与实际值有差距。此时就需要对时间进行矫正。博主在实际应用时差了14s,这里贴一下当时的矫正程序。可能大家用不到,这里只是觉得思考的过程有意思,所以贴出来分享一下。

void RTC_Time_Correct(void)   // 开机时间校正
{
	// 加14秒不满1分钟
	if (gTimeSec < 46)
	{
		gTimeSec = gTimeSec + 14;
	}
	// 加14秒满1分钟
	else if (gTimeSec >= 46)
	{
		gTimeSec = gTimeSec + 14 - 60;
		
		// 分钟数需要加1
		// 加1分钟不满1小时
		if (gTimeMin < 59)
		{
			gTimeMin = gTimeMin + 1;
		}
		// 分钟数加1满1小时
		else if (gTimeMin == 59)
		{
			gTimeMin = 0;
			
			// 小时数需要加1
			// 加1小时不满1天
			if (gTimeHour < 23)
			{
				gTimeHour = gTimeHour + 1;
			}
			// 加1小时满1天
			else if (gTimeHour == 23)
			{
				gTimeHour = 0;
				// 天数需要加1
				// 天数小于28直接加1
				if (gTimeDay < 28)
				{
					gTimeDay = gTimeDay + 1;
				}
				// 天数等于28
				else if (gTimeDay == 28)
				{
					// 当前为二月
					if (gTimeMon == 2)
					{
						// 闰年
						if (Is_Leap_Year(gTimeYear))
						{
							gTimeDay = gTimeDay + 1;
						}
						// 当前为2月且不是闰年
						else
						{
							gTimeDay = 0;   // 天数置零
							gTimeMon = gTimeMon + 1;   // 月份加1
						}
					}
				}
				// 天数等于30
				else if (gTimeDay == 30)
				{
					// 当前月份只有30天
					if (gTimeMon == 2 || gTimeMon == 4 || gTimeMon == 6 || gTimeMon == 9
						  || gTimeMon == 11)
					{
						gTimeDay = 0;
						gTimeMon = gTimeMon + 1;
					}
					// 当前月份有31天
					else
					{
						gTimeDay = gTimeDay + 1;
					}
				}
				// 天数等于31
				else if (gTimeDay == 31)
				{
					gTimeDay = 0;
					
					// 加1月不满1年
					if (gTimeMon != 12)
					{
						gTimeMon = gTimeMon + 1;
					}
					else
					{
						gTimeMon = 1;
						gTimeYear = gTimeYear + 1;
					}
				}
			}
		}
	}
}

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

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

相关文章

【②MySQL 】:测试数据准备、SQL语句规范与基本操作

前言 欢迎来到小K的MySQL专栏&#xff0c;本节将为大家准备MySQL测试数据、以及带来SQL语句规范、数据库的基本操作的详细讲解~✨文末送书&#xff0c;小K赠书活动第二期 目录 前言一、准备测试数据二、SQL语句规范三、数据库的基本操作四、总结&#xff1a;文末赠书 一、准备测…

智能应急疏散系统在大型建筑中的的功能与应用

安科瑞 华楠 摘 要&#xff1a;随着经济的不断发展和城市化进程的推进,城市建筑逐渐发展为高层化、大型化和功能综合化,大空间的建筑物增多。为了实现以人为本,坚持可持续发展理念,保证城市建设系统的正常运行,安全防灾系统在建筑中必不可少,而火患是一项重要的防范内容,要不断…

使用RabbitMQ死信队列关闭未支付的订单

一、什么是RabbitMQ死信队列 RabbitMQ死信队列&#xff08;Dead-Letter Exchange&#xff0c;简称DLX&#xff09;是一种特殊类型的交换机&#xff0c;用于处理在队列中无法被消费的消息。当消息无法被消费时&#xff0c;它会被转发到死信队列中&#xff0c;以便进一步处理。 …

7-WebApis-1

Web APIs - 1 掌握DOM属性操作&#xff0c;完成元素内容设置&#xff0c;元素属性设置&#xff0c;控制元素样式 DOM简介获取DOM元素操作元素内容操作元素属性定时器-间隔函数综合案例 描述属性/方法效果获取DOM对象document.querySelector()获取指定的第一个元素document.que…

nuxt 设置i18n后多语言文件不会动态更新

nuxt 设置i18n后多语言文件不会动态更新 昨天遇到的一个问题&#xff0c;然后研究了一整天&#xff0c;今天才得到解决 nuxt 设置i18n多语言时多语言文件不会动态更新 我的原始代码如下&#xff1a; {modules: [nuxtjs/i18n,],i18n: {locales: [{code: en,iso: en-US,name:…

构建可靠软件的关键步骤之单元测试

引言&#xff1a;在当今快节奏的软件开发环境中&#xff0c;构建可靠的软件是至关重要的。单元测试作为软件开发过程中的关键步骤之一&#xff0c;能够帮助开发者发现和解决代码中的错误&#xff0c;确保代码的正确性。本文将详细介绍单元测试的概念、重要性以及如何有效地进行…

impala远程连接失败排查

周一开发反馈在本地电脑上连接impala失败&#xff0c;怀疑是服务问题。测试后发现服务正常&#xff0c;故障也恢复了&#xff0c;就没追究&#xff0c;第二天又出现相似的故障。服务依然正常。怀疑是网络问题。联系网络同事排查。telnet通。网络负载也不是很高&#xff0c;搁置…

档案库房温湿度标准及措施【档案八防十防解决方案】

档案馆库房温湿度调控标准及相应的措施方案 档案库房是档案保管的基本条件&#xff0c;档案库房温湿度与保护档案&#xff0c;延长档案寿命有很大关系。 档案库房适宜温湿度标准为&#xff1a;温度14℃—24℃&#xff0c;相对湿度45&#xff05;一60 一、库房温湿度对档案的影响…

基于Arduino单片机超声波测距仪设计

文章目录 摘 要 1.课程设计任务 1.1课程设计题目 1.2设计的要求 2.设计总体方案 2.1初步设计方案 2.2各个单元电路的设计要求 2.3主要性能指标 2.4总体方案 3.单元模块设计 3.1显示模块 3.2超声波测距模块 3.3蜂鸣器模块 3.4电机模块 3.5 LED二极管模块 4.软件…

【三维编辑】Editing Conditional Radiance Fields 编辑条件辐射场

Editing Conditional Radiance Fields&#xff08;ICCV 2021&#xff09; 作者单位&#xff1a;Steven Liu, Xiuming Zhang, Zhoutong Zhang, Richard Zhang MIT, Adobe Research, CMU 代码地址&#xff1a;https://github.com/stevliu/editnerf 文章目录 摘要前言一、相关工作…

避雷器带电监测仪

一、产品特点&#xff1a; 本机采用大屏幕液晶显示&#xff0c;全中文菜单操作&#xff0c;使用简便高精度采样、处理电路&#xff0c;先进的付里叶谐波分析技术&#xff0c;确保数据更加可靠 仪器采用独特的高速磁隔离数字传感器直接采ji输入的电压、电流信号&#xff0c;保证…

HTML 全面入门教程:从基础到高级

目录 一、基本结构和标签1. HTML 文档结构2. 常用标签 二、表单和输入元素1. 表单标签&#xff08;<form>&#xff09;2. 输入元素3.实例 三、样式和布局1. 内联样式2. 内部样式表3. 外部样式表 四、多媒体和嵌入内容1. 图像2. 音频和视频3. 嵌入内容 五、语义化标签语义…

胎压计PCBA方案设计

汽车的出现极大的方便了人们的交通出行&#xff0c;随着经济社会的发展&#xff0c;人们生活水平显著提高&#xff0c;不少家庭都购买了汽车。但是车主们不仅要知道开车&#xff0c;更需要知道检测汽车胎压。气压计也称为胎压计&#xff0c;是一种检测胎压的测量仪器。电子产品…

RabbitMQ学习笔记6(小滴课堂)路由,主题模式

我们去修改我们的生产者代码&#xff1a; 我们去修改我们的消费者&#xff1a; 第一个节点&#xff1a; 我们还要去创建其它更多的节点&#xff1a; 这里第二个节点我们只绑定一个交换机队列。 我们去分别启动消费者和生产者&#xff1a; 我们可以看到第一个交换机只绑定了一…

Deepin 20.8 linux convert 一寸照 调整图片尺寸413x579 300dpi

原图 convert修改尺寸指令 convert 一寸照.jpg -resize 413x579 一寸照413x579.jpg 目标图 尺寸已调整&#xff0c;dpi太低了 图片高清修复 提升dpi https://github.com/microsoft/Bringing-Old-Photos-Back-to-Life 官方安装过程参考 Installation Clone the Synchron…

2023腾讯云国际站注册流程介绍-腾讯云国际代充

腾讯云是国内三大云服务商之一&#xff0c;为国内外多个应用程序提供服务器支持。腾讯云的产品比较全面&#xff0c;包括云数据库、 CDN、对象存储&#xff08;COS&#xff09;和高防服务器等&#xff0c;满足各种上云需求。 1.腾讯云区分国内站和国际站&#xff0c;并存在明显…

C# MVC 多图片上传预览

一.效果图&#xff1a; 开发框架&#xff1a;MVC&#xff0c;Layui 列表主界面这里就不展示了&#xff0c;可以去看看这篇文章&#xff1a;Layui项目实战&#xff0c;这里讲的是“上传Banner”界面功能&#xff1a; 其中包括&#xff0c;多文件上传&#xff0c;预览&#xff0c…

【Python】python进阶篇之文件操作

文件操作 编码格式 python3默认的文件编码就是UTF-8 以下内容来源于AI 编码格式是指将字符、符号、数字等信息转化为二进制形式以便计算机能够理解和处理的规则或标准。在计算机领域&#xff0c;常见的编码格式有 ASCII、Unicode、UTF-8 等。 ASCII&#xff08;American Stand…

技术管理三板斧第一板斧拿结果-追过程

一、什么是过程管理&#xff1f; 管理就是追求事务的可持续发展&#xff0c;而想要达成这个目标有两个基本点&#xff1a; 管理动作要形成可持续迭代的闭环&#xff1b; 管理动作足够简单到可以复制和个性化升级。 过程管理当然也遵循这个理念。比如你这次 A 项目做得很好&a…

NXP i.MX 8M Plus工业开发板硬件说明书--上册( 四核ARM Cortex-A53 + 单核ARM Cortex-M7,主频1.6GHz)

前 言 本文档主要介绍创龙科技TLIMX8MP-EVM评估板硬件接口资源以及设计注意事项等内容。 创龙科技TLIMX8MP-EVM是一款基于NXP i.MX 8M Plus的四核ARM Cortex-A53 单核ARM Cortex-M7异构多核处理器设计的高性能工业评估板&#xff0c;由核心板和评估底板组成。ARM Cortex-A5…