EEPROM读写驱动程序
文章目录
- 前言
- 一、EEPROM_TypeDef
- 一、应答查询
- 二、初始化
- 三、写数据
- 1.写一个字节
- 2.页写
- 四、读数据
- 1.读一个字节
- 2.读多个数据
- 程序地址
- 软件IIC驱动地址
前言
EEPROM有多种型号,操作方式略有不同。
从图中可以看到24C04占用了A0寻址地址作为数据寻址地址,24C08和24C16也占用了器件地址作为数据寻址地址,而24C32、24C64、24C128、24C256则使用2个字节为数据寻址地址。
一、EEPROM_TypeDef
抽象出EERPOM的结构体,包括IIC接口、页大小、和启动传输的方式等。
typedef enum
{AT24C02 = 0,AT24C04,AT24C08,AT24C16,AT24C32 = 4,AT24C64,AT24C128,AT24C256 = 7,
} EEPROM_Type;typedef struct
{IIC_TypeDef IIC;//IIC接口EEPROM_Type Type;//EEPROM类型uint16_t PageSize;//页大小uint16_t PageCount;//页数uint16_t TotalCapacity;//总容量//因为EEPROM器件型号不同启动传输的操作也有所不同,所以使用的启动方式也有所不同,如AT24C04在启动一次传输时需要占用一个bit的器件地址做寻址地址uint8_t (*EEPROM_StartTransmission)(void* self, uint16_t address);
} EEPROM_TypeDef;
一、应答查询
很多EEPROM的驱动程序都是写入之后添加一个10ms的延时等待在下一次查询,但EEPROM的数据手册上都是推荐使用应答查询的机制,在使用过程中也发现写入的字节少时等待的时间也会减少,使用延时的方法会造成一定的性能损耗。
/** * @brief 判断EEPROM是否在忙状态,包含一个开始和发送设备地址的过程* @param EEPROM_TypeDef *pEEPROM* @param uint8_t devAdd 设备地址* @retval 0:不忙可以继续操作,1:忙禁止操作*/
static uint8_t EEPROM_IsBusy(EEPROM_TypeDef *const pEEPROM, uint8_t devAdd)
{for (uint8_t i = 0; i < EEPROM_BUSY_CNT; i++){IIC_Start(&pEEPROM->IIC);if(IIC_SendAndSack(&pEEPROM->IIC, devAdd) == 0){return 0;}if(i < EEPROM_BUSY_CNT - 1){IIC_Stop(&pEEPROM->IIC);Delay_ms(1);}}return 1;
}
二、初始化
在初始化时设置根据器件型号设置一些参数,页大小,寻址操作函数和总容量。
/** * @brief 寻址处理函数,支持AT24C02,AT24C04,AT24C08,AT24C16* @param void* self* @param uint16_t address* @retval: */
uint8_t AT24C0X_StartTransmission(void* self, uint16_t address)
{EEPROM_TypeDef* pEEPROM = self;uint8_t add = pEEPROM->IIC.ADD | ((address>>8) & ~(0xff << (uint8_t)pEEPROM->Type));if(EEPROM_IsBusy(pEEPROM, add))return 1;if (IIC_SendAndSack(&pEEPROM->IIC, address & 0xFF))return 2;return 0;
}/** * @brief 寻址处理函数,支持AT24C32,AT24C64,AT24C128,AT24C256* @param void* self* @param uint16_t address* @retval: */
uint8_t AT24CXX_StartTransmission(void* self, uint16_t address)
{IIC_TypeDef* IIC = self;if (EEPROM_IsBusy(self, IIC->ADD))return 1;if (IIC_SendAndSack(IIC, address >> 8))return 2;if (IIC_SendAndSack(IIC, address & 0xFF))return 3;return 0;
}/*** @brief 初始化EEPROM* @param EEPROM_TypeDef *pEEPROM* @param EEPROM_Type type EEPROM类型* @retval 0:成功,其他失败*/
uint8_t EEPROM_Init(EEPROM_TypeDef *const pEEPROM, EEPROM_Type type)
{IIC_Init(&pEEPROM->IIC);switch(type){case AT24C02:case AT24C04:case AT24C08:case AT24C16:pEEPROM->Type = type;if (type == AT24C02) pEEPROM->PageSize = 8;else pEEPROM->PageSize = 16;pEEPROM->EEPROM_StartTransmission = &AT24C0X_StartTransmission;break;case AT24C32:case AT24C64:case AT24C128:case AT24C256:pEEPROM->Type = type;if (type == AT24C256) pEEPROM->PageSize = 64;else pEEPROM->PageSize = 32;pEEPROM->EEPROM_StartTransmission = &AT24CXX_StartTransmission;break;default:return 2;}pEEPROM->TotalCapacity = 256;for (uint8_t i = 0; i < (uint8_t)type; i++){pEEPROM->TotalCapacity *= 2;}pEEPROM->PageCount = pEEPROM->TotalCapacity / pEEPROM->PageSize;return EEPROM_Check(pEEPROM);
}
三、写数据
1.写一个字节
/*** @brief 写入一个字节* @param EEPROM_TypeDef *pEEPROM* @param uint16_t address 写入地址* @param uint8_t dat 数据* @retval 0:成功,其他失败*/
uint8_t EEPROM_WriteByte(EEPROM_TypeDef *const pEEPROM, uint16_t address, uint8_t dat)
{uint8_t result = 0;if(pEEPROM->EEPROM_StartTransmission(pEEPROM, address)){result = 1;goto err;}// 发送数据if (IIC_SendAndSack(&pEEPROM->IIC, dat)){result = 2;}
err:IIC_Stop(&pEEPROM->IIC);return result;
}
2.页写
从图中可以看到页写为在写入一个字节后继续发送数据,并且需要进行页对齐,这里是使用递归来实现的。
/** * @brief: * @param EEPROM_TypeDef *pEEPROM* @param uint16_t address* @param uint8_t *memory* @param uint16_t size* @retval: */
uint8_t EEPROM_Write(EEPROM_TypeDef *const pEEPROM, uint16_t address, uint8_t *memory, uint16_t size)
{uint8_t result = 0;//开始一次IIC传输if(pEEPROM->EEPROM_StartTransmission(pEEPROM, address)){result = 1;goto err;}// 写入数据for (uint16_t i = 0; i < size; i++){if (IIC_SendAndSack(&pEEPROM->IIC, memory[i])){result = 2 + i;break;}// 结束if (i + 1 == size)break;//如果下一个地址是新页的开头结束本次传输if ((address + i + 1) % pEEPROM->PageSize == 0){IIC_Stop(&pEEPROM->IIC);//结束本页传输//递归操作剩下的数据return EEPROM_Write(pEEPROM, address + i + 1, memory + i + 1, size - i - 1);}}err:IIC_Stop(&pEEPROM->IIC);return result;
}
四、读数据
1.读一个字节
从图中可以看出在发送完操作地址之后会再次发送一个开始时序和一个器件地址然后才开始读取数据。
/** * @brief 读取一个字节* @param EEPROM_TypeDef *pEEPROM* @param uint16_t address* @param uint8_t* dat* @retval 0:成功,其他失败*/
uint8_t EEPROM_ReadByte(EEPROM_TypeDef *const pEEPROM, uint16_t address, uint8_t* dat)
{uint8_t result = 0;// 发送写设备地址if(pEEPROM->EEPROM_StartTransmission(pEEPROM, address)){result = 1;goto err;}// 重启IICIIC_Start(&pEEPROM->IIC);// 发送读设备地址if (IIC_SendReadAddress(&pEEPROM->IIC)){result = 2;goto err;}*dat = IIC_ReadAndAck(&pEEPROM->IIC, 0);err:IIC_Stop(&pEEPROM->IIC);return result;
}
2.读多个数据
读多个数据较为简单,不需要像写数据一样进行页对齐。
/** * @brief 读取数据* @param EEPROM_TypeDef *pEEPROM* @param uint16_t address* @param uint8_t *memory* @param uint16_t size* @retval 0:成功,其他失败*/
uint8_t EEPROM_Read(EEPROM_TypeDef *const pEEPROM, uint16_t address, uint8_t *memory, uint16_t size)
{uint8_t result = 0;// 发送写设备地址if(pEEPROM->EEPROM_StartTransmission(pEEPROM, address)){result = 1;goto err;}// 重启IICIIC_Start(&pEEPROM->IIC);// 发送读设备地址if (IIC_SendReadAddress(&pEEPROM->IIC)){result = 2;goto err;}IIC_Read(&pEEPROM->IIC, memory, size )err:IIC_Stop(&pEEPROM->IIC);return result;
}
程序地址
软件IIC驱动地址
EEPROM读写驱动程序相关推荐
- AT24C01/AT24C02系列EEPROM芯片单片机读写驱动程序
一.概述 EEPROM是嵌入式开发中比较常用的芯片,用来保存参数及掉电记忆的数据等,最常用的是ATMEL的AT24Cxx系列的IIC接口,也有其他厂家的如罗姆Rohm的BR24Gxx系列.ST的M24 ...
- STM8S103F2 EEPROM读写
/************ STM8S103 EEPROM读写 ******/ /*芯片型号:STM8S103F2PB6 */ /*功能描述: ...
- pic单片机c语言读eeprom,PIC16F877单片机内部EEPROM读写实例
;PIC16F877单片机内部EEPROM读写实例*************************************************************************** ...
- pic单片机c语言读eeprom,PIC单片机的EEPROM读写实例及说明
PIC单片机的EEPROM读写实例及说明 来源:luchaohai 作者:华仔 浏览:1397 时间:2016-08-10 14:18 标签: 摘要: ; PIC单片机的EEPROM读写实例及说明;* ...
- 基于51单片机的EEPROM读写
本讲内容: 对存储器的基本知识进行介绍.介绍EEPROM芯片AT24C02:通过例程展示EEPROM的读写. 存储器是应用于各种嵌入式场合的存储部件,按功能可分为只读存储器(ROM)和随机存取存储器( ...
- STC15系列单片机EEPROM读写示例
STC15系列单片机EEPROM读写示例
- linux中i2c读写函数,Linux下的eeprom读写操作(IIC)
/* *************************************************************************** * File name: eeprom_i ...
- Linux下的eeprom读写操作
转载地址:http://blog.csdn.net/yuzeze/article/details/51890555 利用Linux内核自带的IIC总线驱动,按系统提供的框架,用ioctl方法对eepr ...
- STM32L0 系列 EEPROM 读写,程序卡死?
STM32L0 系列EEPROM读写,使用过程必须注意到的问题,踩坑史 = =!......by 矜辰所致 目录 前言 一.写入地址问题 二.写入时候容易死机问题 2.1 问题的原因 2.2 问题的解 ...
最新文章
- 在Linux系统下查看ora错误
- UE4_Lighting Scenarios
- php程序员笔试题库,2017年初级PHP程序员笔试题
- 前端命名规范_前端开发工程师如何突破年薪50万?这里有4点建议
- linux之内核剖析
- windows操作笔记
- Https下字体文件无法加载的解决方案
- 网易有道 ASR 团队斩获 Interspeech 2021 算法竞赛两项冠军
- 36. linux系统日志在哪里看
- 小白白红队初成长(4)文件的面纱
- PhoneGap的移动开发框架
- Ubuntu18.04安装wps office
- uniapp 实现销售订单页面-风格1
- CMDB(运维自动化)
- 读《哥德尔、艾舍尔、巴赫——集异壁之大成》
- 诊断Diagnostics
- 用 Python 脚本实现对 Linux 服务器的监控
- 第三方日志文件ALog使用详解
- 2022计算机全程:C语言程序设计精讲
- 阿里大数据打假:实时分析数据每秒1亿次