FRAM铁电存储器FM25W256 | FM24CL04B | FM24CL16B编程实现读写存取数据

本文主要是介绍FRAM铁电存储器FM25W256 | FM24CL04B | FM24CL16B编程实现读写存取数据,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


【本文发布于https://blog.csdn.net/Stack_/article/details/116353030,未经许可不得转载,转载须注明出处】


FM25W256


一、电路

在这里插入图片描述



二、配置SPI(GD32F303)

@ CSDN Tyrion.Mon
/*** @brief  初始化SPI1* @note   SPI1_NSS -- PB12*         SPI1_SCK -- PB13*         SPI1_MI  -- PB14*         SPI1_MO  -- PB15* @param  None* @retval None* @author PWH     @ CSDN Tyrion.Mon* @date   2021/3*/
void SPI1_Init(void)
{RCU->RCU_APB1EN.Bits.SPI1EN = 1;			///* SCK复用输出 */Gd32f30x_Gpio_Init(GPIO_PB13, GPIO_MODE_OUT_50MHZ, GPIO_CTL_AF_PP);/* MI上拉输入 */Gd32f30x_Gpio_Init(GPIO_PB14, GPIO_MODE_IN, GPIO_CTL_IPU);/* MO复用输出 */Gd32f30x_Gpio_Init(GPIO_PB15, GPIO_MODE_OUT_50MHZ, GPIO_CTL_AF_PP);/* SPI1 *///1:主机模式SPI1->SPI_CTL0.Bits.MSTMOD = 1;//0: 2 线单向传输模式SPI1->SPI_CTL0.Bits.BDEN = 0;//0:全双工模式(当 BDEN 清零时)SPI1->SPI_CTL0.Bits.RO = 0;//0: 8 位数据帧格式SPI1->SPI_CTL0.Bits.FF16 = 0;//1: NSS 软件模式, NSS 电平取决于 SWNSS 位SPI1->SPI_CTL0.Bits.SWNSSEN = 1;SPI1->SPI_CTL0.Bits.SWNSS = 1;//SPI1时钟来源:APB1   psc=001 : 4分频  FRAM spi最高20MSPI1->SPI_CTL0.Bits.PSC = 1;//0:先发送最高有效位SPI1->SPI_CTL0.Bits.LF = 0;//1: SPI 为空闲状态时, CLK 引脚拉低,此时fram spi工作在mode0SPI1->SPI_CTL0.Bits.CKPL = 0;//0:在第一个时钟跳变沿采集第一个数据SPI1->SPI_CTL0.Bits.CKPH = 0;//1: RBNE 中断使能。当 RBNE 置位时,产生中断。
//	SPI1->SPI_CTL1.Bits.RBNEIE = 1;//1: SPI 设备使能SPI1->SPI_CTL0.Bits.SPIEN = 1;
}



三、命令字

在这里插入图片描述

所有写操作前都必须先发送WREN以使能写操作。

@ CSDN Tyrion.Mon
/*** @brief  使能/使能写操作* @note   * @param  ENABLE 允许;DISABLE 禁止* @retval None* @author PWH @ CSDN Tyrion.Mon* @date   2021/3*/
static void FRAM_WriteEnable(uint8_t EN_DISEN)
{FRAM_Select(CS_ENABLE);if (EN_DISEN == ENABLE)SPIx_SendData(SPI1, WREN);	//使能写操作(WREN操作码使WEL置位,允许写操作)elseSPIx_SendData(SPI1, WRDI);FRAM_Select(CS_DISABLE);
}



四、读写

读写状态寄存器

@ CSDN Tyrion.Mon
/*** @brief  读状态寄存器数据* @note   * @param  NONE* @retval 状态寄存器值 * @author PWH@ CSDN Tyrion.Mon* @date   2021/3*/
static uint8_t FRAM_ReadSR(void)
{uint8_t ret;FRAM_Select(CS_ENABLE);SPIx_SendData(SPI1, RDSR);ret = SPIx_SendData(SPI1, 0x00);FRAM_Select(CS_DISABLE);return ret;
}/*** @brief  写状态寄存器* @note   * @param  状态寄存器值* @retval NONE* @author PWH @ CSDN Tyrion.Mon* @date   2021/3*/
static void FRAM_WriteSR(uint8_t val)
{FRAM_WriteEnable(ENABLE);	//写SR前需要使能写操作FRAM_Select(CS_ENABLE);SPIx_SendData(SPI1, WRSR);SPIx_SendData(SPI1, val);FRAM_Select(CS_DISABLE);
}

