大学学校类网站设计,网络会议有哪些软件,北京大兴网站建设公司咨询,seo优化交流stm32中I2C 文章目录 stm32中I2CI2C 协议简介I2C物理层协议层I2C基本读写过程 **通讯的起始和停止信号****数据有效性****地址及数据方向****响应** STM32的I2C特性及架构**STM32** **的** I2C外设简介STM32 的 I 2C 架构剖析通讯引脚 通讯过程主发送器主接收器 I2C初始化结构体…stm32中I2C 文章目录 stm32中I2CI2C 协议简介I2C物理层协议层I2C基本读写过程 **通讯的起始和停止信号****数据有效性****地址及数据方向****响应** STM32的I2C特性及架构**STM32** **的** I2C外设简介STM32 的 I 2C 架构剖析通讯引脚 通讯过程主发送器主接收器 I2C初始化结构体代码实现硬件代码软件代码 I2C 协议简介
I2C物理层
协议通讯图 I2C上一个总线能挂载多个设备共用信号线可以连接多个从机只用了两个总线一条双向串行数据线SDA一条串行时钟线(SCL)。数据线即用来表示数据时钟线用于数据收发同步。每个连接到总线的设备都有独立的地址主机可以通过该地址进行访问I2C空闲时输出高阻态当所有设备都空闲时由上拉电阻把总线拉成高电平主机同时使用总线时会用仲裁的方式来决定三种传输模式标准模式传输速率为 100kbit/s 快速模式为 400kbit/s 高速模式下可达3.4Mbit/s但目前大多 I 2C 设备尚不支持高速模式。连接到相同总线的IC数量收到总线的最大电容400pF限制。
协议层
I2C 的协议定义了通讯的起始和停止信号、数据有效性、响应、仲裁、时钟同步和地址广播等环节。
I2C基本读写过程
先看看 I2C 通讯过程的基本结构它的通讯过程见图主机写数据到从机 、图主机由从机中读数据 及图 I2C 通讯复合格式 。 注意
从机地址7位或者10位应答信号只有接收到应答信号后主句才会继续发送或者接收数据
写数据:将数据写入地址
从机向主机写完地址并且接收到应答信号正式向从机传输数据DATA数据包的大小为8位主机没发送完一个字节数据都要等待从机的应答信号ACK重复这个过程可以传输N个数据N大小没有限制。数据结束时向从机发送一个停止传输信号P表示不再传输数据。
读数据将数据从地址读出
从机向主机写完设备地址并且收到应答信号从机开始向主机返回数据 (DATA)数据包大小也为 8 位从机每发送完一个数据都会等待主机的应答信号 (ACK)重复这个过程可以返回 N 个数据这个 N 也没有大小限制。当主机希望停止接收数据时就向从机返回一个非应答信号 (NACK)则从机自动停止数据传输。
读和写数据从主机找到设备后再读
除了基本的读写I2C 通讯更常用的是复合格式即第三幅图的情况该传输过程有两次起始信号 (S)。一般在第一次传输中主机通过 SLAVE_ADDRESS 寻找到从设备后发送一段“数据”这段数据通常用于表示从设备内部的寄存器或存储器地址 (注意区分它与 SLAVE_ADDRESS 的区别)在第二次的传输中对该地址的内容进行读或写。也就是说第一次通讯是告诉从机读写地址第二次则是读写的实际内容
通讯的起始和停止信号 数据有效性 地址及数据方向
七位地址 I2C协议规定地址可以是七位或者十位但是通常使用七位。前七位或者前十位是从机地址第八位或者第十一位是读写标志符
响应 STM32的I2C特性及架构
硬件协议stm32的有点问题很容易卡死软件协议推荐使用
STM32 的 I2C外设简介
STM32 的 I 2C 架构剖析 通讯引脚
引脚I2C1I2C2SCLPB6/PB8(重映射)PB10SDAPB7/PB9重映射PB111
通讯过程
主发送器 主接收器 I2C初始化结构体
typedef struct
{uint32_t I2C_ClockSpeed; /*! Specifies the clock frequency.This parameter must be set to a value lower than 400kHz */uint16_t I2C_Mode; /*! Specifies the I2C mode.This parameter can be a value of ref I2C_mode */uint16_t I2C_DutyCycle; /*! Specifies the I2C fast mode duty cycle.This parameter can be a value of ref I2C_duty_cycle_in_fast_mode */uint16_t I2C_OwnAddress1; /*! Specifies the first device own address.This parameter can be a 7-bit or 10-bit address. */uint16_t I2C_Ack; /*! Enables or disables the acknowledgement.This parameter can be a value of ref I2C_acknowledgement */uint16_t I2C_AcknowledgedAddress; /*! Specifies if 7-bit or 10-bit address is acknowledged.This parameter can be a value of ref I2C_acknowledged_address */
}I2C_InitTypeDef;结构体名称作用I2C_ClockSpeed控制速度I2C_Mode控制模式I2C_DutyCycle控制占空比I2C_OwnAddress1控制自己的地址I2C_Ack控制应答I2C_AcknowledgedAddress控制设备地址
代码实现
硬件代码
/********************************************************************************* file bsp_i2c_ee.c* author STMicroelectronics* version V1.0* date 2013-xx-xx* brief i2c EEPROM(AT24C02)应用函数bsp******************************************************************************* attention** 实验平台:野火 F103-指南者 STM32 开发板 ********************************************************************************/ #include ./i2c/bsp_i2c_ee.h
#include ./usart/bsp_usart.h uint16_t EEPROM_ADDRESS;static __IO uint32_t I2CTimeout I2CT_LONG_TIMEOUT; static uint32_t I2C_TIMEOUT_UserCallback(uint8_t errorCode);/*** brief I2C I/O配置* param 无* retval 无*/
static void I2C_GPIO_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure; /* 使能与 I2C 有关的时钟 */EEPROM_I2C_APBxClock_FUN ( EEPROM_I2C_CLK, ENABLE );EEPROM_I2C_GPIO_APBxClock_FUN ( EEPROM_I2C_GPIO_CLK, ENABLE );/* I2C_SCL、I2C_SDA*/GPIO_InitStructure.GPIO_Pin EEPROM_I2C_SCL_PIN;GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_OD; // 开漏输出GPIO_Init(EEPROM_I2C_SCL_PORT, GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin EEPROM_I2C_SDA_PIN;GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_OD; // 开漏输出GPIO_Init(EEPROM_I2C_SDA_PORT, GPIO_InitStructure); }/*** brief I2C 工作模式配置* param 无* retval 无*/
static void I2C_Mode_Configu(void)
{I2C_InitTypeDef I2C_InitStructure; /* I2C 配置 */I2C_InitStructure.I2C_Mode I2C_Mode_I2C;/* 高电平数据稳定低电平数据变化 SCL 时钟线的占空比 */I2C_InitStructure.I2C_DutyCycle I2C_DutyCycle_2;I2C_InitStructure.I2C_OwnAddress1 I2Cx_OWN_ADDRESS7; I2C_InitStructure.I2C_Ack I2C_Ack_Enable ;/* I2C的寻址模式 */I2C_InitStructure.I2C_AcknowledgedAddress I2C_AcknowledgedAddress_7bit;/* 通信速率 */I2C_InitStructure.I2C_ClockSpeed I2C_Speed;/* I2C 初始化 */I2C_Init(EEPROM_I2Cx, I2C_InitStructure);/* 使能 I2C */I2C_Cmd(EEPROM_I2Cx, ENABLE);
}/*** brief I2C 外设(EEPROM)初始化* param 无* retval 无*/
void I2C_EE_Init(void)
{I2C_GPIO_Config(); I2C_Mode_Configu();/* 根据头文件i2c_ee.h中的定义来选择EEPROM的设备地址 */
#ifdef EEPROM_Block0_ADDRESS/* 选择 EEPROM Block0 来写入 */EEPROM_ADDRESS EEPROM_Block0_ADDRESS;
#endif#ifdef EEPROM_Block1_ADDRESS /* 选择 EEPROM Block1 来写入 */EEPROM_ADDRESS EEPROM_Block1_ADDRESS;
#endif#ifdef EEPROM_Block2_ADDRESS /* 选择 EEPROM Block2 来写入 */EEPROM_ADDRESS EEPROM_Block2_ADDRESS;
#endif#ifdef EEPROM_Block3_ADDRESS /* 选择 EEPROM Block3 来写入 */EEPROM_ADDRESS EEPROM_Block3_ADDRESS;
#endif
}/*** brief 将缓冲区中的数据写到I2C EEPROM中* param * arg pBuffer:缓冲区指针* arg WriteAddr:写地址* arg NumByteToWrite:写的字节数* retval 无*/
void I2C_EE_BufferWrite(u8* pBuffer, u8 WriteAddr, u16 NumByteToWrite)
{u8 NumOfPage 0, NumOfSingle 0, Addr 0, count 0;Addr WriteAddr % I2C_PageSize;count I2C_PageSize - Addr;NumOfPage NumByteToWrite / I2C_PageSize;NumOfSingle NumByteToWrite % I2C_PageSize;/* If WriteAddr is I2C_PageSize aligned */if(Addr 0) {/* If NumByteToWrite I2C_PageSize */if(NumOfPage 0) {I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);I2C_EE_WaitEepromStandbyState();}/* If NumByteToWrite I2C_PageSize */else {while(NumOfPage--){I2C_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize); I2C_EE_WaitEepromStandbyState();WriteAddr I2C_PageSize;pBuffer I2C_PageSize;}if(NumOfSingle!0){I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);I2C_EE_WaitEepromStandbyState();}}}/* If WriteAddr is not I2C_PageSize aligned */else {/* If NumByteToWrite I2C_PageSize */if(NumOfPage 0) {I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);I2C_EE_WaitEepromStandbyState();}/* If NumByteToWrite I2C_PageSize */else{NumByteToWrite - count;NumOfPage NumByteToWrite / I2C_PageSize;NumOfSingle NumByteToWrite % I2C_PageSize; if(count ! 0){ I2C_EE_PageWrite(pBuffer, WriteAddr, count);I2C_EE_WaitEepromStandbyState();WriteAddr count;pBuffer count;} while(NumOfPage--){I2C_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize);I2C_EE_WaitEepromStandbyState();WriteAddr I2C_PageSize;pBuffer I2C_PageSize; }if(NumOfSingle ! 0){I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle); I2C_EE_WaitEepromStandbyState();}}}
}/*** brief 写一个字节到I2C EEPROM中* param * arg pBuffer:缓冲区指针* arg WriteAddr:写地址 * retval 无*/
uint32_t I2C_EE_ByteWrite(u8* pBuffer, u8 WriteAddr)
{/* Send STRAT condition */I2C_GenerateSTART(EEPROM_I2Cx, ENABLE);I2CTimeout I2CT_FLAG_TIMEOUT; /* Test on EV5 and clear it */while(!I2C_CheckEvent(EEPROM_I2Cx, I2C_EVENT_MASTER_MODE_SELECT)) {if((I2CTimeout--) 0) return I2C_TIMEOUT_UserCallback(0);} I2CTimeout I2CT_FLAG_TIMEOUT;/* Send EEPROM address for write */I2C_Send7bitAddress(EEPROM_I2Cx, EEPROM_ADDRESS, I2C_Direction_Transmitter);/* Test on EV6 and clear it */while(!I2C_CheckEvent(EEPROM_I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)){if((I2CTimeout--) 0) return I2C_TIMEOUT_UserCallback(1);} /* Send the EEPROMs internal address to write to */I2C_SendData(EEPROM_I2Cx, WriteAddr);I2CTimeout I2CT_FLAG_TIMEOUT;/* Test on EV8 and clear it */while(!I2C_CheckEvent(EEPROM_I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED)){if((I2CTimeout--) 0) return I2C_TIMEOUT_UserCallback(2);} /* Send the byte to be written */I2C_SendData(EEPROM_I2Cx, *pBuffer); I2CTimeout I2CT_FLAG_TIMEOUT; /* Test on EV8 and clear it */while(!I2C_CheckEvent(EEPROM_I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED)){if((I2CTimeout--) 0) return I2C_TIMEOUT_UserCallback(3);} /* Send STOP condition */I2C_GenerateSTOP(EEPROM_I2Cx, ENABLE);return 1;
}/*** brief 在EEPROM的一个写循环中可以写多个字节但一次写入的字节数* 不能超过EEPROM页的大小AT24C02每页有8个字节* param * arg pBuffer:缓冲区指针* arg WriteAddr:写地址* arg NumByteToWrite:写的字节数* retval 无*/
uint32_t I2C_EE_PageWrite(u8* pBuffer, u8 WriteAddr, u8 NumByteToWrite)
{I2CTimeout I2CT_LONG_TIMEOUT;while(I2C_GetFlagStatus(EEPROM_I2Cx, I2C_FLAG_BUSY)) {if((I2CTimeout--) 0) return I2C_TIMEOUT_UserCallback(4);} /* Send START condition */I2C_GenerateSTART(EEPROM_I2Cx, ENABLE);I2CTimeout I2CT_FLAG_TIMEOUT;/* Test on EV5 and clear it */while(!I2C_CheckEvent(EEPROM_I2Cx, I2C_EVENT_MASTER_MODE_SELECT)) {if((I2CTimeout--) 0) return I2C_TIMEOUT_UserCallback(5);} /* Send EEPROM address for write */I2C_Send7bitAddress(EEPROM_I2Cx, EEPROM_ADDRESS, I2C_Direction_Transmitter);I2CTimeout I2CT_FLAG_TIMEOUT;/* Test on EV6 and clear it */while(!I2C_CheckEvent(EEPROM_I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) {if((I2CTimeout--) 0) return I2C_TIMEOUT_UserCallback(6);} /* Send the EEPROMs internal address to write to */ I2C_SendData(EEPROM_I2Cx, WriteAddr); I2CTimeout I2CT_FLAG_TIMEOUT;/* Test on EV8 and clear it */while(! I2C_CheckEvent(EEPROM_I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED)){if((I2CTimeout--) 0) return I2C_TIMEOUT_UserCallback(7);} /* While there is data to be written */while(NumByteToWrite--) {/* Send the current byte */I2C_SendData(EEPROM_I2Cx, *pBuffer); /* Point to the next byte to be written */pBuffer; I2CTimeout I2CT_FLAG_TIMEOUT;/* Test on EV8 and clear it */while (!I2C_CheckEvent(EEPROM_I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED)){if((I2CTimeout--) 0) return I2C_TIMEOUT_UserCallback(8);} }/* Send STOP condition */I2C_GenerateSTOP(EEPROM_I2Cx, ENABLE);return 1;
}/*** brief 从EEPROM里面读取一块数据 * param * arg pBuffer:存放从EEPROM读取的数据的缓冲区指针* arg WriteAddr:接收数据的EEPROM的地址* arg NumByteToWrite:要从EEPROM读取的字节数* retval 无*/
uint32_t I2C_EE_BufferRead(u8* pBuffer, u8 ReadAddr, u16 NumByteToRead)
{ I2CTimeout I2CT_LONG_TIMEOUT;//*((u8 *)0x4001080c) |0x80; while(I2C_GetFlagStatus(EEPROM_I2Cx, I2C_FLAG_BUSY)){if((I2CTimeout--) 0) return I2C_TIMEOUT_UserCallback(9);}/* Send START condition */I2C_GenerateSTART(EEPROM_I2Cx, ENABLE);//*((u8 *)0x4001080c) ~0x80;I2CTimeout I2CT_FLAG_TIMEOUT;/* Test on EV5 and clear it */while(!I2C_CheckEvent(EEPROM_I2Cx, I2C_EVENT_MASTER_MODE_SELECT)){if((I2CTimeout--) 0) return I2C_TIMEOUT_UserCallback(10);}/* Send EEPROM address for write */I2C_Send7bitAddress(EEPROM_I2Cx, EEPROM_ADDRESS, I2C_Direction_Transmitter);I2CTimeout I2CT_FLAG_TIMEOUT;/* Test on EV6 and clear it */while(!I2C_CheckEvent(EEPROM_I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)){if((I2CTimeout--) 0) return I2C_TIMEOUT_UserCallback(11);}/* Clear EV6 by setting again the PE bit */I2C_Cmd(EEPROM_I2Cx, ENABLE);/* Send the EEPROMs internal address to write to */I2C_SendData(EEPROM_I2Cx, ReadAddr); I2CTimeout I2CT_FLAG_TIMEOUT;/* Test on EV8 and clear it */while(!I2C_CheckEvent(EEPROM_I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED)){if((I2CTimeout--) 0) return I2C_TIMEOUT_UserCallback(12);}/* Send STRAT condition a second time */ I2C_GenerateSTART(EEPROM_I2Cx, ENABLE);I2CTimeout I2CT_FLAG_TIMEOUT;/* Test on EV5 and clear it */while(!I2C_CheckEvent(EEPROM_I2Cx, I2C_EVENT_MASTER_MODE_SELECT)){if((I2CTimeout--) 0) return I2C_TIMEOUT_UserCallback(13);}/* Send EEPROM address for read */I2C_Send7bitAddress(EEPROM_I2Cx, EEPROM_ADDRESS, I2C_Direction_Receiver);I2CTimeout I2CT_FLAG_TIMEOUT;/* Test on EV6 and clear it */while(!I2C_CheckEvent(EEPROM_I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)){if((I2CTimeout--) 0) return I2C_TIMEOUT_UserCallback(14);}/* While there is data to be read */while(NumByteToRead) {if(NumByteToRead 1){/* Disable Acknowledgement */I2C_AcknowledgeConfig(EEPROM_I2Cx, DISABLE);/* Send STOP Condition */I2C_GenerateSTOP(EEPROM_I2Cx, ENABLE);}/* Test on EV7 and clear it */ I2CTimeout I2CT_LONG_TIMEOUT;while(I2C_CheckEvent(EEPROM_I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)0) {if((I2CTimeout--) 0) return I2C_TIMEOUT_UserCallback(3);} { /* Read a byte from the EEPROM */*pBuffer I2C_ReceiveData(EEPROM_I2Cx);/* Point to the next location where the byte read will be saved */pBuffer; /* Decrement the read bytes counter */NumByteToRead--; } }/* Enable Acknowledgement to be ready for another reception */I2C_AcknowledgeConfig(EEPROM_I2Cx, ENABLE);return 1;
}/*** brief Wait for EEPROM Standby state * param 无* retval 无*/
void I2C_EE_WaitEepromStandbyState(void)
{vu16 SR1_Tmp 0;do{/* Send START condition */I2C_GenerateSTART(EEPROM_I2Cx, ENABLE);/* Read I2C1 SR1 register */SR1_Tmp I2C_ReadRegister(EEPROM_I2Cx, I2C_Register_SR1);/* Send EEPROM address for write */I2C_Send7bitAddress(EEPROM_I2Cx, EEPROM_ADDRESS, I2C_Direction_Transmitter);}while(!(I2C_ReadRegister(EEPROM_I2Cx, I2C_Register_SR1) 0x0002));/* Clear AF flag */I2C_ClearFlag(EEPROM_I2Cx, I2C_FLAG_AF);/* STOP condition */ I2C_GenerateSTOP(EEPROM_I2Cx, ENABLE);
}/*** brief Basic management of the timeout situation.* param errorCode错误代码可以用来定位是哪个环节出错.* retval 返回0表示IIC读取失败.*/
static uint32_t I2C_TIMEOUT_UserCallback(uint8_t errorCode)
{/* Block communication and all processes */EEPROM_ERROR(I2C 等待超时!errorCode %d,errorCode);return 0;
}
/*********************************************END OF FILE**********************/
软件代码
/********************************************************************************* file bsp_i2c_ee.c* version V1.0* date 2013-xx-xx* brief i2c EEPROM(AT24C02)应用函数bsp******************************************************************************* attention** 实验平台:野火 F103-指南者 STM32 开发板 ********************************************************************************/ #include bsp_i2c_ee.h
#include bsp_i2c_gpio.h
#include bsp_usart.h /*
*********************************************************************************************************
* 函 数 名: ee_CheckOk
* 功能说明: 判断串行EERPOM是否正常
* 形 参无
* 返 回 值: 1 表示正常 0 表示不正常
*********************************************************************************************************
*/
uint8_t ee_CheckOk(void)
{if (i2c_CheckDevice(EEPROM_DEV_ADDR) 0){return 1;}else{/* 失败后切记发送I2C总线停止信号 */i2c_Stop(); return 0;}
}/*
*********************************************************************************************************
* 函 数 名: ee_ReadBytes
* 功能说明: 从串行EEPROM指定地址处开始读取若干数据
* 形 参_usAddress : 起始地址
* _usSize : 数据长度单位为字节
* _pReadBuf : 存放读到的数据的缓冲区指针
* 返 回 值: 0 表示失败1表示成功
*********************************************************************************************************
*/
uint8_t ee_ReadBytes(uint8_t *_pReadBuf, uint16_t _usAddress, uint16_t _usSize)
{uint16_t i;/* 采用串行EEPROM随即读取指令序列连续读取若干字节 *//* 第1步发起I2C总线启动信号 */i2c_Start();/* 第2步发起控制字节高7bit是地址bit0是读写控制位0表示写1表示读 */i2c_SendByte(EEPROM_DEV_ADDR | EEPROM_I2C_WR); /* 此处是写指令 *//* 第3步等待ACK */if (i2c_WaitAck() ! 0){goto cmd_fail; /* EEPROM器件无应答 */}/* 第4步发送字节地址24C02只有256字节因此1个字节就够了如果是24C04以上那么此处需要连发多个地址 */i2c_SendByte((uint8_t)_usAddress);/* 第5步等待ACK */if (i2c_WaitAck() ! 0){goto cmd_fail; /* EEPROM器件无应答 */}/* 第6步重新启动I2C总线。前面的代码的目的向EEPROM传送地址下面开始读取数据 */i2c_Start();/* 第7步发起控制字节高7bit是地址bit0是读写控制位0表示写1表示读 */i2c_SendByte(EEPROM_DEV_ADDR | EEPROM_I2C_RD); /* 此处是读指令 *//* 第8步发送ACK */if (i2c_WaitAck() ! 0){goto cmd_fail; /* EEPROM器件无应答 */} /* 第9步循环读取数据 */for (i 0; i _usSize; i){_pReadBuf[i] i2c_ReadByte(); /* 读1个字节 *//* 每读完1个字节后需要发送Ack 最后一个字节不需要Ack发Nack */if (i ! _usSize - 1){i2c_Ack(); /* 中间字节读完后CPU产生ACK信号(驱动SDA 0) */}else{i2c_NAck(); /* 最后1个字节读完后CPU产生NACK信号(驱动SDA 1) */}}/* 发送I2C总线停止信号 */i2c_Stop();return 1; /* 执行成功 */cmd_fail: /* 命令执行失败后切记发送停止信号避免影响I2C总线上其他设备 *//* 发送I2C总线停止信号 */i2c_Stop();return 0;
}/*
*********************************************************************************************************
* 函 数 名: ee_WriteBytes
* 功能说明: 向串行EEPROM指定地址写入若干数据采用页写操作提高写入效率
* 形 参_usAddress : 起始地址
* _usSize : 数据长度单位为字节
* _pWriteBuf : 存放读到的数据的缓冲区指针
* 返 回 值: 0 表示失败1表示成功
*********************************************************************************************************
*/
uint8_t ee_WriteBytes(uint8_t *_pWriteBuf, uint16_t _usAddress, uint16_t _usSize)
{uint16_t i,m;uint16_t usAddr;/* 写串行EEPROM不像读操作可以连续读取很多字节每次写操作只能在同一个page。对于24xx02page size 8简单的处理方法为按字节写操作模式每写1个字节都发送地址为了提高连续写的效率: 本函数采用page wirte操作。*/usAddr _usAddress; for (i 0; i _usSize; i){/* 当发送第1个字节或是页面首地址时需要重新发起启动信号和地址 */if ((i 0) || (usAddr (EEPROM_PAGE_SIZE - 1)) 0){/* 第步发停止信号启动内部写操作 */i2c_Stop();/* 通过检查器件应答的方式判断内部写操作是否完成, 一般小于 10ms CLK频率为200KHz时查询次数为30次左右*/for (m 0; m 1000; m){ /* 第1步发起I2C总线启动信号 */i2c_Start();/* 第2步发起控制字节高7bit是地址bit0是读写控制位0表示写1表示读 */i2c_SendByte(EEPROM_DEV_ADDR | EEPROM_I2C_WR); /* 此处是写指令 *//* 第3步发送一个时钟判断器件是否正确应答 */if (i2c_WaitAck() 0){break;}}if (m 1000){goto cmd_fail; /* EEPROM器件写超时 */}/* 第4步发送字节地址24C02只有256字节因此1个字节就够了如果是24C04以上那么此处需要连发多个地址 */i2c_SendByte((uint8_t)usAddr);/* 第5步等待ACK */if (i2c_WaitAck() ! 0){goto cmd_fail; /* EEPROM器件无应答 */}}/* 第6步开始写入数据 */i2c_SendByte(_pWriteBuf[i]);/* 第7步发送ACK */if (i2c_WaitAck() ! 0){goto cmd_fail; /* EEPROM器件无应答 */}usAddr; /* 地址增1 */ }/* 命令执行成功发送I2C总线停止信号 */i2c_Stop();return 1;cmd_fail: /* 命令执行失败后切记发送停止信号避免影响I2C总线上其他设备 *//* 发送I2C总线停止信号 */i2c_Stop();return 0;
}void ee_Erase(void)
{uint16_t i;uint8_t buf[EEPROM_SIZE];/* 填充缓冲区 */for (i 0; i EEPROM_SIZE; i){buf[i] 0xFF;}/* 写EEPROM, 起始地址 0数据长度为 256 */if (ee_WriteBytes(buf, 0, EEPROM_SIZE) 0){printf(擦除eeprom出错\r\n);return;}else{printf(擦除eeprom成功\r\n);}
}/*--------------------------------------------------------------------------------------------------*/
static void ee_Delay(__IO uint32_t nCount) //简单的延时函数
{for(; nCount ! 0; nCount--);
}/** eeprom AT24C02 读写测试* 正常返回1异常返回0*/
uint8_t ee_Test(void)
{uint16_t i;uint8_t write_buf[EEPROM_SIZE];uint8_t read_buf[EEPROM_SIZE];/*-----------------------------------------------------------------------------------*/ if (ee_CheckOk() 0){/* 没有检测到EEPROM */printf(没有检测到串行EEPROM!\r\n);return 0;}
/*------------------------------------------------------------------------------------*/ /* 填充测试缓冲区 */for (i 0; i EEPROM_SIZE; i){ write_buf[i] i;}
/*------------------------------------------------------------------------------------*/ if (ee_WriteBytes(write_buf, 0, EEPROM_SIZE) 0){printf(写eeprom出错\r\n);return 0;}else{ printf(写eeprom成功\r\n);}/*写完之后需要适当的延时再去读不然会出错*/ee_Delay(0x0FFFFF);
/*-----------------------------------------------------------------------------------*/if (ee_ReadBytes(read_buf, 0, EEPROM_SIZE) 0){printf(读eeprom出错\r\n);return 0;}else{ printf(读eeprom成功数据如下\r\n);}
/*-----------------------------------------------------------------------------------*/ for (i 0; i EEPROM_SIZE; i){if(read_buf[i] ! write_buf[i]){printf(0x%02X , read_buf[i]);printf(错误:EEPROM读出与写入的数据不一致);return 0;}printf( %02X, read_buf[i]);if ((i 15) 15){printf(\r\n); } }printf(eeprom读写测试成功\r\n);return 1;
}
/*********************************************END OF FILE**********************/