细说STM32F407单片机RTC的基本原理及闹钟和周期唤醒功能的使用方法
目录
一、RTC基础知识
1、 RTC的功能
2、RTC工作原理
(1)RTC的时钟信号源
(2)预分频器
(3)实时时钟和日历数据
(4)周期性自动唤醒
(5)可编程闹钟
(6)时间戳
(7)入侵检测
(8)数字校准
(9)RTC参考时钟检测
3、RTC的中断和复用引脚
二、RTC的HAL基础驱动
1、RTC初始化
2、读取和设置日期
3、读取和设置时间
4、二进制数与BCD码之间的转换
5、判断函数
三、周期唤醒和闹钟
1、周期唤醒相关HAL函数
(1)宏函数
(2)周期唤醒定时器
(3)周期唤醒中断回调函数
2、闹钟相关HAL函数
四、案例:闹钟及周期唤醒功能的用法
1、工程简介
2、项目配置
(1)时钟、DEBUG、CodeGenerator
(2) RTC
1)RTC模式设置
2)RTC基本参数设置
3)闹钟定时设置
4)周期唤醒设置
(3)USART6
(4) NVIC
3、软件设计
(1)main.c
(2)rtc.c
4、运行与调试
实时时钟(Real-Time Clock,RTC)是由时钟信号驱动的日历时钟,提供日期和时间数据。STM32F407上有一个RTC,可以由备用电源VBAT供电,从而提供不间断的日期时间数据。它还有两个可编程闹钟,一个周期唤醒单元,使用RTC可以实现一些时间日历相关的应用。
一、RTC基础知识
1、 RTC的功能
STM32F407有一个片上RTC,它可以由内部或外部时钟信号驱动,提供日历时间数据,它内部维护一个日历,能自动确定每个月的天数,能自动处理闰年情况,还可以设定夏令时补偿。RTC能提供BCD或二进制的秒、分钟、小时(12或24小时制)、星期几、曰期、月份、年份数据,还可以提供二进制的亚秒数据。
RTC及其时钟都使用备用存储区域,而备用存储区域使用VBAT备用电源(一般用纽扣电池作为VBAT电源),所以即使主电源断电或系统复位也不影响RTC的工作。
RTC有两个可编程闹钟,可以设定任意组合和重复性的闹钟;有一个周期唤醒单元,可以作为一个普通定时器使用;还具有时间戳和入侵检测功能。
2、RTC工作原理
RTC的结构如下图所示,从几个方面对RTC的工作原理和特性进行说明。
(1)RTC的时钟信号源
从上图,RTC可以从3个时钟信号中选择一个作为RTC的时钟信号源。
- LSI,MCU内部的32kHz时钟信号。
- LSE,MCU外接的32.768kHz时钟信号。
- HSE_RTC,HSE经过2到31分频后的时钟信号。
如果MCU有外接的32.768kHz晶振,一般选择LSE作为RTC的时钟源,因为32.768kHz经过多次2分频后,可以得到精确的1Hz时钟信号。
(2)预分频器
RTC的时钟源信号经过精密校准后就是时钟信号RTCCLK,RTCCLK依次要经过一个7位的异步预分频器(最高为128分频)和一个15位的同步预分频器(默认为256分频)。
如果选用32.768kHz的LSE时钟源作为RTCCLK,经过异步预分频器128分频后的信号ck_apre是256Hz。256Hz的时钟信号再经过同步预分频器256分频后得到1Hz时钟信号ck_spre。这个1Hz信号可以用于更新日历,也可以作为周期唤醒单元的时钟源。
ck_apre和ck_spre经过一个选择器后,可以选择其中一个时钟信号作为RTC_CALIB时钟信号,这个时钟信号再经过输出控制选择,可以输出到复用引脚RTC_AF1,也就是可以向外部提供一个256Hz或1Hz的时钟信号。
(3)实时时钟和日历数据
上图中,有3个影子寄存器,RTC_SSR对应亚秒数据,RTC_TR对应于时间,RTC_DR对应于日期。影子寄存器就是内部亚秒计数器、日历时间计数器的数值暂存寄存器,系统每隔两个RTCCLK周期就将当前的日历值复制到影子寄存器。当程序读取日期时间数据时,读取的是影子寄存器的内容,而不会影响日历计数器的工作。
(4)周期性自动唤醒
RTC内有一个16位自动重载递减计数器,可以产生周期性的唤醒中断,16位寄存器RTC_WUTR存储用于设置定时周期的自动重载值。周期唤醒定时器的输入时钟有如下两个来源。
- 同步预分频器输出的ck_spre时钟信号,通常是1Hz。
- RTCCLK经过2、4、8或16分频后的时钟信号。
一般可以在周期性唤醒中断里读取RTC当前时间,例如,设置周期唤醒时钟源为1Hz的ck_spre信号,且每秒中断一次。唤醒中断产生事件信号WUTF,这个信号可以配置输出到复用引脚RTC_AF1。
(5)可编程闹钟
RTC有2个可编程闹钟,即闹钟A和闹钟B。闹钟的时间和重复方式是可以设置的,闹钟触发时可以产生事件信号ALRAF和ALRBF。这两个信号和周期唤醒事件信号WUTF一起经过一个选择器,可以选择其中一个信号作为输出信号RTC_ALARM,再通过输出控制可以输出到复用引脚RTC_AF1。
(6)时间戳
时间戳(timestamp)就是某个外部事件(上跳沿或下跳沿变化)发生时刻的日历时间,例如,行车记录仪在发生碰撞时保存的发生碰撞时刻的RTC日期时间数据就是时间戳。
启用RTC的时间戳功能,可以选择复用引脚RTC_AF1或RTC_AF2作为事件源RTC_TS,监测其上跳沿或下跳沿变化。当复用引脚上发生事件时,RTC就将当前的日期时间数据记录到时间戳寄存器,还会产生时间戳事件信号TSF,响应此事件中断就可以读取出时间戳寄存器的委据。如果检测到入侵事件,也可以记录时间戳数据。
(7)入侵检测
入侵检测(tamper[ˈtæmpər] detection)输入信号源有两个,即RTC_TAMP1和RTC_TAMP2,这两个信号源可以映射到复用引脚RTC_AF1和RTC_AF2。可以配置为边沿检测或带滤波的电平检测。STM32F407上有20个32位备份寄存器,这些备份寄存器是在备份域中的,由备用电源VBAT供电。在系统主电源关闭或复位时,备份寄存器的数据不会丢失,所以可以用于保存用户定义数据。当检测到入侵事件发生时,MCU就会复位这20个备份寄存器的内容。检测到入侵事件时,MCU会产生中断事件信号,同时还会记录时间戳数据。
(8)数字校准
RTC内部有粗略数字校准和精密数字校准。粗略数字校准需要使用异步预分频器的256Hz时钟信号,校准周期为64min。精密数字校准需要使用同步预分频器输出的1Hz时钟信号,默误模式下校准周期为32s。
用户可以选择256Hz或1Hz数字校准时钟信号作为校准时钟输出信号RTC_CALIB,通过输出控制可以输出到复用引脚RTC_AF1。
(9)RTC参考时钟检测
RTC的日历更新可以与一个参考时钟信号RTC_REFIN(通常为50Hz或60Hz)同步,RTC_REFIN使用引脚PB15。参考时钟信号RTC_REFIN的精度应该高于32.768kHz的LSE时钟。启用RTC_REFIN检测时,日历仍然由LSE提供时钟,而RTC_REFIN用于补偿不准确的日历更新频率。
3、RTC的中断和复用引脚
一般的外设只有一个中断号,一个中断号有多个中断事件源,例如,通用定时器,虽然有多个中断事件源,但只有一个中断号。但是RTC有3个中断号,每个中断号有对应的ISR,如下表所示:
中断号 | 中断名称 | 说明 | ISR |
2 | TAMP_STAMP | 连接到EXTI 21线的RTC入侵和时间戳中断 | TAMP_STAMP_IRQHandler() |
3 | RTC_WKUP | 连接到EXTI22线的RTC唤醒中断 | RTC_WKUP_IRQHandler() |
41 | RTC_Alarm | 连接到EXTI17线的RTC闹钟(A和B)中断 | RTC_Alarm_IRQHandler() |
RTC的这3个中断号各对应1个到3个中断事件源,例如,RTC_WKUP中断只有1个中断事件源,即周期唤醒中断事件,RTC_Alarm中断有2个中断事件源,即闹钟A中断事件和闹钟B中断事件,而TAMP_STAMP有3个中断事件源。
在HAL驱动程序中,每个中断事件都对应有表示中断事件类型的宏,每个中断事件对应一个回调函数。中断名称、中断事件类型和回调函数的对应关系如下表所示。基于这个表,在处理某个中断事件时,就只需重新实现其回调函数即可。
中断名称 | 中断事件源 | 中断事件类型 | 输出或输入 | 回调函数 |
RTC_Alarm | 闹钟A | RTC_IT_ALRA | RTC AF1 | HAL_RTC_AlarmAEventCallback() |
闹钟B | RTC_IT_ALRB | RTC AF1 | HAL_RTCEx_AlarmBEventCallback() | |
RTC_WKUP | 周期唤醒 | RTC_IT_WUT | RTC AF1 | HAL_RTCEx_WakeUpTimerEventCallback() |
TAMP_STAMP | 时间戳 | RTC_IT_TS | RTC_AF1或 | HAL_RTCEx_TimeStampEventCallback() |
入侵检测1 | RTC_IT_TAMP1 | RTC AF1 或 | HAL_RTCEx_Tamper1EventCallback() | |
入侵检测2 | RTC_IT_TAMP2 | RTC AF1 或 | HAL_RTCEx_Tamper2EventCallback() |
其中,“中断事件类型”一列中是HAL库中定义的宏,实际上是各中断事件在RTC控制寄存器(RTC_CR)中的中断使能控制位的掩码。这些中断事件类型的宏定义如下:
#define RTC_IT_TS 0x00008000U
#define RTC_IT_WUT 0x00004000U
#define RTC_IT_ALRB 0x00002000U
#define RTC_IT_ALRA 0x00001000U
#define RTC_IT_TAMP 0x00000004U /*仅用于使能Tamper中断*/
#define RTC_IT_TAMP1 0x00020000U
#define RTC_IT_TAMP2 0x00040000U
某些中断事件产生的信号可以选择输出到RTC的复用引脚,某些事件需要外部输入信号。其中,闹钟A、闹钟B和周期唤醒中断的信号可以选择输出到复用引脚RTC_AF1,时间戳事件检测一般使用RTC_AF1作为输入引脚,入侵检测可以使用RTC_AF1或RTC_AF2作为输入引脚。对于STM32F407xx,复用引脚RTC_AF1是引脚PC13,RTC_AF2是引脚PI8。只有176个引脚的MCU上才有PI8,所以,STM32F407ZG上没有RTC_AF2,只有RTC_AF1。
复用引脚除了可以作为闹钟A、闹钟B和周期唤醒中断信号的输出引脚外,还可以作为两个预分频器时钟的输出引脚,用于输出256Hz或1Hz的时钟信号。
二、RTC的HAL基础驱动
RTC的HAL驱动程序头文件有两个,即stm32f4xx_hal_rtc.h和stm32f4xx_hal_rtc_ex.h针对RTC、闹钟、周期唤醒、入侵检测分别有一组函数和定义。
RTC的一些通用基础函数如下表所示,包括RTC初始化函数、读取日期和时间的函数设置日期和时间的函数、BCD码与二进制之间转换的函数,以及一些判断函数。
函数名 | 功能描述 |
HAL_RTC_Init() | RTC初始化 |
HAL_RTC_MspInit() | RTC初始化的MSP弱函数,在HAL RTC_Init()中被调用。重新实现的这个函数一般用于RTC中断的设置 |
HAL_RTC_GetDate() | 获取RTC当前日期,返回的日期数据是RTC_DateTypeDef类型结构体 |
HAL_RTC_SetDate() | 设置RTC日期 |
HAL_RTC_GetTime() | 获取RTC当前时间,返回的时间数据是RTC_TimeTypeDef类型结构体 |
HAL_RTC_SetTime() | 设置RTC时间 |
HAL_RTC_GetState() | 返回RTC当前状态,状态是枚举类型HAL_RTCStateTypeDef |
RTC_Bcd2ToByte() | 2位BCD码转换为二进制数 |
RTC_ByteToBcd2() | 将二进制数转换为2位BCD码 |
IS_RTC_YEAR(YEAR) | 宏函数,判断参数YEAR是否小于100 |
IS_RTC_MONTH(MONTH) | 宏函数,判断参数MONTH是否在1和12之间 |
IS_RTC_DATE(DATE) | 宏函数,判断参数DATE是否在1和31之间 |
IS_RTC_WEEKDAY(WEEKDAY) | 宏函数,判断参数WEEKDAY是否在宏定义常量RTC_WEEKDAY_ |
IS_RTC_FORMAT(FORMAT) | 宏函数,判断参数FORMAT是否为RTC_FORMAT_BIN或 |
IS_RTC_HOUR_FORMAT(FORMAT) | 宏函数,判断参数FORMAT是否为RTC_HOURFORMAT_12 |
1、RTC初始化
RTC初始化函数进行RTC初始化的函数是HAL_RTC_Init(),其原型定义如下:
HAL_StatusTypeDef HAL_RTC_Init(RTC_HandleTypeDef *hrtc);
其中,参数hrtc是RTC外设对象指针,是RTC_HandleTypeDef结构体类型指针。结构体RTC_HandleTypeDef的定义如下:
typedef struct
{RTC_TypeDef *Instance; //RTC寄存器基地址RTC_InitTypeDef Init; //RTC的参数HAL_LockTypeDef Lock; //RTC锁定对象__IO HAL_RTCStateTypeDef State; //时间通信状态
}RTC_HandleTypeDef;
其中的成员变量Init存储了RTC的各种参数,是RTC_InitTypeDef结构体类型,其原型定义如下:
typedef struct
{uint32_t HourFormat; //小时数据格式,12小时制或24小时制uint32_t AsynchPrediv; //异步预分频器值,范围0x00~0x7E,默认值为127uint32_t SynchPrediv; //同步预分频器值,范围0x00~0x7FFFU,默认值为255uint32_t OutPut; //哪个信号被作为RTC输出信号uint32_t OutPutPolarity; //输出信号的极性,信号有效时的电平uint32_t OutPutType; //输出引脚模式,开漏输出或推挽输出
}RTC_InitTypeDef;
其中,小时数据的格式取值可以用如下的宏定义常量:
#define RTC_HOURFORMAT_240x00000000U //24小时制
#define RTC_HOURFORMAT_120x00000040U //12小时制
2、读取和设置日期
读取RTC当前日期的函数是HAL_RTC_GetDate(),其原型定义如下:
HAL_StatusTypeDef HAL_RTC_GetDate(RTC_HandleTypeDef *hrtc,RTC_DateTypeDef *sDate,uint32_t Format);
返回的日期数据保存在RTC_DateTypeDef类型指针sDate指向的变量里,参数Format表示返回日期数据类型是BCD码或二进制码,可以用下面的宏定义常量作为Format的值。
#define RTC_FORMAT_BIN 0x00000000U //二进制格式
#define RTC_FORMAT_BCD 0x00000001U //BCD码格式
日期数据结构体RTC_DateTypeDef的定义如下:
typedef struct
{uint8_t WeekDay; //星期几,有表示星期几的宏定义uint8_t Month; //月份,有表示月份的宏定义uint8_t Date; //日期,范围1~31uint8_t Year; //年,范围0~99,表示2000~2099
}RTC_DateTypeDef;
设置日期的函数是HAL_RTC_SetDate(),其原型定义如下:
HAL_statusTypeDef HAL_RTC_SetDate(RTC_HandleTypeDef *hrtc,RTC_DateTypeDef *sDate.uint32_t Format);
参数sDate是需要设置的日期数据指针,参数Format表示数据的格式是BCD码或二进制码。
3、读取和设置时间
读取时间的函数是HAL_RTC_GetTime(),其原型定义如下:
HAL_StatusTypeDef HAL_RTC_GetTime(RTC_HandleTypeDef *hrtc,RTC_TimeTypeDef *sTime.uint32_t Format);
返回的时间数据保存在RTC_TimeTypeDef类型指针sTime指向的变量里,参数Format表示返回日期数据类型是BCD码或二进制码。
时间数据结构体RTC_TimeTypeDef的定义如下:
typedef struct
{uint8_t Hours; //小时,范围0~12(12小时制),或0~23(24小时制)uint8_t Minutes; //分钟,范围0~59uint8_t Seconds; //秒,范围0~59uint8_t TimeFormat; //时间格式,AM或PM显示uint32_t SubSeconds; //亚秒数据uint32_t SecondFraction; //秒的小数部分数据uint32_t DayLightSaving; //夏令时设置uint32_t StoreOperation; //存储操作定义
}RTC_TimeTypeDef;
一般情况下,只需关心时间的小时、分钟和秒数据,如果是12小时制,还需要看TimeFormat的值。AM/PM的取值使用如下的宏定义:
#define RTC_HOURFORMAT12_AM ((uint8_t)0x00) //表示AM
#define RTC_HOURFORMAT12_PM ((uint8_t)0x40) //表示PM
设置时间的函数是HAL_RTC_SetTime(),其原型定义如下:
HAL_StatusTypeDef HAL_RTC_SetTime(RTC_HandleTypeDef *hrtc,RTC_TimeTypeDef *sTime,int32_t Format);
任何时候读取日期和读取时间的函数都必须成对使用,即使读出的日期或时间数据用不上。也就是说,调用HAL_RTC_GetTime()之后,必须调用HAL_RTC_GetDate(),否则不能连续更新日期和时间。因为调用HAL_RTC_GetTime()时会锁定日历影子寄存器的当前值,直到日期数据被读出后才会被解锁。
4、二进制数与BCD码之间的转换
读取和设置RTC的日期或时间数据时,可以指定数据格式为二进制或BCD码,二进制就是常规的数。BCD(Binary Coded Decimal)码是为便于BCD数码管显示用的编码,它用4位二进制数表示十进制中一个位的数,表示的范围是0~9,百位、十位、个位连续排列。
读取日期或时间的函数中有个Format参数,可以指定为二进制格式(RTC_FORMAT_BIN)或BCD码格式(RTC_FORMAT_BCD),这两种编码的数据之间可以通过HAL提供的两个函数进行转换。这两个函数的原型定义如下,这两个函数只能转换两位数字的数据。
uint8_t RTC_Bcd2TOByte(uint8_t Value) //两位BCD码转换为二进制数
uint8_t RTC_ByteTOBcd2(uint8_t Value) //二进制数转换为两位BCD码
5、判断函数
在文件stm32f4xx_hal_rtc.h中有一些以“IS_RTC_”为前缀的宏函数,这些宏函数主要用于判断参数是否在合理范围之内。部分典型的宏函数定义如下,全部的此类函数定义见文件m32f4xx_hal_rtc.h。
#define IS_RTC_YEAR(YEAR) ((YEAR)<=99U)
#define IS_RTC_MONTH(MONTH) (((MONTH)>=1U)&&((MONTH)<=12U))
#define IS_RTC_DATE(DATE) (((DATE)>=1U)&&((DATE)<=31U))
define IS_RTC_HOUR12(HOUR) (((HOUR)>0U)&&((HOUR)<=12U))
#define IS_RTC_HOUR24(HOUR) ((HOUR)<=23U)
#define IS_RTC_ASYNCH_PREDIV(PREDIV) ((PREDIV)<=0x7FU)
#define IS_RTC_SYNCH_PREDIV(PREDIV) ((PREDIV)<=0x7FFFU)
#define IS_RTC_MINUTES(MINUTES) ((MINUTES)<=59U)
#define IS_RTC_SECONDS(SECONDS) ((SECONDS)<=59U)
三、周期唤醒和闹钟
1、周期唤醒相关HAL函数
周期唤醒就是RTC的一种定时功能,一般为周期唤醒定时器设置1Hz时钟源,每秒或每隔几秒中断一次。使用RTC的周期唤醒功能,可以很方便地设置1s定时中断,与系统时钟频率无关,比用定时器设置1s中断要简单得多。
RTC周期唤醒中断的相关函数在文件stm32f4xx_hal_rtc_ex.h中定义,常用的函数如下表所示。
函数名 | 功能描述 |
__HAL_RTC_WAKEUPTIMER_ENABLE() | 开启RTC的周期唤醒单元 |
__HAL_RTC_WAKEUPTIMER_DISABLE() | 停止RTC的周期唤醒单元 |
__HAL_RTC_WAKEUPTIMER_ENABLE_IT() | 允许RTC周期唤醒事件产生硬件中断 |
__HAL_RTC_WAKEUPTIMER_DISABLE_IT() | 禁止RTC周期唤醒事件产生硬件中断 |
HAL_RTCEx_GetWakeUpTimer() | 获取周期唤醒计数器的当前计数值,返回值类型uint32_t |
HAL_RTCEx_SetWakeUpTimer() | 设置周期唤醒单元的计数周期和时钟信号源,不开启 |
HAL_RTCEx_SetWakeUpTimer_IT() | 设置周期唤醒单元的计数周期和时钟信号源,开启中断 |
HAL_RTCEx_DeactivateWakeUpTimer() | 停止RTC周期唤醒单元及其中断,停止后可用两个宏函数重新启动RTC周期唤醒单元及其中断 |
HAL_RTCEx_WakeUpTimerIRQHandler() | RTC周期唤醒中断的ISR里调用的通用处理函数 |
HAL_RTCEx_WakeUpTimerEventCallback() | RTC周期唤醒事件的回调函数 |
这些函数都要用到RTC外设对象指针。RTC初始化程序文件rtc.c定义了表示RTC的外设对象变量hrtc。
RTC_HandleTypeDef hrtc; //RTC外设对象变量
(1)宏函数
周期唤醒中断事件类型的定义是宏定义RTC_IT_WUT,定义如下:
#define RTC_IT_WUT 0x00004000U //周期唤醒中断事件类型
在允许或禁止RTC周期唤醒事件产生硬件中断的宏函数里,会用到这个宏定义,示例如下:
__HAL_RTC_WAKEUPTIMER_ENABLE_IT(&hrtc,RTC_IT_WUT); //允许RTC周期唤醒事件产生中断
__HAL_RTC_WAKEUPTIMER_DISABLE_IT(&hrtc,RTC_IT_WUT); //禁止RTC周期唤醒事件产生中断
(2)周期唤醒定时器
函数HAL_RTCEx_SetWakeUpTimer()设置周期唤醒定时器的定时周期数和时钟信号源,不开启周期唤醒中断,其原型定义如下:
HAL_StatusTypeDef HAL_RTCEx_SetWakeUpTimer(RTC_HandleTypeDef *hrtc,uint32_t WakeUpCounter,uint32_t WakeUpClock)
其中,参数WakeUpCounter是计数周期值,参数WakeUpClock是时钟信号源,可以使用一组宏定义表示的时钟信号源。
函数HAL_RTCEx_SetWakeUpTimer_IT()设置周期唤醒定时器的定时周期数和时钟信号源,并开启周期唤醒中断,函数参数形式与HAL_RTCEx_SetWakeUpTimer()的一样。这两个函数在CubeMX生成的RTC初始化函数代码里会被调用。
函数HAL_RTCEx_DeactivateWakeUpTimer()用于停止RTC周期唤醒单元及其中断,内部调用__HAL_RTC_WAKEUPTIMER_DISABLE()和__HAL_RTC_WAKEUPTIMER_DISABLE_IT()。
(3)周期唤醒中断回调函数
RTC的周期唤醒中断有独立的中断号,ISR是RTC_WKUP_IRQHandler()。在CubeMX中开启RTC的周期唤醒中断后,在文件stm32f4xx_t.c中自动生成周期唤醒中断的ISR,代码如下:
void RTC_WKUP_IRQHandler(void)
{HAL_RTCEx_WakeUpTimerIRQHandler(&hrtc);
}
其中,函数HAL_RTCEx_WakeUpTimerIRQHandler()是周期唤醒中断的通用处理函数,它内部会调用周期唤醒事件的回调函数HAL_RTCEx_WakeUpTimerEventCallback()。所以,用户要对周期唤醒中断进行处理,只需重新实现这个回调函数即可。
2、闹钟相关HAL函数
RTC有两个闹钟(某些型号MCU上只有一个),闹钟相关的函数和定义在文件stm32f4xx_rtc.h和stm32f4xx_hal_rtc_ex.h中定义。有些函数需要用一个变量区分是哪个闹钟,文件32f4xx_hal_rtc.h中有如下的宏定义区分闹钟A和闹钟B:
#define RTC_ALARM_ARTC_CR_ALRAE //表示闹钟A
#define RTC_ALARM_BRTC_CR_ALRBE //表示闹钟B
同样,假设在RTC初始化程序文件rtc.c中定义了表示RTC的外设对象变量hrtc。闹钟的相关常用函数如下表所示。
函数名 | 功能 |
__HAL_RTC_ALARM_DISABLE_IT() | 禁止闹钟A或闹钟B产生硬件中断,例如 |
__HAL_RTC_ALARM_ENABLE_IT() | 允许闹钟A或闹钟B产生硬件中断,例如 |
__HAL_RTC_ALARMA_DISABLE() | 关闭闹钟A模块,例如__HAL_RTC_ALARMA_DISABLE(&hrtc) |
__HAL_RTC_ALARMA_ENABLE() | 开启闹钟A模块,例如__HAL_RTC_ALARMA_ENABLE(&hrtc) |
__HAL_RTC_ALARMB_DISABLE() | 关闭闹钟B模块,例如__HAL_RTC_ALARMB_DISABLE(&hrtc) |
__HAL_RTC_ALARMB_ENABLE() | 开启闹钟B模块,例如__HAL_RTC_ALARMB_ENABLE(&hrtc) |
HAL_RTC_SetAlarm() | 设置闹钟A或闹钟B的闹钟参数,不开启闹钟中断 |
HAL_RTC_SetAlarm_IT() | 设置闹钟A或闹钟B的闹钟参数,开启闹钟中断 |
HAL_RTC_DeactivateAlarm() | 停止闹钟A或闹钟B,例如 |
HAL_RTC_GetAlarm() | 获取闹钟A或闹钟B的设定时间和掩码 |
HAL_RTC_AlarmIRQHandler() | 闹钟硬件中断ISR里调用的通用处理函数 |
HAL_RTC_AlarmAEventCallback() | 闹钟A中断事件的回调函数 |
HAL_RTCEx_AlarmBEventCallback() | 闹钟B中断事件的回调函数 |
函数HAL_RTC_SetAlarm()用于设置闹钟时间和掩码,函数HAL_RTC_GetAlarm()用于获取设置的闹钟时间和掩码,其参数类型与HAL_RTC_SetAlarm()的相同。
闹钟有一个中断号,ISR是RTC_Alarm_IRQHandler()。函数HAL_RTC_AlarmIRQHandler()是闹钟中断ISR里调用的通用处理函数,文件stm32f4xx_it.c中闹钟中断的ISR代码如下:
void RTC_Alarm_IRQHandler(void)
{HAL_RTC_AlarmIRQHandler(&hrtc);
}
函数HAL_RTC_AlarmIRQHandler()会根据闹钟事件来源,分别调用闹钟A的中断事件回调函数HAL_RTC_AlarmAEventCallback()或闹钟B的中断事件回调函数HAL_RTCEx_AlarmBEventCallback()。
四、案例:闹钟及周期唤醒功能的用法
1、工程简介
本实例使用旺宝红龙开发板STM32F407ZGT6 KIT V1.0,使用闹钟A、闹钟B和周期唤醒功能,具有如下功能。
- 使用32.768kHz的LSE时钟作为RTC的时钟源。
- 系统复位时初始化RTC日期为2022-2-12,时间为10:10:10。
- 每秒唤醒一次,在周期唤醒中断里读取当前日期和时间,并在串口助手上显示。
- 将周期唤醒中断信号WUTF输出到复用引脚RTC_AF1(PC13),用杜邦线连接PC13和LED1的引脚PA6(在CubeMX中不要配置PA6引脚),使其为初姓复位状态,这样,LED1的亮灭由PC13的输出状态控制。
- 闹钟A设置为在时间xx:16:05触发,其中xx表示任意数字,即在每个小时的16分5秒时刻触发闹钟A。对闹钟A中断次数计数,并在串口助手上显示。
- 闹钟B设置为在时间xx:x:30触发,即在每分钟的30秒时刻触发闹钟B。对闹钟B中断次数计数,并在串口助手上显示。
2、项目配置
(1)时钟、DEBUG、CodeGenerator
HSE,外部晶振,HCLK=168MHz;
LSE,外部晶振,32.768kHz,LSE to RTC;
DEBUG,serial wire;
选中,CodeGenerator;
(2) RTC
1)RTC模式设置
启用时钟源和日历,Alarm A和Alarm B是闹钟A和闹钟B,它们旁边的下拉列表框里都有3个选项。
- Disable,禁用闹钟。
- Internal Alarm,内部闹钟功能。
- Routed to AF1,闹钟事件信号输出到复用引脚RTC_AF1,也就是引脚PC13。
WakeUp是周期唤醒功能,它旁边的下拉列表框里有3个选项。
- Disable,禁用周期唤醒功能。
- Internal WakeUp,内部周期唤醒。
- Routed to AF1,周期唤醒事件信号输出到复用引脚RTC_AF1。
本例,将闹钟A和闹钟B都设置为Internal Alarm,将周期唤醒WakeUp设置为Routed to AF1,也就是将周期唤醒事件信号输出到复用引脚RTC_AF1。
闹钟A、闹钟B和周期唤醒都可产生中断,且中断事件信号都可以输出到复用引脚RTC_AF1,但是只能选择其中一个信号输出到RTC_AF1。有一个信号占用RTC_AF1引脚后,其他使用RTC_AF1引脚的功能就不能使用了。(Timestamp Routed to AF1(时间戳)、Tamper1 Routed to AF1(入侵检测)、Calibration(校准时钟)等功能都用紫色底色标识,并且不能配置了。)
特别地,Reference clock detection是参考时钟检测功能,如果勾选此项,就会使引脚PB15作为RTC_REFIN引脚,这个引脚需要接一个50Hz或60Hz的精密时钟信号,用于对RTC日历的1Hz更新频率进行精确补偿。某些GPS模块可以配置输出025Hz至10MHz的时钟脉冲信号,在使用GPS模块的应用中,就可以配置GPS模块输出50Hz信号,作为RTC的参考时钟源。
2)RTC基本参数设置
在RTC的配置界面对RTC的参数进行设置。设置预分频器、初始日期和时间等基本参数。
General分组里有以下通用参数。
- Hour Format,小时格式,可以选择12小时制或24小时制。
- Asynchronous Predivider value,异步预分频器值。设置范围为0~127,对应分频系数是1~128。当RTCCLK为32.768kHz时,128分频后就是256Hz。
- Synchronous Predivider value,同步预分频器值。设置范围为0~32767,对应分频系数是1~32768。256分频后就是1Hz。
- Output Polarity,输出极性。闹钟A、闹钟B、周期唤醒中断事件信号有效时的输出极性,可设置为高电平或低电平。这里设置为低电平,因为配置周期唤醒模块的事件信号WUTF输出到复用引脚RTC_AF1,而RTC_AF1连接LED1的引脚PA6,当RTC_AF1输出为低电平时LED1点亮。
- Output Type,输出类型。复用引脚RTC_AF1的输出类型,可选开漏(Opendrain)输出或推挽(Pushpull)输出,这里设置为开漏输出。因为RTC_AF1和PA6都连接到LED1的同一个引脚上,设置为开漏输出更安全。
Calendar Time分组里有用于设置日历的时间参数和初始化数据的如下参数。
- Data Format,数据格式,可选择二进制格式或BCD格式,这里选择Binary data format。
- 初始化时间数据,包括时、分、秒的数据,这里设置为7时15分10秒。
- Day Light Saving:value of hour adjustment,夏令时设置,这里设置为DaylightsavingNone,即不使用夏令时。
- Store Operation,存储操作,表示是否已经对夏令时设置做修改。设置为StoreoperatioReset表示未修改夏令时,设置为Storeoperation Set表示已修改。用户可以在Calendar Date分组里设置日历初始化日期数据,包括年、月、日、星期几,其中,年的设置范围是0~99,表示2000~2099年。这里设置初始化日期为2025年2月12日,星期三。
3)闹钟定时设置
在RTC的模式设置里启用闹钟A和闹钟B后,就会在参数配置部分看到闹钟的设置。闹钟A和闹钟B的设置方法是完全一样的,闹钟的触发时间可以设置为日期(天或星期几)、时、分、秒、亚秒的任意组合,只需设置相应的日期时间和屏蔽即可。本例中,设置RTC的初始时间为7时15分10秒,闹钟A设置为在时间xx:16:05触发,即每个小时的16分5秒时刻触发。闹钟A的设置主要是闹钟日期时间设置和屏蔽设置,对应的闹钟参数的意义和设置如下表所示。
参数 | 意义 | 取值示例 | 数据范围 |
Hours | 时 | 8 | 0~23 |
Minutes | 分 | 16 | 0~59 |
Seconds | 秒 | 5 | 0~59 |
Sub Seconds | 亚秒 | 0 | 0~59 |
Alarm Mask Date Week day | 屏蔽日期 | Enable | 设置为Enable表示屏蔽,即闹钟与日期数据无关,设置为Disable表示日期数据参与比对 |
Alarm Mask Hours | 屏蔽小时 | Enable | 设置为Enable表示屏蔽,即闹钟与小时数据无关,设置为Disable表示小时数据参与比对 |
Alarm Mask Minutes | 屏蔽分钟 | Disable | 设置为Enable表示屏蔽,即闹钟与分钟数据无关,设置为Disable表示分钟数据参与比对 |
Alarm Mask Seconds | 屏蔽秒 | Disable | 设置为Enable表示屏蔽,即闹钟与秒数据无关,设置为Disable表示秒数据参与比对 |
Alarm Sub Second Mask | 屏蔽亚秒 | All Alarm SS fields are masked | 设置为All Alarm SS fields are masked表示屏蔽,闹钟与亚秒数据无关,设置为其他选项时,用于亚秒数据比对 |
Alarm Date Week Day Sel | 日期形式 | Date | 有Date和Weekday两种选项。 |
Alarm Date | 日 期 | 3 | 1~31或Monday到Sunday |
对于闹钟A,只有Alarm Mask Minutes和Alarm Mask Seconds设置为Disable,所以闹钟A的定时是xx:16:05,与小时、日期数据无关。
同样,对于闹钟B,只有Alarm Mask Seconds设置为Disable,所以闹钟B的定时是xx:xx:30,即每分钟的第30秒触发闹钟B。
4)周期唤醒设置
周期唤醒的参数设置如图11-7所示,只有两个参数需要设置。
Wake Up Clock,周期唤醒的时钟源。周期唤醒的时钟源可以来自同步预分频器的1Hz信号,也可以来自RTCCLK经过2、4、8、16分频的信号。若RTCCLK是32.768kHz,则这个参数各选项的意义如下。
- RTCCLK/16,16分频信号,即2.048kHz。
- RTCCLK/8,8分频信号,即4.096kHz。
- RTCCLK/4,4分频信号,即8.192kHz。
- RTCCLK/2,2分频信号,即16.384kHz。
- 1 Hz,来自ck_spre的1Hz信号。
- 1Hz with 1 bit added to Wake Up Counter,来自ck_spre的1Hz信号,将Wake Up Counter(唤醒计数器)的值加2¹⁶。
Wake Up Counter,唤醒计数器的重载值,设定值的范围是0~65535。表示周期唤醒计数器的计数值达到这个值时,就触发一次WakeUp中断。如果这个值设置为0,则每个时钟周期中断1次。例如,选择周期唤醒时钟源为1Hz信号时,若设置此值为0,则每1秒发生一次唤醒中断;若设置为1,则每2秒发生一次唤醒中断。
本例选择周期唤醒单元的时钟源为1Hz信号,唤醒计数器的重载值为0,所以每1秒会发生一次唤醒中断。在此中断处理程序里,读取RTC当前时间并在串口助手上显示,就可以看到时间是每秒刷新一次。
(3)USART6
使用管脚PG9、PG14,所有参数默认;
(4) NVIC
在NVIC组件的配置界面里设置RTC的中断。
3、软件设计
(1)main.c
/* USER CODE BEGIN Includes */
#include <stdio.h>
/* USER CODE END Includes */
// 菜单设计
/* USER CODE BEGIN 2 */printf("Demo11_1_RTC_Alarm:RTC and Alarm.\r\n");printf("Alarm A(xx:16:05) trigger: 0.\r\n");printf("Alarm B(xx:xx:30) trigger: 0.\r\n\r\n");
/* USER CODE END 2 */
/* USER CODE BEGIN 4 */
//串口打印
int __io_putchar(int ch)
{HAL_UART_Transmit(&huart6,(uint8_t*)&ch,1,0xFFFF);return ch;
}
/* USER CODE END 4 */
main()函数在外设初始化部分调用了MX_RTC_Init(对RTC进行初始化,包括周期唤醒和钟的初始化,为RTC选择LSE作为时钟源是在函数SystemClock_Config()里实现的。RTC初始化完成后,就自动开启周期唤醒和闹钟功能。
在串口助手上显示几条菜单信息后,程序就进入了while死循环,此后,程序的运行由中断驱动。
(2)rtc.c
/* USER CODE BEGIN 0 */
#include <stdio.h>uint16_t triggerCntA=0; //闹钟A触发次数
uint16_t triggerCntB=0; //闹钟B触发次数
/* USER CODE END 0 */
/* USER CODE BEGIN 1 */
/* 周期唤醒中断回调函数 */
void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
{RTC_TimeTypeDef sTime;RTC_DateTypeDef sDate;if (HAL_RTC_GetTime(hrtc,&sTime,RTC_FORMAT_BIN) == HAL_OK){HAL_RTC_GetDate(hrtc,&sDate,RTC_FORMAT_BIN);//调用HAL_RTC_GetTime()之后必须调用HAL_RTC_GetDate()以解锁数据,才能连续更新日期和时间//调用HAL_RTC_GetTime()时会将日历影子寄存器的当前值锁定,直到日期数据被读出//所以,即使不使用日期数据,也需要调用HAL_RTC_GetDate()读取//* @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.//显示日期(年月日)char str[40];sprintf(str,"RTC Date= %4d-%2d-%2d",2000+sDate.Year,sDate.Month,sDate.Date);printf(" %s.\r\n",str);//显示时间hh:mm:sssprintf(str,"RTC Time = %2d:%2d:%2d",sTime.Hours,sTime.Minutes,sTime.Seconds);printf(" %s.\r\n",str);}
}/* 闹钟A中断的回调函数 */
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
{triggerCntA++; //闹钟A触发计数printf("Alarm A(xx:16:05) trigger: %d\r\n",triggerCntA);
}/* 闹钟B中断的回调函数 */
void HAL_RTCEx_AlarmBEventCallback(RTC_HandleTypeDef *hrtc)
{triggerCntB++; //闹钟B触发计数printf("Alarm B(xx:xx:30) trigger: %d\r\n",triggerCntB);
}
/* USER CODE END 1 */
闹钟A和闹钟B共用EXTI线17中断,周期唤醒使用EXTI线22中断,在中断响应程序文件stm32f4xx_it.c自动生成了相应的ISR代码。要实现闹钟A、闹钟B、周期唤醒中断的处理,只需重新实现3个回调函数即可。
文件rtc.c里包含重新实现了这3个回调函数,重新实现的回调函数无须在头文件里声明函数原型。
在文件rtc.c中定义了两个uint16_t类型的全局变量,即triggerCntA和triggerCntB,用于记录闹钟A和闹钟B发生中断的次数。
周期唤醒中断的回调函数是HAL_RTCEx_WakeUpTimerEventCallback(),唤醒中断每秒触发一次。中断回调函数里用HAL_RTC_GetTime()读取RTC的当前时间,再使用HAL_RTC_GetDate()读取当前日期,然后在串口助手上显示。
调用HAL_RTC_GetTime()之后必须调用HAL_RTC_GetDate()以解锁数据,才能连续更新日期和时间。因为调用HAL_RTC_GetTime()时会锁定日历影子寄存器的当前值,直到日期数据被读出,所以即使不使用日期数据,也需要调用HAL_RTC_GetDate()读取日期数据。另外,因为还设置了将周期唤醒中断信号输出到复用引脚RTC_AF1(引脚PC13),并且用杜邦线连接了PC13与LED1的引脚PA6,所以程序运行时,可以看到LED1每秒会闪亮一下,这是因为RTC_AF1输出了一个低电平信号,只是这个信号持续时间比较短,LED1只是一闪即灭。
闹钟A的中断回调函数是HAL_RTC_AlarmAEventCallback()。闹钟A在xx:16:05时刻触发,中断回调函数在串口助手上显示信息,并且显示中断发生的次数。因RTC的初始时间设为7:15:10,因此很快就会到7:16:05,就会触发一次闹钟A中断,在串口助手上就会看到显示的闹钟A的中断信息。闹钟A实际上每隔一小时触发一次。
闹钟B的中断回调函数是HAL_RTCEx_AlarmBEventCallback()。闹钟B在xx:xx:30时刻触发,中断回调函数在串口助手上显示信息并且显示中断发生的次数。闹钟B触发周期是1分钟,可以在串口助手上看到闹钟B的中断次数每分钟增加一次。
4、运行与调试
相关文章:
细说STM32F407单片机RTC的基本原理及闹钟和周期唤醒功能的使用方法
目录 一、RTC基础知识 1、 RTC的功能 2、RTC工作原理 (1)RTC的时钟信号源 (2)预分频器 (3)实时时钟和日历数据 (4)周期性自动唤醒 (5)可编程闹钟 &a…...
ES用脚本更新异常
因为需要向原有的es结构中增加一个检索字段,但因为历史es数据都没有该字段,需要批量刷新es的该字段,本地使用了脚本的方式进行刷新,在测试环境测试,出现了以下错误: 500 Internal Server Error: [{"e…...
Navicat导入海量Excel数据到数据库(简易介绍)
目录 前言正文 前言 此处主要作为科普帖进行记录 原先Java处理海量数据的导入时,由于接口超时,数据处理不过来,后续转为Navicat Navicat 是一款功能强大的数据库管理工具,支持多种数据库系统(如 MySQL、PostgreSQL、…...
C++学习
C对C语言的加强 1.命名空间(namespace) 为了避免,在大规模程序的设计中,以及在程序员使用各种各样的C库时,这些标识符的命名发送冲突。 标准C引入了关键字namespace,可以更好地控制标识符的作用域。 st…...
Linux Mem -- Where the mte store and check in the real hardware platform
目录 1 前言 2 MTE tag分类 3 Address tag 4 Memory tag 5 Tag Check 6 Cortex-A710 和 CI-700 系统示例: 1 前言 ARM的MTE允许分配、设置、比较一个 4bit的allocation tag 为16字节粒度的物理地址。当对MTE有一定了解后,应该会产生如下疑问&#…...
老牌软件,如今依旧坚挺
今天给大家介绍一个非常好用的老牌电脑清理软件,这个软件好多年之前就有人使用了。 今天找出来之后,发现还是那么的好用,功能非常强大。 Red Button 电脑清理软件 软件是绿色版,无需安装,打开这个图标就能直接使用了…...
springboot整合modbus实现通讯
springboot整合modbus4j实现tcp通讯 前言 本文基于springboot和modbus4j进行简单封装,达到开箱即用的目的,目前本方案仅实现了tcp通讯。代码会放在最后,按照使用方法操作后就可以直接使用 介绍 在使用本方案之前,有必要对modb…...
【java面试】线程篇
1.什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。 2.线程和进程有什么区别? 线程是进程的子集,一个进程可以有很多线程,每条线程并行执行不同的任…...
DeepSeek官方发布R1模型推荐设置
今年以来,DeepSeek便在AI领域独占鳌头,热度一骑绝尘。其官方App更是创造了惊人纪录,成为史上最快突破3000万日活的应用,这一成绩无疑彰显了它在大众中的超高人气与强大吸引力。一时间,各大AI及云服务厂商纷纷投身其中&…...
Vue CLI 配置与插件
Vue CLI 配置与插件 今天我们来聊聊 Vue CLI 的配置与插件。随着项目复杂度的增加,合理配置 Vue CLI 可以帮助我们更高效地管理项目,同时利用插件机制快速集成各种功能。下面我就和大家详细介绍如何配置 Vue CLI,以及如何使用和开发插件&…...
Spring Boot (maven)分页3.0版本 通用版
前言: 通过实践而发现真理,又通过实践而证实真理和发展真理。从感性认识而能动地发展到理性认识,又从理性认识而能动地指导革命实践,改造主观世界和客观世界。实践、认识、再实践、再认识,这种形式,循环往…...
pip 与 conda 的故事
pip 换源 pip 官方源 -i https://pypi.python.org/simple pip 清华源 -i https://pypi.tuna.tsinghua.edu.cn/simple pip 阿里源 -i https://mirrors.aliyun.com/pypi/simple PyTorch 安装 pip3 install torch torchvision torchaudio pip3 install torch torchvision torchaud…...
清华大学KVCache.AI团队联合趋境科技联合的KTransformers开源项目为什么那么厉害
KTransformers是一个由清华大学KVAV.AI团队开发的开源项目,旨在优化大语言模型(LLM)的推理性能,特别是在有限显存资源下运行大型模型。以下是KTransformers的详细介绍: 1. 核心特点 高性能优化:KTransfor…...
DeepSeek 遭 DDoS 攻击背后:DDoS 攻击的 “千层套路” 与安全防御 “金钟罩”_deepseek ddos
当算力博弈升级为网络战争:拆解DDoS攻击背后的技术攻防战——从DeepSeek遇袭看全球网络安全新趋势 在数字化浪潮席卷全球的当下,网络已然成为人类社会运转的关键基础设施,深刻融入经济、生活、政务等各个领域。从金融交易的实时清算…...
4090单卡挑战DeepSeek r1 671b:尝试量化后的心得的分享
引言: 最近,DeepSeek-R1在完全开源的背景下,与OpenAI的O1推理模型展开了激烈竞争,引发了广泛关注。为了让更多本地用户能够运行DeepSeek,我们成功将R1 671B参数模型从720GB压缩至131GB,减少了80%ÿ…...
【动态路由】系统Web URL资源整合系列(后端技术实现)【apisix实现】
需求说明 软件功能需求:反向代理功能(描述:apollo、eureka控、apisix、sentinel、普米、kibana、timetask、grafana、hbase、skywalking-ui、pinpoint、cmak界面、kafka-map、nacos、gateway、elasticsearch、 oa-portal 业务应用等多个web资…...
【Elasticsearch】通过运行时字段在查询阶段动态覆盖索引字段
在 Elasticsearch 中,Override field values at query time是指通过运行时字段(runtime fields)在查询阶段动态覆盖索引字段的值,而无需修改原始索引数据。这种功能特别适用于以下场景: 1. 动态修改字段值:…...
【stm32】定时器
stm32f4xx: APB2 ----> TIM1,TIM8,TIM9,TIM10,TIM11 APB1 ----> TIM2,TIM3,TIM4,TIM5,TIM6,TIM7,TIM12,TIM13,TIM14 一、定时器介绍 1、基本定时器 1.1、TIM6 和 TIM7 的主要特性 ● 16 位自动重载递增计数器 ● 16 位可编程…...
滑动窗口算法篇:连续子区间与子串问题
1.滑动窗口原理 那么一谈到子区间的问题,我们可能会想到我们可以用我们的前缀和来应用子区间问题,但是这里对于子区间乃至子串问题,我们也可以尝试往滑动窗口的思路方向去进行一个尝试,那么说那么半天,滑动窗口是什么…...
华三交换机-链路聚合配置案例
目录 1.链路聚合简述:2.链路聚合的作用:3.链路聚合的模式:4.网络拓扑:5.实验需求:6.网络配置:6.1 链路聚合配置(静态聚合)6.1.1 链路聚合配置:6.1.2 查看链路聚合状态: 6.2 链路聚合配置(动态聚合)6.2.1 链路聚合配置:6.2.2 查看链路聚合状态: 7.网络连通性测试:(接…...
Qwen2-VL 的重大省级,Qwen 发布新旗舰视觉语言模型 Qwen2.5-VL
Qwen2.5-VL 是 Qwen 的新旗舰视觉语言模型,也是上一代 Qwen2-VL 的重大飞跃。 Qwen2.5-VL主要特点 视觉理解事物:Qwen2.5-VL不仅能够熟练识别花、鸟、鱼、昆虫等常见物体,而且还能够分析图像中的文本、图表、图标、图形和布局。 代理性&…...
关系数据库标准语言SQL
1.SOL称为结构化查询语言,它是由1974年由Boyce和Chamberlin提出的,1975年至1979年IBM公司的San Jose Research Laboratory研制了关系数据库管理系统的原型系统SystemR,并实现了这种语言。 2.SQL(Structured Ouery Language)称为结构化查询语言 3.SQL数…...
mysql8.0使用MGR实现高可用与利用MySQL Router构建读写分离MGR集群
MGR是MySQL Group Replication的缩写,即MySQL组复制。 在以往,我们一般是利用MySQL的主从复制或半同步复制来提供高可用解决方案,但这存在以下几个比较严重的问题: 主从复制间容易发生复制延迟,尤其是在5.6以前的版本…...
《AI大模型开发笔记》MoE模型技术对比(Mixtral,Qwen2-MoE,DeepSeek-v3)
MoE模型技术对比(Mixtral,Qwen2-MoE,DeepSeek-v3) MoE(混合专家)大模型进入爆发期!本期我们对比三大开源MoE LLM:Mixtral、Qwen2-MoE 和最新爆火的 DeepSeek-V3。从 2023 年 Mixtral 开启风潮,到 2024 年 DeepSeek-V3 让全球瞩目,MoE 模型到底经历了怎样的进化? De…...
Vue.js 组件开发深入解析:Vue 2 vs Vue 3
Vue.js 是一个渐进式框架,旨在通过声明式渲染和组件化开发来提高开发效率和可维护性。组件是 Vue 应用的基本组成部分,几乎所有的功能都可以通过组件来实现。随着 Vue 3 的发布,Vue.js 引入了许多新的特性,使得组件的开发变得更加…...
DeepSeek大模型一键部署解决方案:全平台多机分布式推理与国产硬件优化异构计算私有部署
DeepSeek R1 走红后,私有部署需求也随之增长,各种私有部署教程层出不穷。大部分教程只是简单地使用 Ollama、LM Studio 单机运行量化蒸馏模型,无法满足复杂场景需求。一些操作配置也过于繁琐,有的需要手动下载并合并分片模型文件&…...
多个用户如何共用一根网线传输数据
前置知识 一、电信号 网线(如以太网线)中传输的信号主要是 电信号,它携带着数字信息。这些信号用于在计算机和其他网络设备之间传输数据。下面是一些关于网线传输信号的详细信息: 1. 电信号传输 在以太网中,数据是…...
DeepSeek官方推荐的AI集成系统
DeepSeek模型虽然强大先进,但是模型相当于大脑,再聪明的大脑如果没有输入输出以及执行工具也白搭,所以需要有配套工具才能让模型发挥最大的作用。下面是一个典型AI Agent架构图,包含核心组件与数据流转关系: #mermaid-…...
el-select 添加icon
Element-ui-plus 新版本:Select 选择器 | Element Plus 要实现如上的效果 ,要用到具名插槽 prefix,看代码: <template><el-dialog ref"dialogRef" v-model"dialogVisible" :title"title"…...
Qt的QPushButton样式设置
在Qt中,可以通过样式表(QSS)为QPushButton设置丰富的样式。以下是常见样式设置方法的详细说明: 1. 基础样式 // 设置背景色、文字颜色、圆角边框 button->setStyleSheet("QPushButton {"" background-color…...
Java函数计算冷启动从8s到800ms的优化实录
在函数计算场景中,冷启动性能对用户体验至关重要。本文将分享如何将 Java 函数计算的冷启动时间从 8 秒优化到 800 毫秒,包括具体的技术手段和代码示例。 一、背景介绍 函数计算是一种事件驱动的计算服务,用户只需上传代码,无需管理服务器。但在实际使用中,函数计算的冷…...
通过例子学 rust 个人精简版 1-1
1-1 Hello World fn main() {println!("Hello World!");// 动手试一试println!("Im a Rustacean!"); }Hello World! Im a Rustacean!要点1 :println 自带换行符 注释 fn main() {let x 5 /* 90 */ 5;println!("Is x 10 or 100? x …...
STM32、GD32驱动TM1640原理图、源码分享
一、原理图分享 二、源码分享 /************************************************* * copyright: * author:Xupeng * date:2024-07-18 * description: **************************************************/ #include "smg.h"#define DBG_TAG "smg&…...
Centos安装php-8.0.24.tar
查看系统环境 cat /etc/redhat-release 预先安装必要的依赖 yum install -y \ wget \ gcc \ gcc-c \ autoconf \ automake \ libtool \ make \ libxml2 \ libxml2-devel \ openssl \ openssl-devel \ sqlite-devel yum update 1、下载解压 cd /data/ wget https:/…...
VNC远程控制Mac
前言 macOS系统自带有VNC远程桌面,我们可以在控制端上安装配置VNC客户端,以此来实现远程控制macOS。但通常需要在不同网络下进行远程控制,为此,我们可以在macOS被控端上使用cpolar做内网穿透,映射VNC默认端口5…...
基于大数据的北京市天气数据分析系统的设计与实现
【Flask】基于Flask的北京市天气数据分析系统的设计与实现(完整系统源码开发笔记详细部署教程)✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 该系统采用Python和Flask框架,结合Pandas、NumPy等数据处理库及Echarts进…...
20250214在ubuntu20.04下使用obs studio录制外挂的1080p的USB摄像头【下载安装】
20250214在ubuntu20.04下使用obs studio录制外挂的1080p的USB摄像头 2025/2/14 9:10 缘起:笔记本电脑在ubuntu20.04下使用Guvcview录制自带的摄像头,各种问题。 1、降帧率。WIN10/11自带的相机应用可以满速30fps,马上重启到ubuntu20.04&#…...
OpenEuler学习笔记(三十):在OpenEuler上搭建3D建模环境
在OpenEuler上搭建3D建模环境,通常可以选择一些常见的3D建模软件,如Blender、FreeCAD等。以下以搭建Blender和FreeCAD这两款软件的使用环境为例,为你详细介绍搭建步骤。 搭建Blender 3D建模环境 1. 更新系统软件包 首先,确保系…...
Deepseek R1模型本地化部署+API接口调用详细教程:释放AI生产力
文章目录 前言一、deepseek R1模型与chatGPT o1系列模型对比二、本地部署步骤1.安装ollama2部署DeepSeek R1模型删除已存在模型,以7b模型为例 三、DeepSeek API接口调用Cline配置 前言 随着最近人工智能 DeepSeek 的爆火,越来越多的技术大佬们开始关注如…...
Ubuntu添加桌面快捷方式
以idea为例 一. 背景 在ubuntu中,很多时候是自己解压的文件并没有桌面快捷方式,需要自己找到对应的目录的执行文件手动打开,很麻烦 而只需要在 /usr/share/applications 中创建自定义的desktop文件就能自动复制到桌面 二. 添加方法 创建desk…...
教程:使用 Vue 3 和 arco 实现表格合并
1. 功能概述 本教程将介绍如何使用 Vue 3 和 arco 组件库实现表格合并功能。具体来说,我们会根据表格数据中的某个字段(如 type)对表格的某一列(如入库类型列)进行合并,同时将质检说明列合并为一列。 2. …...
【MySQL数据库】Ubuntu下的mysql
目录 1,安装mysql数据库 2,mysql默认安装路径 3,my.cnf配置文件? 4,mysql运用的相关指令及说明 5,数据库、表的备份和恢复 mysql是一套给我们提供数据存取的,更加有利于管理数据的服务的网络程序。下…...
Java实现MinIO上传PDF文件并配置浏览器在线打开而非下载
在Minio中上传PDF文件后,通常文件的访问方式(即URL)是配置为允许下载文件的,因为大多数Web服务器和存储服务默认将PDF文件视为应下载的内容类型(Content-Type: application/pdf)。但是,如果你想…...
CSV格式和普通EXCEL格式文件的区别
CSV 文件(.csv) 普通的 Excel 文件(.xlsx 或 .xls) 主要体现在 文件格式、数据存储、功能支持 等方面: 文件格式 比较项CSV 文件 (.csv)Excel 文件 (.xlsx/.xls)文件类型纯文本文件二进制或 XML 格式数据分隔逗号(,)…...
安卓基础(持续更新的笔记)
为什么要这样: // 创建请求体RequestBody body RequestBody.create(MediaType.parse("application/json; charsetutf-8"),jsonObject.toString()); jsonObject 就包含了一个 JSON 数据,它其实就是: {"name": "张…...
大模型Deepseek的使用_基于阿里云百炼和Chatbox
目录 前言1. 云服务商2. ChatBox参考 前言 上篇博文中探索了(本地)部署大语言模型,适合微调、数据高隐私性等场景。随着Deepseek-R1的发布,大语言模型的可及性得到极大提升,应用场景不断增加,对高可用的方…...
数学建模基础训练-1:概念解析
文章目录 数学建模基础训练-1:概念解析问题一:如何找到“概念”?问题二:如何全面理解概念的基础含义?问题三:如何深刻理解概念并作出创新点发掘?实际举例问题一 :研究并给出寒假开学某大学返校交…...
【mybatis】基本操作:详解Spring通过注解和XML的方式来操作mybatis
mybatis 的常用配置 配置数据库连接 #驱动类名称 spring.datasource.driver-class-namecom.mysql.cj.jdbc.Driver #数据库连接的url spring.datasource.urljdbc:mysql://127.0.0.1:3306/mybatis_test characterEncodingutf8&useSSLfalse #连接数据库的名 spring.datasourc…...
联邦学习中的“参数聚合“机制详解:医疗数据隐私保护的技术实现路径
一、技术原理:参数聚合的数学本质 1.1 核心数学公式 联邦平均算法(FedAvg): \theta_{global}^{t1} \sum_{k1}^K \frac{n_k}{N} \theta_k^t其中: K K K:参与本轮训练的客户端数量 n k n_k nkÿ…...
LVS 负载均衡集群(NAT模式)
一、环境准备 四台主机(一台 LVS、两台 RS、一台客户端) 注意每个虚拟机都需要关闭防火墙和 selinux 1.1.LVS 主机 LVS 主机(两块网卡) 第一块:NAT模式(内网) 第二块:添加网卡&am…...