嵌入式进阶——RTC时钟

news2024/9/22 17:34:01

🎬 秋野酱:《个人主页》
🔥 个人专栏:《Java专栏》《Python专栏》

⛺️心若有所向往,何惧道阻且长

文章目录

    • RTC时钟
    • 原理图
    • PCF8563寄存器
      • 控制与状态寄存器
    • 设备地址
    • I2C环境初始化
    • RTC寄存器数据读取
    • RTC寄存器数据写入
    • RTC闹钟设置
    • RTC定时器设置
    • 驱动封装
    • BCD(Binary-Coded Decimal)
    • 一些状态分析
    • 有源晶振和无源晶振

RTC时钟

RTC时钟是一种实时时钟芯片,通常与微控制器或计算机等设备配合使用,提供高精度的时间和日期信息,以便于设备进行时间相关的操作,如记录数据、定时执行任务、闹钟提醒等。
RTC时钟的应用场景非常广泛,例如计算机主板、智能家居、物联网设备、工业自动化等领域。在这些应用中,RTC时钟可以提供高精度的时间戳、定时任务、日历功能等,从而为系统提供更加可靠的时间基准。
除了时间和日期信息,一些RTC时钟芯片还集成了温度传感器、电池备份等功能,以提供更加全面的服务。例如,在断电情况下,RTC时钟的备用电池可以维持时钟的运行,以保证时间和日期信息的准确性。
以下是几种常见的RTC时钟芯片及其特点和应用场景:

  1. DS1302:DS1302是一款低功耗时钟模块,集成了时钟、日历和时钟报警功能,能够以BCD格式存储时间和日期信息。它具有低功耗、简单易用、成本低等特点,适用于需要长时间运行且功耗要求较低的应用场景。
  2. DS3231:DS3231是一款高精度的I2C RTC时钟芯片,能够以二进制格式存储时间和日期信息,并具有时钟报警、温度补偿等功能。它具有高精度、低功耗、高可靠性等特点,适用于对时钟精度要求较高的应用场景,如电子钟、精密计时器等。
  3. PCF8563:PCF8563是一款低功耗的I2C RTC时钟芯片,能够以BCD格式存储时间和日期信息,并具有时钟报警、时钟输出等功能。它具有低功耗、集成度高、工作稳定等特点,适用于需要长时间运行且功耗要求较低的应用场景。
  4. RV-4162-C7:RV-4162-C7是一款高精度的I2C RTC时钟芯片,能够以二进制格式存储时间和日期信息,并具有时钟输出、时钟同步、时钟校准等功能。它具有高精度、低功耗、抗干扰能力强等特点,适用于对时钟精度要求较高的应用场景,如高精度计时器、高精度工控系统等。
  5. MCP7940N:MCP7940N是一款低功耗的I2C RTC时钟芯片,能够以BCD格式存储时间和日期信息,并具有时钟输出、时钟同步、时钟报警等功能。它具有低功耗、成本低等特点,适用于需要长时间运行且功耗要求较低的应用场景,如电子钟、自动售货机等。
    我们开发板中采用的是PCF8563

原理图

在这里插入图片描述

在这里插入图片描述
原理图外围设计:

  1. 外部电池: 确保断电后能正常工作
  2. 晶振:确保震荡频率准确。
  3. 肖特基二极管:防止电流倒灌。
    引脚说明:
  4. INT: 中断引脚。当触发到定时任务时,会触发引脚高低电平变化。
  5. SCL和SDA:为I2C通讯的两个引脚。用来保证MCU和RTC时钟芯片间进行通讯的。

PCF8563寄存器

在这里插入图片描述

控制与状态寄存器

用来配置控制和状态切换的寄存器。
在这里插入图片描述
在这里插入图片描述

设备地址

// 设备地址
#define		PCF8563_ADDR  0x51 << 1
// 存储地址:时间的存储地址开始位置
#define		PCF8563_REG_TD   0x02

I2C环境初始化

#include "Config.h"
#include "GPIO.h"
#include "Delay.h"