读写存储块

/*** @brief  FRAM* @note   * @param  None* @retval None* @author PWH@ CSDN Tyrion.Mon* @date   2021/3*/
uint16_t FRAM_Write(uint16_t AddrOffset, uint8_t *Data, uint16_t DataLen)
{if ((!DataLen) || (AddrOffset > FRAM_ADDR_MAX) || ((AddrOffset + DataLen - 1) > FRAM_ADDR_MAX))return 0;FRAM_WriteSR(0x80);			//写SR寄存器,所有存储块取消写保护FRAM_WriteEnable(ENABLE);	//写存储块前需要使能写操作FRAM_Select(CS_ENABLE);SPIx_SendData(SPI1, WRITE);								//写指令SPIx_SendData(SPI1, (AddrOffset >> 8) & 0x00ff);		//写入起始地址高字节SPIx_SendData(SPI1, AddrOffset & 0x00ff);				//写入起始地址低字节do {SPIx_SendData(SPI1, *Data++);} while (--DataLen);FRAM_Select(CS_DISABLE);FRAM_WriteSR(0x8C);			//写SR寄存器,所有存储块使能写保护return 1;
}/*** @brief  FRAM* @note   * @param  None* @retval Noned* @author PWH @ CSDN Tyrion.Mon* @date   2021/3*/
uint16_t FRAM_Read(uint16_t AddrOffset, uint8_t *Data, uint16_t DataLen)
{if ((!DataLen) || (AddrOffset > FRAM_ADDR_MAX) || ((AddrOffset + DataLen - 1) > FRAM_ADDR_MAX))return 0;FRAM_Select(CS_ENABLE);SPIx_SendData(SPI1, READ);								//读指令SPIx_SendData(SPI1, (AddrOffset >> 8) & 0x00ff);		//写入起始地址高字节SPIx_SendData(SPI1, AddrOffset & 0x00ff);				//写入起始地址低字节do {*Data++ = SPIx_SendData(SPI1, 0x00);} while (--DataLen);FRAM_Select(CS_DISABLE);return 1;
}




FM24CL04B/FM24CL16B


一、电路


在这里插入图片描述

/** FM24CL04B* 1    0    1    0    A2    A1    A0    R/W** A2 A1 已硬件拉低, A0作页选择** FM24CL16B* 1    0    1    0    A2    A1    A0    R/W** 外部无地址选择引脚,A2 A1 A0作页选择**/

二、I2C驱动 (软 – ESP8266)

