acdt/board/Src/eeprom.c

403 lines
7.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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(); /* 发送启动信号 */
/* 发送设备地址+读写控制bit0 = 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);
// }
}