#include "I2C.h"
#include "UART.h"
#include "NVIC.h"
#include "Switch.h"
/***

1. 初始化IO口,将P32,P33初始化开漏OD模式
2. 初始化I2C协议 \ UART
		EAXSFR();
		EA = 1

3. 通过I2C读取RTC时钟芯片数据
4. 通过I2C给RTC时钟芯片写数据
***/

void GPIO_config() {
    P3_MODE_OUT_OD(GPIO_Pin_2 | GPIO_Pin_3);
}

void UART_config(void) {
    // >>> 记得添加 NVIC.c, UART.c, UART_Isr.c <<<
    COMx_InitDefine		COMx_InitStructure;					//结构定义
    COMx_InitStructure.UART_Mode      = UART_8bit_BRTx;	//模式, UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTx
    COMx_InitStructure.UART_BRT_Use   = BRT_Timer1;			//选择波特率发生器, BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)
    COMx_InitStructure.UART_BaudRate  = 115200ul;			//波特率, 一般 110 ~ 115200
    COMx_InitStructure.UART_RxEnable  = ENABLE;				//接收允许,   ENABLE或DISABLE
    COMx_InitStructure.BaudRateDouble = DISABLE;			//波特率加倍, ENABLE或DISABLE
    UART_Configuration(UART1, &COMx_InitStructure);		//初始化串口1 UART1,UART2,UART3,UART4

    NVIC_UART1_Init(ENABLE,Priority_1);		//中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
    UART1_SW(UART1_SW_P30_P31);		// 引脚选择, UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17,UART1_SW_P43_P44
}
/****************  I2C初始化函数 *****************/
void	I2C_config(void)
{
    I2C_InitTypeDef		I2C_InitStructure;

    I2C_InitStructure.I2C_Mode      = I2C_Mode_Master;	//主从选择   I2C_Mode_Master, I2C_Mode_Slave
    I2C_InitStructure.I2C_Enable    = ENABLE;						//I2C功能使能,   ENABLE, DISABLE
    I2C_InitStructure.I2C_MS_WDTA   = DISABLE;					//主机使能自动发送,  ENABLE, DISABLE
    I2C_InitStructure.I2C_Speed     = 13;								//总线速度=Fosc/2/(Speed*2+4),      0~63
    // 400K = 24M / 2 / (Speed * 2 + 4):
    // 400  = 12000 / (Speed * 2 + 4)
    // Speed * 2   = 26
    I2C_Init(&I2C_InitStructure);
    NVIC_I2C_Init(I2C_Mode_Master,DISABLE,Priority_0);	//主从模式, I2C_Mode_Master, I2C_Mode_Slave; 中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3

    I2C_SW(I2C_P33_P32);					//I2C_P14_P15,I2C_P24_P25,I2C_P33_P32
}

#define NUMBER	7

void main() {
    // 设备地址 read A3h and write A2h
    u8 dev_addr = 0x51 << 1; 	// (设备地址 << 1) | 0 = 写地址. 
    // 存储地址
    u8 mem_addr = 0x02;
    // 用于接收从机传来的数据
    u8 p[NUMBER];
	// 保存时间信息
    u8 second, minute, hour, day, week, month;
    u16 year;

    // 开启扩展寄存器使能
    EAXSFR();

    GPIO_config();
    UART_config();
    I2C_config();

    EA = 1;

//		4. 通过I2C给RTC时钟芯片写数据
//	void I2C_WriteNbyte(u8 dev_addr, u8 mem_addr, u8 *p, u8 number);

    printf("--------------------------------read\n");
    while(1) {

		//		3. 通过I2C读取RTC时钟芯片数据
        I2C_ReadNbyte(dev_addr, mem_addr, &p, NUMBER);
    
        printf("%d:%d:%d \n", (int)hour, (int)minute, (int)second);
    
        delay_ms(250);
        delay_ms(250);
        delay_ms(250);
        delay_ms(250);
    }
}

RTC寄存器数据读取