@ CSDN Tyrion.Mon#define I2C_MASTER_SCL_PIN			GPIO_Pin_5
#define I2C_MASTER_SCL_NUM			GPIO_NUM_5
#define I2C_MASTER_SCL_MODE			GPIO_MODE_OUTPUT_OD#define I2C_MASTER_SDA_PIN			GPIO_Pin_4
#define I2C_MASTER_SDA_NUM			GPIO_NUM_4
#define I2C_MASTER_SDA_MODE			GPIO_MODE_OUTPUT_OD#define I2C_MASTER_SCL_CLR() 		gpio_set_level(I2C_MASTER_SCL_NUM, 0)//i2c scl
#define I2C_MASTER_SCL_SET() 		gpio_set_level(I2C_MASTER_SCL_NUM, 1)#define I2C_MASTER_SDA_CLR() 		gpio_set_level(I2C_MASTER_SDA_NUM, 0)//i2c sda
#define I2C_MASTER_SDA_SET() 		gpio_set_level(I2C_MASTER_SDA_NUM, 1)//延时
void I2C_Master_delay(void)
{uint8_t t = 1;while (t--);
}
//SDA配置为输出
void I2C_Master_SDA_PIN_OUTPUT(void)
{
#if 0gpio_config_t gpio_cfg = {.pin_bit_mask = I2C_MASTER_SDA_PIN,.mode = GPIO_MODE_OUTPUT_OD,.pull_up_en = 0,.pull_down_en = 0,.intr_type = GPIO_INTR_DISABLE,};gpio_config(&gpio_cfg);
#elsegpio_set_direction(I2C_MASTER_SDA_NUM, GPIO_MODE_OUTPUT_OD);
#endif
}
//SDA配置为输入
void I2C_Master_SDA_PIN_INPUT(void)
{
#if 0gpio_config_t gpio_cfg = {.pin_bit_mask = I2C_MASTER_SDA_PIN,.mode = GPIO_MODE_INPUT,.pull_up_en = 0,.pull_down_en = 0,.intr_type = GPIO_INTR_DISABLE,};gpio_config(&gpio_cfg);
#elsegpio_set_direction(I2C_MASTER_SDA_NUM, GPIO_MODE_INPUT);
#endif
}
//读取SDA输入电平
uint8_t I2C_Master_SDA_PIN_GET(void)
{return gpio_get_level(I2C_MASTER_SDA_NUM);
}
//起始信号
void I2C_Master_Start(void)
{I2C_Master_SDA_PIN_OUTPUT();I2C_MASTER_SDA_SET();I2C_MASTER_SCL_SET();I2C_Master_delay();I2C_MASTER_SDA_CLR();I2C_Master_delay();I2C_MASTER_SCL_CLR();I2C_Master_delay();
}
//结束信号
void I2C_Master_Stop(void)
{I2C_Master_SDA_PIN_OUTPUT();I2C_MASTER_SDA_CLR();I2C_MASTER_SCL_SET();I2C_Master_delay();I2C_MASTER_SDA_SET();
}
//发送ack
void I2C_Master_Ack(void)
{I2C_Master_SDA_PIN_OUTPUT();I2C_MASTER_SDA_CLR();I2C_MASTER_SCL_SET();I2C_Master_delay();I2C_MASTER_SCL_CLR();I2C_Master_delay();
}
//发送nack
void I2C_Master_NAck(void)
{I2C_Master_SDA_PIN_OUTPUT();I2C_MASTER_SDA_SET();I2C_MASTER_SCL_SET();I2C_Master_delay();I2C_MASTER_SCL_CLR();I2C_Master_delay();
}
//等待信号响应
uint8_t I2C_Master_WaitAck(void) //测数据信号的电平
{uint8_t ack;I2C_Master_SDA_PIN_INPUT();//I2C_MASTER_SDA_SET();//I2C_Master_delay();I2C_MASTER_SCL_SET();ack = I2C_Master_SDA_PIN_GET();I2C_Master_delay();I2C_MASTER_SCL_CLR();I2C_Master_delay();return ack;
}
//写入一个字节
void I2C_Master_Send_Byte(uint8_t dat)
{uint8_t i;I2C_Master_SDA_PIN_OUTPUT();for(i = 0; i < 8; i++){if(dat & 0x80)//将dat的8位从最高位依次写入{I2C_MASTER_SDA_SET();}else{I2C_MASTER_SDA_CLR();}I2C_Master_delay();I2C_MASTER_SCL_SET();I2C_Master_delay();I2C_MASTER_SCL_CLR();//将时钟信号设置为低电平dat <<= 1;}
}
//写入一个字节
void I2C_Master_Send_1Byte(uint8_t slave_addr, uint8_t reg_address, uint8_t dat)
{I2C_Master_Start();I2C_Master_Send_Byte(slave_addr);I2C_Master_WaitAck();I2C_Master_Send_Byte(reg_address);I2C_Master_WaitAck();I2C_Master_Send_Byte(dat);I2C_Master_WaitAck();I2C_Master_Stop();
}
//写入n个字节
void I2C_Master_Send_Bytes(uint8_t slave_addr, uint8_t reg_address, uint8_t *dat, uint16_t len)
{uint16_t i = 0;I2C_Master_Start();I2C_Master_Send_Byte(slave_addr);I2C_Master_WaitAck();I2C_Master_Send_Byte(reg_address);I2C_Master_WaitAck();for (i = 0; i < len; i++){I2C_Master_Send_Byte(dat[i++]);I2C_Master_WaitAck();}I2C_Master_Stop();
}
//读一个字节
void I2C_Master_Read_Byte(uint8_t *dat)
{uint8_t i;*dat = 0;I2C_Master_SDA_PIN_INPUT();for(i = 0; i < 8; i++){I2C_MASTER_SCL_SET();I2C_Master_delay();*dat <<= 1;if (I2C_Master_SDA_PIN_GET())*dat |= 0x01;I2C_MASTER_SCL_CLR();I2C_Master_delay();}
}
void I2C_Master_Init(void)
{gpio_config_t gpio_cfg;gpio_cfg.pin_bit_mask = I2C_MASTER_SCL_PIN | I2C_MASTER_SDA_PIN;gpio_cfg.mode = I2C_MASTER_SCL_MODE;gpio_cfg.pull_up_en = 0;gpio_cfg.pull_down_en = 0;gpio_cfg.intr_type = GPIO_INTR_DISABLE;gpio_config(&gpio_cfg);I2C_MASTER_SCL_SET();I2C_MASTER_SDA_SET();
}
#define FRAM_FM24CL04B						0	//4K bit / 512字节
#define FRAM_FM24CL16B						1	//16K bit / 2K字节#define FRAM_FM24CLxx						FRAM_FM24CL16B#define FRAM_I2C_ADDR						0xA0
#if (FRAM_FM24CLxx == FRAM_FM24CL04B)	//2pages x 256bytes#define FRAM_PAGE_MAX						2#define FRAM_PAGE_BYTES_MAX					256#define FRAM_DATA_ADDR_END					0x1FF
#elif (FRAM_FM24CLxx == FRAM_FM24CL16B)	//8pages x 256bytes#define FRAM_PAGE_MAX						8#define FRAM_PAGE_BYTES_MAX					256#define FRAM_DATA_ADDR_END					0x7FF
#endif/*** @名称: FRAM_WriteBytes* @描述: FM24CL04B 同一页写入多个字节	256字节x2页* @参数:* @参数:* @日期:2023* @返回: bool**/
bool FRAM_WriteBytes(uint8_t *pBytes, uint32_t framStartAddress, uint32_t dataLenght)
{uint8_t page;if (framStartAddress > FRAM_DATA_ADDR_END) return false;page = framStartAddress >> 8;if ((page + 1) > FRAM_PAGE_MAX) return false;I2C_Master_Start();I2C_Master_Send_Byte(FRAM_I2C_ADDR | ((page << 1) & 0x0E) | 0x00);I2C_Master_WaitAck();I2C_Master_Send_Byte(0xFF & framStartAddress);I2C_Master_WaitAck();for (uint32_t i = 0; i < dataLenght; i++){I2C_Master_Send_Byte(pBytes[i]);I2C_Master_WaitAck();}I2C_Master_Stop();return true;
}/*** @名称: FRAM_ReadBytes* @描述: FM24CL04B 同一页读多个字节	256字节x2页* @参数:* @参数:* @日期:2023* @返回: bool**/
bool FRAM_ReadBytes(uint8_t *pBytes, uint32_t framStartAddress, uint32_t dataLenght)
{uint8_t page;if (framStartAddress > FRAM_DATA_ADDR_END) return false;page = framStartAddress >> 8;if ((page + 1) > FRAM_PAGE_MAX) return false;I2C_Master_Start();I2C_Master_Send_Byte(FRAM_I2C_ADDR | ((page << 1) & 0x0E) | 0x00);I2C_Master_WaitAck();I2C_Master_Send_Byte(framStartAddress & 0xFF);I2C_Master_WaitAck();I2C_Master_Start();I2C_Master_Send_Byte(FRAM_I2C_ADDR | ((page << 1) & 0x0E) | 0x01);I2C_Master_WaitAck();do{I2C_Master_Read_Byte(pBytes);pBytes++;if (dataLenght == 1) {I2C_Master_NAck();}else {I2C_Master_Ack();}}while(--dataLenght);I2C_Master_Stop();return true;
}读写示例:
uint8_t datArray[10];
FRAM_WriteBytes(datArray, 0, sizeof(datArray));		//写page0第0-9
FRAM_WriteBytes(datArray, 256, sizeof(datArray));	//写page1第0-9
FRAM_WriteBytes(datArray, 512, sizeof(datArray));	//写page2第0-9FRAM_ReadBytes(datArray, 0, sizeof(datArray));		//读page0第0-9
FRAM_ReadBytes(datArray, 256, sizeof(datArray));	//读page1第0-9
FRAM_ReadBytes(datArray, 512, sizeof(datArray));	//读page2第0-9

三、I2C驱动 (硬 – STM32F103)


@ CSDN Tyrion.Mon
/*** @名称: FRAM_Init* @描述: FRAM IO初始化  i2c配置* @参数: * @参数: * @日期:2019* @返回: bool**/
bool FRAM_Init(void)
{I2C_InitTypeDef   I2C_InitStruct;GPIO_InitTypeDef  GPIO_InitStruct;RCC_APB2PeriphClockCmd(FRAM_GPIO_CLK,ENABLE);RCC_APB1PeriphClockCmd(FRAM_I2C_CLK, ENABLE);I2C_InitStruct.I2C_ClockSpeed = 100000;	I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;	//该参数只有在 I2C 工作在快速模式(时钟工作频率高于 100KHz)下才有意义。I2C_InitStruct.I2C_OwnAddress1 = 0x75;I2C_InitStruct.I2C_Ack = I2C_Ack_Enable; I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;I2C_Init(I2C1, &I2C_InitStruct);I2C_Cmd(FRAM_I2C, ENABLE);GPIO_InitStruct.GPIO_Pin =  FRAM_SCL_PIN | FRAM_SDA_PIN;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;               GPIO_Init(FRAM_GPIO, &GPIO_InitStruct);GPIO_SetBits(FRAM_GPIO, FRAM_SCL_PIN);GPIO_SetBits(FRAM_GPIO, FRAM_SDA_PIN);GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;               //先把GPIO设为推挽输出并拉倒高电平再转设为复用开漏输出,这样可以有效解决I2C设备死锁的问题???GPIO_Init(FRAM_GPIO, &GPIO_InitStruct);return true;
}
/*** @名称: FRAM_WriteBytes* @描述: FM24CL04B 同一页写入多个字节	256字节x2页* @参数: * @参数: * @日期:2019* @返回: bool**/
bool FRAM_WriteBytes(uint8_t framPage, uint8_t *pBytes, uint8_t framStartAddress, uint8_t dataLenght)
{if(framPage > 1 || !dataLenght) return false;if(framStartAddress + dataLenght > 256) return false;/* Send START condition */I2C_GenerateSTART(FRAM_I2C, ENABLE);/* Test on EV5 and clear it */while(I2C_CheckEvent(FRAM_I2C, I2C_EVENT_MASTER_MODE_SELECT) == ERROR);//EV5事件被检测到,发送设备地址I2C_Send7bitAddress(FRAM_I2C, 0xA0 | (FRAM_ADDRESS << 2) | (framPage << 1), I2C_Direction_Transmitter);/* Test on EV6 and clear it */while(I2C_CheckEvent(FRAM_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) == ERROR);//EV6事件被检测到,发送要操作的存储单元地址I2C_SendData (FRAM_I2C, framStartAddress);/* Test on EV8 and clear it */while(I2C_CheckEvent(FRAM_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) == ERROR);do{//EV8事件被检测到,发送要存储的数据I2C_SendData (FRAM_I2C, *pBytes++);/* Test on EV8 and clear it */while(I2C_CheckEvent(FRAM_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) == ERROR);}while(--dataLenght);/* Send STOP condition */I2C_GenerateSTOP(FRAM_I2C, ENABLE);return true;
}/*** @名称: FRAM_ReadBytes* @描述: FM24CL04B 同一页读多个字节	256字节x2页* @参数: * @参数: * @返回: bool**/
bool FRAM_ReadBytes(uint8_t framPage, uint8_t *pBytes, uint8_t framStartAddress, uint8_t dataLenght)
{if(framPage > 1 || !dataLenght) return false;if(framStartAddress + dataLenght > 256) return false;/* Send START condition */I2C_GenerateSTART(FRAM_I2C, ENABLE);/* Test on EV5 and clear it */while(I2C_CheckEvent(FRAM_I2C, I2C_EVENT_MASTER_MODE_SELECT) == ERROR);//EV5事件被检测到,发送设备地址I2C_Send7bitAddress(FRAM_I2C, 0xA0 | (FRAM_ADDRESS << 2) | (framPage << 1), I2C_Direction_Transmitter);/* Test on EV6 and clear it */while(I2C_CheckEvent(FRAM_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) == ERROR);//EV6事件被检测到,发送要操作的存储单元地址I2C_SendData (FRAM_I2C, framStartAddress);/* Test on EV8 and clear it */while(I2C_CheckEvent(FRAM_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) == ERROR);/* Send START condition */I2C_GenerateSTART(FRAM_I2C, ENABLE);/* Test on EV5 and clear it */while(I2C_CheckEvent(FRAM_I2C, I2C_EVENT_MASTER_MODE_SELECT) == ERROR);//EV5事件被检测到,发送设备地址I2C_Send7bitAddress(FRAM_I2C, 0xA0 | (FRAM_ADDRESS << 2) | (framPage << 1), I2C_Direction_Receiver);/* Test on EV6 and clear it */while(I2C_CheckEvent(FRAM_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED ) == ERROR);do{if(dataLenght == 1){I2C_AcknowledgeConfig (FRAM_I2C, DISABLE);}//EV7事件被检测到	while(I2C_CheckEvent(FRAM_I2C, I2C_EVENT_MASTER_BYTE_RECEIVED ) == ERROR);//EV8事件被检测到,发送要存储的数据*pBytes++ = I2C_ReceiveData (FRAM_I2C);}while(--dataLenght);/* Send STOP condition */I2C_GenerateSTOP(FRAM_I2C, ENABLE);I2C_AcknowledgeConfig (FRAM_I2C, ENABLE);return true;
}读写示例:
uint8_t FRAM_ENERGY_BANK[10];
FRAM_ReadBytes(0, FRAM_ENERGY_BANK, 0x00, 10);	//读page0第0-9个数据
FRAM_ReadBytes(1, FRAM_ENERGY_BANK, 0x00, 10);	//读page1第0-9个数据FRAM_WriteBytes(0, FRAM_ENERGY_BANK, 0x00, 10);	//写page0第0-9个数据
FRAM_WriteBytes(1, FRAM_ENERGY_BANK, 0x00, 10);	//写page1第0-9个数据

这篇关于FRAM铁电存储器FM25W256 | FM24CL04B | FM24CL16B编程实现读写存取数据的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/191932

相关文章

SpringBoot3实现Gzip压缩优化的技术指南

《SpringBoot3实现Gzip压缩优化的技术指南》随着Web应用的用户量和数据量增加,网络带宽和页面加载速度逐渐成为瓶颈,为了减少数据传输量,提高用户体验,我们可以使用Gzip压缩HTTP响应,... 目录1、简述2、配置2.1 添加依赖2.2 配置 Gzip 压缩3、服务端应用4、前端应用4.1 N

SpringBoot实现数据库读写分离的3种方法小结

《SpringBoot实现数据库读写分离的3种方法小结》为了提高系统的读写性能和可用性,读写分离是一种经典的数据库架构模式,在SpringBoot应用中,有多种方式可以实现数据库读写分离,本文将介绍三... 目录一、数据库读写分离概述二、方案一:基于AbstractRoutingDataSource实现动态

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整

揭秘Python Socket网络编程的7种硬核用法

《揭秘PythonSocket网络编程的7种硬核用法》Socket不仅能做聊天室,还能干一大堆硬核操作,这篇文章就带大家看看Python网络编程的7种超实用玩法,感兴趣的小伙伴可以跟随小编一起... 目录1.端口扫描器:探测开放端口2.简易 HTTP 服务器:10 秒搭个网页3.局域网游戏:多人联机对战4.

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co

使用Python实现快速搭建本地HTTP服务器

《使用Python实现快速搭建本地HTTP服务器》:本文主要介绍如何使用Python快速搭建本地HTTP服务器,轻松实现一键HTTP文件共享,同时结合二维码技术,让访问更简单,感兴趣的小伙伴可以了... 目录1. 概述2. 快速搭建 HTTP 文件共享服务2.1 核心思路2.2 代码实现2.3 代码解读3.

MySQL双主搭建+keepalived高可用的实现

《MySQL双主搭建+keepalived高可用的实现》本文主要介绍了MySQL双主搭建+keepalived高可用的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、测试环境准备二、主从搭建1.创建复制用户2.创建复制关系3.开启复制,确认复制是否成功4.同

Java实现文件图片的预览和下载功能

《Java实现文件图片的预览和下载功能》这篇文章主要为大家详细介绍了如何使用Java实现文件图片的预览和下载功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... Java实现文件(图片)的预览和下载 @ApiOperation("访问文件") @GetMapping("

Java并发编程必备之Synchronized关键字深入解析

《Java并发编程必备之Synchronized关键字深入解析》本文我们深入探索了Java中的Synchronized关键字,包括其互斥性和可重入性的特性,文章详细介绍了Synchronized的三种... 目录一、前言二、Synchronized关键字2.1 Synchronized的特性1. 互斥2.

使用Sentinel自定义返回和实现区分来源方式

《使用Sentinel自定义返回和实现区分来源方式》:本文主要介绍使用Sentinel自定义返回和实现区分来源方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Sentinel自定义返回和实现区分来源1. 自定义错误返回2. 实现区分来源总结Sentinel自定