#include "eeprom.h" uint8_t Tx1_Buffer[] = "3.14159265358978"; uint8_t Rx1_Buffer[BufferSize1] = ""; void ee_io_init(void) { GPIO_InitTypeDef GPIO_InitStruct; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOB_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6|GPIO_PIN_7, GPIO_PIN_RESET); /*Configure GPIO pins : PB6 PB9 */ GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7; //PB6 PB7 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; //开漏输出 GPIO_InitStruct.Pull = GPIO_NOPULL; //上下拉模式配置为既不上拉也不下拉 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;//IO口速度配置 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); //初始化 } static void i2c_delay(void) { uint8_t i; for (i = 0; i < 40; i++); } void i2c_start(void) { // 当SCL高电平时,SDA出现一个下跳沿表示I2C总线启动信号 I2C_SDA_1(); I2C_SCL_1(); i2c_delay(); I2C_SDA_0(); i2c_delay(); I2C_SCL_0(); i2c_delay(); } void i2c_stop(void) { // 当SCL高电平时,SDA出现一个上跳沿表示I2C总线停止信号 I2C_SDA_0(); I2C_SCL_1(); i2c_delay(); I2C_SDA_1(); i2c_delay(); } void i2c_sendbyte(uint8_t _ucByte) { uint8_t i; // 先发送字节的高位bit7 for (i = 0; i < 8; i++) { if (_ucByte & 0x80) { I2C_SDA_1(); } else { I2C_SDA_0(); } i2c_delay(); I2C_SCL_1(); i2c_delay(); I2C_SCL_0(); if (i == 7) { I2C_SDA_1(); // 释放总线 } _ucByte <<= 1; // 左移一个bit i2c_delay(); } } uint8_t i2c_readbyte(void) { uint8_t i; uint8_t value; /* 读到第1个bit为数据的bit7 */ value = 0; for (i = 0; i < 8; i++) { value <<= 1; I2C_SCL_1(); i2c_delay(); if (I2C_SDA_READ()) { value++; } I2C_SCL_0(); i2c_delay(); } return value; } uint8_t i2c_waitack(void) { uint8_t re; I2C_SDA_1(); /* CPU释放SDA总线 */ // i2c_Delay(); I2C_SCL_1(); /* CPU驱动SCL = 1, 此时器件会返回ACK应答 */ i2c_delay(); if (I2C_SDA_READ()) /* CPU读取SDA口线状态 */ { re = 1; } else { re = 0; } I2C_SCL_0(); i2c_delay(); return re; } void i2c_ack(void) { I2C_SDA_0(); /* CPU驱动SDA = 0 */ i2c_delay(); I2C_SCL_1(); /* CPU产生1个时钟 */ i2c_delay(); I2C_SCL_0(); i2c_delay(); I2C_SDA_1(); /* CPU释放SDA总线 */ } void i2c_nack(void) { I2C_SDA_1(); /* CPU驱动SDA = 1 */ i2c_delay(); I2C_SCL_1(); /* CPU产生1个时钟 */ i2c_delay(); I2C_SCL_0(); i2c_delay(); } uint8_t i2c_checkdevice(uint8_t _Address) { uint8_t ucAck; if (I2C_SDA_READ() && I2C_SCL_READ()) { i2c_start(); /* 发送启动信号 */ /* 发送设备地址+读写控制bit(0 = w, 1 = r) bit7 先传 */ i2c_sendbyte(_Address | I2C_WR); ucAck = i2c_waitack(); /* 检测设备的ACK应答 */ i2c_stop(); /* 发送停止信号 */ return ucAck; } return 1; /* I2C总线异常 */ } uint8_t ee_checkok(void) { if (i2c_checkdevice(EE_DEV_ADDR) == 0) { return 1; } else { /* 失败后,切记发送I2C总线停止信号 */ i2c_stop(); return 0; } } uint8_t ee_writebytes(uint8_t *_pWriteBuf, uint16_t _usAddress, uint16_t _usSize) { uint16_t i,m; uint16_t usAddr; usAddr = _usAddress; for (i = 0; i < _usSize; i++) { /* 当发送第1个字节或是页面首地址时,需要重新发起启动信号和地址 */ if ((i == 0) || (usAddr & (EE_PAGE_SIZE - 1)) == 0) { /* 第0步:发停止信号,启动内部写操作 */ i2c_stop(); /* 通过检查器件应答的方式,判断内部写操作是否完成, 一般小于 10ms CLK频率为200KHz时,查询次数为30次左右 */ for (m = 0; m < 1000; m++) { /* 第1步:发起I2C总线启动信号 */ i2c_start(); /* 第2步:发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读 */ // #if EE_ADDR_A8 == 1 // i2c_SendByte(EE_DEV_ADDR | I2C_WR | ((_usAddress >> 7) & 0x0E)); /* 此处是写指令 */ // #else i2c_sendbyte(EE_DEV_ADDR | I2C_WR); // #endif /* 第3步:发送一个时钟,判断器件是否正确应答 */ if (i2c_waitack() == 0) { break; } } if (m == 1000) { goto cmd_fail; /* EEPROM器件写超时 */ } /* 第4步:发送字节地址,24C02只有256字节,因此1个字节就够了,如果是24C04以上,那么此处需要连发多个地址 */ if (EE_ADDR_BYTES == 1) { i2c_sendbyte((uint8_t)usAddr); if (i2c_waitack() != 0) { goto cmd_fail; /* EEPROM器件无应答 */ } } else { i2c_sendbyte(usAddr >> 8); if (i2c_waitack()!= 0) { goto cmd_fail; /* EEPROM器件无应答 */ } i2c_sendbyte(usAddr); 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(); /* 通过检查器件应答的方式,判断内部写操作是否完成, 一般小于 10ms CLK频率为200KHz时,查询次数为30次左右 */ for (m = 0; m < 1000; m++) { /* 第1步:发起I2C总线启动信号 */ i2c_start(); /* 第2步:发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读 */ #if EE_ADDR_A8 == 1 i2c_sendbyte(EE_DEV_ADDR | I2C_WR | ((_usAddress >> 7) & 0x0E)); /* 此处是写指令 */ #else i2c_sendbyte(EE_DEV_ADDR | I2C_WR); /* 此处是写指令 */ #endif /* 第3步:发送一个时钟,判断器件是否正确应答 */ if (i2c_waitack() == 0) { break; } } if (m == 1000) { goto cmd_fail; /* EEPROM器件写超时 */ } /* 命令执行成功,发送I2C总线停止信号 */ i2c_stop(); return 1; cmd_fail: /* 命令执行失败后,切记发送停止信号,避免影响I2C总线上其他设备 */ /* 发送I2C总线停止信号 */ i2c_stop(); return 0; } 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(EE_DEV_ADDR | I2C_WR); /* 此处是写指令 */ /* 第3步:发送ACK */ if (i2c_waitack() != 0) { goto cmd_fail; /* EEPROM器件无应答 */ } /* 第4步:发送字节地址,24C02只有256字节,因此1个字节就够了,如果是24C04以上,那么此处需要连发多个地址 */ if (EE_ADDR_BYTES == 1) { i2c_sendbyte((uint8_t)_usAddress); if (i2c_waitack() != 0) { goto cmd_fail; /* EEPROM器件无应答 */ } } else { i2c_sendbyte(_usAddress >> 8); if (i2c_waitack() != 0) { goto cmd_fail; /* EEPROM器件无应答 */ } i2c_sendbyte(_usAddress); if (i2c_waitack() != 0) { goto cmd_fail; /* EEPROM器件无应答 */ } } /* 第6步:重新启动I2C总线。下面开始读取数据 */ i2c_start(); /* 第7步:发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读 */ i2c_sendbyte(EE_DEV_ADDR | 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; } // m=ee_writebytes(Tx1_Buffer,0,BufferSize1); // printf("I2C_WriteByte %d %s\r\n",m,(uint8_t*)&Tx1_Buffer[0]); // m=ee_readbytes(Rx1_Buffer,0,BufferSize1); // printf("I2C_ReadByte %d %s\r\n",m,(uint8_t*)&Rx1_Buffer[0]); // printf(" Rx1_Buffer is:%s,\t the BufferSize1 is:%d\r\n",Rx1_Buffer,BufferSize1); uint8_t trans1[12]={0}; uint8_t trans2[12]={0}; void ee_writefloats(uint16_t _usAddress, float wr_data[3], uint8_t _usSize) { // for(uint8_t i = 0;i<_usSize;i++) // { memcpy(trans1,wr_data,12); ee_writebytes(trans1, _usAddress, 12); // } } void ee_readfloats(uint16_t _usAddress, float rd_data[3], uint8_t _usSize) { // for(uint8_t i =0 ;i<_usSize;i++) // { ee_readbytes(trans2, _usAddress, 12); memcpy(rd_data,&trans2,12); // } }