I2C_ReadNbyte(PCF8563_ADDR, 0x02, dat, 7);
second = (dat[0] & 0x0F) + ((dat[0] >> 4) & 0x07) * 10;
minute = (dat[1] & 0x0F) + ((dat[1] >> 4) & 0x07) * 10;
hour = (dat[2] & 0x0F) + ((dat[2] >> 4) & 0x03) * 10;
day = (dat[3] & 0x0F) + ((dat[3] >> 4) & 0x03) * 10;
weekday = dat[4] & 0x07;
month = (dat[5] & 0x0F) + ((dat[5] >> 4) & 0x01) * 10;
year = ((dat[6] >> 4) & 0x0F) * 10 + (dat[6] & 0x0F);
year += ((dat[5] >> 7) & 0x01) * 100 + 1900;		

RTC寄存器数据写入

year = 2023;
month = 12;
day = 31;
weekday = 0;
hour = 23;
minute = 59;
second = 50;
if(year >= 2100) {
    c = 1;
}
tmp[0] = ((second / 10) << 4) + (second % 10);
tmp[1] = ((minute / 10) << 4) + (minute % 10);
tmp[2] = ((hour / 10) << 4) + (hour % 10);
tmp[3] = ((day / 10) << 4) + (day % 10);
tmp[4] = weekday % 7;
tmp[5] = (c << 7) + ((month / 10) << 4) + (month % 10);
tmp[6] = (u8)(((year % 1000) / 10) << 4) + (u8)((year % 1000) % 10);
I2C_WriteNbyte(PCF8563_ADDR, 0x02, tmp, 7);	

RTC闹钟设置

通过配置寄存器来配置闹钟

u8 config;
// 先读配置
I2C_ReadNbyte(PCF8563_ADDR, 0x01, &config, 1);
// 再去设置, 设置的时候别动别人的配置
config |= 0x02;
config &= ~0x08;//clear clock标记
I2C_WriteNbyte(PCF8563_ADDR, 0x01, &config, 1);
void ext_int3_call(void) {
	u8 tmp[7];
	u16 year;
	u8 month, day, weekday, hour, minute, second, c = 0;
	u8 config[1] = {0};
	printf("alarm \r\n");
	
	// 读取状态
	I2C_ReadNbyte(PCF8563_ADDR, 0x01, config, 1);
	printf("config: %d\r\n", (int)config[0]);
	
	// 判断闹钟是否被激活
	if((config[0] >> 3) & 0x01 == 1) {
		//清除 alarm 标记
		config[0] &= ~0x08;
		I2C_WriteNbyte(RTC_ADDR, 0x01, config, 1);
		
		I2C_ReadNbyte(RTC_ADDR, 0x01, config, 1);
		printf("config: %d\r\n", (int)config[0]);
	}
}

RTC定时器设置

通过配置寄存器来配置定时器。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

u8 config;
// 先读配置
I2C_ReadNbyte(PCF8563_ADDR, 0x01, &config, 1);
// 再去设置, 设置的时候别动别人的配置
config |= 0x01;
config &= ~0x04;//clear timer标记
I2C_WriteNbyte(PCF8563_ADDR, 0x01, &config, 1);
u8 config[1] = {0};
	
I2C_ReadNbyte(PCF8563_ADDR, 0x01, config, 1);
printf("config: %d\r\n", (int)config[0]);
if((config[0] >> 2) & 0x01 == 1) {
    printf("timer \r\n");
	config[0] &= ~0x04;
	I2C_WriteNbyte(PCF8563_ADDR, 0x01, config, 1);
}

驱动封装

头文件封装

#ifndef __PCF8563_H__
#define __PCF8563_H__

#include "config.h"
#include "I2C.h"

#define PCF8563_SCL			P32
#define PCF8563_SDA			P33
#define PCF8563_INT			P37
#define PCF8563_ADDR		0x51 << 1
#define PCF8563_ADDR_W		0xA2
#define PCF8563_ADDR_R		0xA3

#define PCF8563_SCL_INIT()	{P3M1 |= 0x04, P3M0 |= 0x04;}
#define PCF8563_SDA_INIT()	{P3M1 |= 0x08, P3M0 |= 0x08;}
#define PCF8563_INT_INIT()	{P3M1 &= ~0x80, P3M0 &= ~0x80;}

//u16 year;
//u8 month, day, weekday, hour, minute, second
// 定义clock
typedef struct {
	u16 year;
	u8 month;
	u8 day;
	u8 weekday;
	u8 hour;
	u8 minute;
	u8 second;
} Clock_t;

//定义alarm
typedef struct {
	u8 hour;
	u8 enableHour;
	u8 minute;
	u8 enableMinute;
	u8 day;
	u8 enableDay;
	u8 weekday;
	u8 enableWeekday;
} Alarm_t;

// 国产芯片的HZ1有问题,不要使用,建议使用HZ64
enum TimerFreq{ HZ4096 = 0, HZ64 = 1, HZ1 = 2, HZ1_60 = 3};

extern void PCF8563_on_alarm(void); 
extern void PCF8563_on_timer(void); 
	
void PCF8563_init(void);
void PCF8563_get_clock(Clock_t *c);
void PCF8563_set_clock(Clock_t c);

void PCF8563_enable_alarm();
void PCF8563_set_alarm(Alarm_t a);
void PCF8563_disable_alarm();

void PCF8563_enable_timer();
void PCF8563_set_timer(enum TimerFreq freq, u8 period);
void PCF8563_disable_timer();

#endif

● 定义结构体Clock_t表示时间数据,通过这个结构体承载数据,方便读取和设置。
● 定义结构体Alarm_t表示闹钟数据,通过这个结构体承载数据,方便读取和设置。
● 定义枚举TimerFreq限定计时器设置的范围。

#include "PCF8563.h"
#include <stdio.h>


void PCF8563_init(void) {
	PCF8563_SCL_INIT();
	PCF8563_SDA_INIT();
	PCF8563_INT_INIT();
}

void PCF8563_get_clock(Clock_t *c) {
	u8 dat[7];
	I2C_ReadNbyte(PCF8563_ADDR, 0x02, dat, 7);
	c->second  = (dat[0] & 0x0F) + ((dat[0] >> 4) & 0x07) * 10;
	c->minute  = (dat[1] & 0x0F) + ((dat[1] >> 4) & 0x07) * 10;
	c->hour    = (dat[2] & 0x0F) + ((dat[2] >> 4) & 0x03) * 10;
	c->day 	   = (dat[3] & 0x0F) + ((dat[3] >> 4) & 0x03) * 10;
	c->weekday =  dat[4] & 0x07;
	c->month   = (dat[5] & 0x0F) + ((dat[5] >> 4) & 0x01) * 10;
	c->year    = ((dat[6] >> 4) & 0x0F) * 10 + (dat[6] & 0x0F);
	c->year   += ((dat[5] >> 7) & 0x01) * 100 + 1900;
}

void PCF8563_set_clock(Clock_t clk) {
	u8 tmp[7];
	u8 c = 0;
	if(clk.year >= 2000) {
		c = 1;
	}
	tmp[0] = ((clk.second / 10) << 4) + (clk.second % 10);
	tmp[1] = ((clk.minute / 10) << 4) + (clk.minute % 10);
	tmp[2] = ((clk.hour   / 10) << 4) + (clk.hour   % 10);
	tmp[3] = ((clk.day    / 10) << 4) + (clk.day    % 10);
	tmp[4] = clk.weekday % 7;
	tmp[5] = (c << 7) + ((clk.month / 10) << 4) + (clk.month % 10);
	tmp[6] = (u8)(((clk.year % 1000) / 10) << 4) + (u8)((clk.year % 1000) % 10);
	I2C_WriteNbyte(PCF8563_ADDR, 0x02, tmp, 7);
}

void PCF8563_enable_alarm() {
	u8 config;
	// 先读配置
	I2C_ReadNbyte(PCF8563_ADDR, 0x01, &config, 1);
	// 再去设置, 设置的时候别动别人的配置
	config |= 0x02;
	config &= ~0x08;//clear clock标记
	I2C_WriteNbyte(PCF8563_ADDR, 0x01, &config, 1);
}

void PCF8563_set_alarm(Alarm_t a) {
	u8 tmp[4];
	tmp[0] = ((a.minute / 10) << 4) + (a.minute % 10);
	if(a.enableMinute == 0) {
		tmp[0] += (1 << 7);
	}
	tmp[1] = ((a.hour / 10) << 4) + (a.hour % 10);
	if(a.enableHour == 0) {
		tmp[1] += (1 << 7);
	}
	tmp[2] = ((a.day / 10) << 4) + (a.day % 10);
	if(a.enableDay == 0) {
		tmp[2] += (1 << 7);
	}
	tmp[3] = a.weekday % 7;
	if(a.enableWeekday == 0) {
		tmp[3] += (1 << 7);
	}
	I2C_WriteNbyte(PCF8563_ADDR, 0x09, tmp, 4);
}

void PCF8563_disable_alarm() {
	u8 config[1];
	// 先读配置
	I2C_ReadNbyte(PCF8563_ADDR, 0x01, config, 1);
	// 再去设置, 设置的时候别动别人的配置
	config[0] &= ~0x02;
	config[0] &= ~0x08;//clear clock标记
	I2C_WriteNbyte(PCF8563_ADDR, 0x01, config, 1);
}

void PCF8563_enable_timer() {
	u8 config;
	// 先读配置
	I2C_ReadNbyte(PCF8563_ADDR, 0x01, &config, 1);
	// 再去设置, 设置的时候别动别人的配置
	config |= 0x01;
	config &= ~0x04;//clear timer标记
	I2C_WriteNbyte(PCF8563_ADDR, 0x01, &config, 1);
}

void PCF8563_set_timer(enum TimerFreq freq, u8 period) {
	u8 config;
	config = freq + (1 << 7);//计数频率 + timer enable
	I2C_WriteNbyte(PCF8563_ADDR, 0x0E, &config, 1);
	
	config = period; // config, period
	I2C_WriteNbyte(PCF8563_ADDR, 0x0F, &config, 1);
}

void PCF8563_disable_timer() {
	u8 config[1];
	// 先读配置
	I2C_ReadNbyte(PCF8563_ADDR, 0x01, config, 1);
	// 再去设置, 设置的时候别动别人的配置
	config[0] &= ~0x01;
	config[0] &= ~0x04;//clear timer标记
	I2C_WriteNbyte(PCF8563_ADDR, 0x01, config, 1);
}

void Ext_INT3 (void) interrupt INT3_VECTOR
{
	u8 config[1];
	// 先读配置
	I2C_ReadNbyte(PCF8563_ADDR, 0x01, &config, 1);
 
	// 判断闹钟是否被激活 Alarm Flag && AIE
	if((config[0] & 0x08) && (config[0] & 0x02)) {
		//清除 alarm 标记
		config[0] &= ~0x08;
		I2C_WriteNbyte(PCF8563_ADDR, 0x01, config, 1);
		
		PCF8563_on_alarm();
	}
	// 判断计时器是否被激活 Timer Flag && TIE
	if((config[0] & 0x04) && (config[0] & 0x01)) {
		//清除 timer 标记
		config[0] &= ~0x04;
		I2C_WriteNbyte(PCF8563_ADDR, 0x01, config, 1);
		
		PCF8563_on_timer();
	}
}

● Ext_INT3中断函数为当前STC8H平台可用的。如果切换平台需要进行对应的移植操作。

BCD(Binary-Coded Decimal)

BCD(Binary-Coded Decimal)是一种用二进制编码表示十进制数字的格式。
在BCD格式中,每个十进制数位用4个二进制位来表示。BCD的目的是使得数字的编码与显示更加直观和容易处理。在BCD格式中,每个十进制数位的取值范围是0到9。
例如,数字5用BCD表示为0101,数字9用BCD表示为1001。这种表示方法使得每个十进制数位都独立地编码,方便在数字处理和显示设备上进行操作。
10进制数转BCD数:

// 十位取出左移4位 + 个位 (得到BCD数)
#define WRITE_BCD(val) 	((val / 10) << 4) + (val % 10)
// 将高4位乘以10 + 低四位 (得到10进制数)
#define READ_BCD(val) 	(val >> 4) * 10 + (val & 0x0F) 

一些状态分析

PCF8563的规则:

  1. 通电后,就开始工作,内部可配置寄存器(时间,闹钟,定时器)
  2. 如果已经有电池,但是单片机断电了,单片机重新通电后,单片机应该遵守PCF8563中已经配置的规则(时间,闹钟,定时器)

有源晶振和无源晶振

晶振可分为有源晶振与无源晶振。一般我们说的“晶振”指的是有源晶振,而无源晶振通常叫“晶体”,或者叫“谐振器”。两者最大的区别是:
● 有源晶振自身即可起振
● 无源晶振则需要外加专门的时钟电路才能起振
总体来看,有源晶振的精度、稳定度等方面均要好于无源晶振,尤其是在精密测量领域,大部分用的都是高档的有源晶振,以方便把各种补偿技术集成在一起,减少设计复杂性。
在这里插入图片描述

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

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

相关文章

Linux 使用 yum安装 ELK服务,yum 安装elasticsearch和Kibana(未写完)

文章目录 环境准备ELK组件介绍安装Elasticsearch安装Kibana 丢弃下载ELK 服务安装包Elasticsearch安装 Tips:关闭elasticsearch https 环境准备 ELK组件介绍 ElasticSearch &#xff1a; 是一个近实时&#xff08;NRT&#xff09;的分布式搜索和分析引擎&#xff0c;它可以用…

学术图表的基本配色方法

不论是商业图表还是专业图表&#xff0c;图表的配色都极其关键。图表配色主要有彩色和黑白两种配色方案。刘万祥老师曾提出&#xff1a; “在我看来&#xff0c;普通图表与专业图表的差别&#xff0c;很大程度就体现在颜色运用上。” 对于科学图表&#xff0c;大部分国内的期…

【Unity之FGUI】黑神章Fairy GUI控件详解

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;就业…

【MATLAB】基于VMD-SSA-GRU的回归预测模型

有意向获取代码&#xff0c;请转文末观看代码获取方式~ 1 基本定义 基于VMD-SSA-GRU的回归预测模型是一种集成了变分模态分解&#xff08;VMD&#xff09;、同步滑动平均&#xff08;SSA&#xff09;和门控循环单元&#xff08;GRU&#xff09;的复杂时间序列预测方法。下面将…

SaaS产品如何借助分销裂变实现爆发式增长?

在SaaS市场中&#xff0c;如何通过有效的推广方式实现产品的快速增长是每个企业都在思考的问题。分销裂变作为一种新兴的推广方式&#xff0c;以其低成本、高效率的特点&#xff0c;为SaaS产品的增长提供了新的可能。 一、分销裂变的基本原理 分销裂变是通过设置一定的奖励机…

一招搞定!家里灰尘多?教你如何轻松清理,推荐必备神器

在现代生活中&#xff0c;灰尘无处不在&#xff0c;特别是在大城市&#xff0c;空气中的污染物更多&#xff0c;导致家里的灰尘积聚速度加快。保持家居环境的干净和整洁不仅能提升生活质量&#xff0c;还能保护我们的健康。作为一名家电博主将为你提供详细的家里灰尘清理方法&a…

抖音里卖什么最赚钱?4个冷门的高利润商品,还有谁不知道!

哈喽~我的电商月月 做抖音小店的新手朋友&#xff0c;一定很想知道&#xff0c;在抖音里卖什么最赚钱&#xff1f; 很多人都会推荐&#xff0c;日常百货&#xff0c;小风扇&#xff0c;女装&#xff0c;宠物用品等等&#xff0c;这些商品确实很好做&#xff0c;你们可以试试 …

【跟着例子学MySQL】SQL进阶 -- 子查询和时间

文章目录 前言回顾子查询日期和时间未完待续 前言 举例子&#xff0c;是最简单有效的学习方法。本系列文章以一个贯穿始终的场景&#xff0c;结合多个实例讲解MySQL的基本用法。 ❔ 为什么要写这个系列&#xff1f; 模仿是最好的老师&#xff0c;实践是检验成果的方法。本系列…

c语言从入门到函数速成(完结篇)

哈喽&#xff0c;小伙伴们大家好呀&#xff0c;本篇文章是这个系列的完结篇&#xff0c;希望大家看完后能有所收获哦 首先能看到这里的同学&#xff0c;一定也是自觉性比较强的了&#xff0c;我会在文章末尾给大家发点小福利 那么&#xff0c;我们先来通过数学中的函数来引入一…

neo4j docker安装使用,py2neo python包使用

参考&#xff1a;https://neo4j.com/docs/operations-manual/current/docker/introduction/ 运行&#xff1a; docker run --publish7474:7474 --publish7687:7687 neo4j查看&#xff1a; http://192***ip:7474 username/password 都是 neo4j/neo4j 简单案例 创建例子&am…

融资融券操作指南(附最低费率开户渠道)

部分朋友在开通融资融券后&#xff0c;对于融资融券的操作不是很熟练&#xff0c;并且存在很多问题。其实&#xff0c;融资融券核心就是一个“借”&#xff0c;你借券商的资金或者股票&#xff0c;看多时借入资金买入&#xff0c;看空时借入券源卖出。你不可能空口白牙的去借&a…

使用Github Action发布python包到pypi.org

一、pypi中创建token 1. 浏览器中打开这个网址Log in PyPI 输入Token name&#xff0c;选择一个Scope&#xff0c;然后点击Create token 创建成功后&#xff0c;进入到如下页面&#xff1a; 点进Copy token&#xff0c;然后在新的标签页打开github 二、配置token到GitHub …

修改uniapp内置组件checkbox的样式

默认情况下 <view style"margin-bottom: 20rpx;"><label style"display: flex;align-items: center;width: fit-content;" click"handleCheck(cxm4s)"><checkbox /><text>车信盟出险4S维保</text></label>…

学习Uni-app开发小程序Day27

这一章学习了几个功能点&#xff0c;例如&#xff1a;try{}catch处理同步请求下载记录异常处理、onShareAppMessage分享好友和分享微信朋友圈、对分享页面传参进行特殊处理、共用分类列表页面实现我的下载和评分页面、使用mp-html富文本插件渲染公告详情页面 try{}catch处理同…

Java代码——@Mock注入失效,注入对象始终为null

现象&#xff1a; 最近在使用Mock对象做单元测试&#xff0c;但是发现mock的对象始终为null. 代码如下&#xff1a; package com.****.cache;import org.junit.jupiter.api.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.Mock…

基本Java语法和语义 (Reading 2)

&#xff08;1&#xff09;Java和C在变量类型命名和使用 基本数据类型 对象类型与引用类型 特殊类型 关键字和修饰符 &#xff08;2&#xff09;快照图&#xff1a; IDE调试工具: 许多IDE&#xff08;如Eclipse、IntelliJ IDEA&#xff09;提供了调试功能&#xff0c;可以…

新风向?——2DGS(2D高斯泼溅)横空出世

之前读完了3D高斯泼溅&#xff0c;收获颇丰&#xff0c;可没想到的是2D高斯泼溅也在三月份接踵而至。让我们一起解读一下&#xff01; 论文地址: 2D Gaussian Splatting for Geometrically Accurate Radiance Fields 代码地址: 2d-gaussian-splatting 一. 论文解读 Abstract …

Redis 可视化工具 RedisInsight 的保姆级安装以及使用(最新)

Redis 可视化工具 RedisInsight 的保姆级安装以及使用 一、下载 RedisInsight二、安装 RedisInsight三、使用 RedisInsight四、新建 Redis 连接 一、下载 RedisInsight 官网 https://redis.io/insight/填写基本信息之后点击 DOWNLOAD 二、安装 RedisInsight 双击安装包 点击下一…

Kubeadm Online Install Kubernetes v1.30.1

文章目录 简介架构预备条件资源规划 基础配置配置网卡配置 hosts安装常用软件配置互信安装 ansible配置 hosts关闭 swapselinux防火墙文件句柄数配置内核参数日志主机配置代理 安装 containerd方法1. 适用于rocky-8.9-x86_64-dvd1.iso方法2 适用于 rocky-8.9-x86_64-minimal.is…

ARM IHI0069F GIC architecture specification (8)

3.2中断旁路支持 CPU interface可以支持中断信号旁路&#xff0c;使得当接口发出的中断信号被禁用时&#xff0c;传统中断信号被传递到PE上的中断请求输入&#xff0c;从而绕过GIC功能。 是否支持旁路由实际设计决定。 用于确定是否使用GICv3 FIQ和IRQ输出或旁路信号的控制取决…