464 lines
9.8 KiB
C
464 lines
9.8 KiB
C
#include "24cxx.h"
|
||
#include "bsp_i2c_gpio.h"
|
||
#include "led.h"
|
||
|
||
//初始化IIC
|
||
void ee_Init(void)
|
||
{
|
||
bsp_InitI2C();
|
||
|
||
}
|
||
//在AT24CXX指定地址读取一个数据
|
||
//ReadAddr :开始读数的地址
|
||
//返回值 :读取到的数据
|
||
u8 ee_ReadOneByte(u16 ReadAddr)
|
||
{
|
||
u8 temp = 0;
|
||
IIC_Start();
|
||
|
||
if (EE_TYPE > AT24C16) {
|
||
IIC_Send_Byte(EE_DEV_ADDR|EEPROM_I2C_WR);//发送写命令
|
||
IIC_Wait_Ack();
|
||
IIC_Send_Byte(ReadAddr / 256); //发送高地址
|
||
} else IIC_Send_Byte(EE_DEV_ADDR|EEPROM_I2C_WR + ((ReadAddr / 256) << 1)); //发送器件地址0xA0,写数据
|
||
|
||
IIC_Wait_Ack();
|
||
IIC_Send_Byte(ReadAddr % 256); //发送低地址
|
||
IIC_Wait_Ack();
|
||
IIC_Start();
|
||
|
||
if (1)IIC_Send_Byte(EE_DEV_ADDR|EEPROM_I2C_RD); //进入接收模式
|
||
else IIC_Send_Byte(EE_DEV_ADDR|EEPROM_I2C_RD + ((ReadAddr / 256) << 1)); //进入接收模式
|
||
|
||
IIC_Wait_Ack();
|
||
temp = IIC_Read_Byte(1);
|
||
IIC_Stop();//产生一个停止条件
|
||
return temp;
|
||
}
|
||
|
||
//在AT24CXX指定地址写一个数据
|
||
//WriteAddr:写入数据的目的地址
|
||
//data :要写入的数据
|
||
void ee_WriteOneByte(u16 WriteAddr, u8 data)
|
||
{
|
||
IIC_Start();
|
||
|
||
if (EE_TYPE > AT24C16) {
|
||
IIC_Send_Byte(EE_DEV_ADDR|EEPROM_I2C_WR);
|
||
IIC_Wait_Ack();
|
||
IIC_Send_Byte(WriteAddr / 256); //发送高地址
|
||
} else IIC_Send_Byte(EE_DEV_ADDR|EEPROM_I2C_WR + ((WriteAddr / 256) << 1));
|
||
|
||
IIC_Wait_Ack();
|
||
IIC_Send_Byte(WriteAddr % 256); //发送低地址
|
||
IIC_Wait_Ack();
|
||
IIC_Send_Byte(data);
|
||
IIC_Wait_Ack();
|
||
IIC_Stop();//产生一个停止条件
|
||
Delay_MS(6);
|
||
}
|
||
#if 1
|
||
//向EEPROM写入多个字节
|
||
uint8_t ee_WriteBytes(uint8_t *_pWriteBuf, uint16_t _usAddress, uint16_t _usSize)
|
||
{
|
||
uint16_t i, m;
|
||
uint16_t addr;
|
||
addr = _usAddress;
|
||
|
||
for (i = 0; i < _usSize; i++) {
|
||
//当第一次或者地址对齐到8就要重新发起起始信号和EEPROM地址
|
||
//为了解决8地址对齐问题
|
||
if (i == 0 || (addr % EE_PAGE_SIZE) == 0) {
|
||
if (i != 0) {
|
||
IIC_Stop();
|
||
Delay_MS(6);
|
||
}
|
||
//发送起始地址
|
||
IIC_Start();
|
||
|
||
//发送设备写地址
|
||
if (EE_TYPE > AT24C16) {
|
||
IIC_Send_Byte(EE_DEV_ADDR|EEPROM_I2C_WR);
|
||
if (IIC_Wait_Ack() != 0) {
|
||
goto cmd_fail;
|
||
}
|
||
IIC_Send_Byte(addr / 256); //发送高地址
|
||
} else IIC_Send_Byte((EE_DEV_ADDR + ((addr / 256) << 1)) | EEPROM_I2C_WR);
|
||
|
||
//等待从机应答
|
||
if (IIC_Wait_Ack() != 0) {
|
||
goto cmd_fail;
|
||
}
|
||
|
||
//EEPROM应答后发送EEPROM的内部存储器地址
|
||
IIC_Send_Byte((uint8_t)addr);
|
||
|
||
//等待从机应答
|
||
if (IIC_Wait_Ack() != 0) {
|
||
goto cmd_fail;
|
||
}
|
||
}
|
||
|
||
//发送数据
|
||
IIC_Send_Byte(_pWriteBuf[i]);
|
||
|
||
//等待应答
|
||
if (IIC_Wait_Ack() != 0) {
|
||
goto cmd_fail;
|
||
}
|
||
|
||
//写入地址加1
|
||
addr++;
|
||
}
|
||
|
||
IIC_Stop();
|
||
return 1;
|
||
|
||
cmd_fail:
|
||
IIC_Stop();
|
||
return 0;
|
||
}
|
||
|
||
|
||
uint8_t ee_ReadBytes(uint8_t *_pReadBuf, uint16_t _usAddress, uint16_t _usSize)
|
||
{
|
||
uint16_t i;
|
||
|
||
//发送起始地址
|
||
IIC_Start();
|
||
|
||
//发送设备写地址
|
||
if (EE_TYPE > AT24C16) {
|
||
IIC_Send_Byte(EE_DEV_ADDR);
|
||
if (IIC_Wait_Ack() != 0) {
|
||
goto cmd_fail;
|
||
}
|
||
IIC_Send_Byte(_usAddress / 256); //发送高地址
|
||
} else IIC_Send_Byte((EE_DEV_ADDR + ((_usAddress / 256) << 1)) | EEPROM_I2C_WR);
|
||
|
||
if (IIC_Wait_Ack() != 0) {
|
||
goto cmd_fail;
|
||
}
|
||
|
||
IIC_Send_Byte((uint8_t)_usAddress);
|
||
|
||
if (IIC_Wait_Ack() != 0) {
|
||
goto cmd_fail;
|
||
}
|
||
|
||
IIC_Start();
|
||
if (EE_TYPE > AT24C16) IIC_Send_Byte(EE_DEV_ADDR | EEPROM_I2C_RD);
|
||
else IIC_Send_Byte((EE_DEV_ADDR + ((_usAddress / 256) << 1)) | EEPROM_I2C_RD);
|
||
|
||
if (IIC_Wait_Ack() != 0) {
|
||
goto cmd_fail;
|
||
}
|
||
|
||
for (i = 0; i < _usSize; i++) {
|
||
/* 每读完1个字节后,需要发送Ack, 最后一个字节不需要Ack,发Nack */
|
||
_pReadBuf[i] = IIC_Read_Byte(i != _usSize - 1?1:0);
|
||
}
|
||
|
||
IIC_Stop();
|
||
return 1;
|
||
|
||
cmd_fail:
|
||
IIC_Stop();
|
||
return 0;
|
||
}
|
||
#endif
|
||
#if 0
|
||
static void IIC1_Start(void); //发送起始信号
|
||
static void IIC1_Stop(void); //发送停止信号
|
||
static void IIC1_Write_Byte(u8 dat);//发送一个字节
|
||
static u8 IIC1_Read_Byte(unsigned char ack);//接收一个字节
|
||
static u8 IIC1_Wait_Ack(void);//等待ACK信号
|
||
static void IIC1_Ack(void);//发送ACK信号
|
||
static void IIC1_NAck(void);//不发送ACK信号
|
||
|
||
void I2C_delay(uint16_t n)
|
||
{
|
||
u8 i = 100 * n; //这里可以优化速度 ,经测试最低到5还能写入
|
||
|
||
while (i) {
|
||
i--;
|
||
}
|
||
}
|
||
|
||
//初始化IIC
|
||
void AT24cxx_init(void)
|
||
{
|
||
GPIO_InitTypeDef GPIO_InitStructure;
|
||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); /* 打开GPIO时钟 */
|
||
|
||
|
||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; //SDA,SCL
|
||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
|
||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||
GPIO_Init(GPIOB, &GPIO_InitStructure);
|
||
IIC_SDA1;
|
||
IIC_SCL1;
|
||
|
||
}
|
||
|
||
//在AT24CXX指定地址读取一个数据
|
||
//ReadAddr :开始读数的地址
|
||
//返回值 :读取到的数据
|
||
u8 AT24cxx_ReadOneByte(u16 ReadAddr)
|
||
{
|
||
u8 temp = 0;
|
||
IIC1_Start();
|
||
|
||
if (EE_TYPE > AT24C16) {
|
||
IIC1_Write_Byte(0xa0);//发送写命令
|
||
IIC1_Wait_Ack();
|
||
IIC1_Write_Byte(ReadAddr / 256); //发送高地址
|
||
} else IIC1_Write_Byte(0xa0 + ((ReadAddr / 256) << 1)); //发送器件地址0xA0,写数据
|
||
|
||
IIC1_Wait_Ack();
|
||
IIC1_Write_Byte(ReadAddr % 256); //发送低地址
|
||
IIC1_Wait_Ack();
|
||
IIC1_Start();
|
||
|
||
if (EE_TYPE > AT24C16)IIC1_Write_Byte(0xa1); //进入接收模式
|
||
else IIC1_Write_Byte(0xa1 + ((ReadAddr / 256) << 1)); //进入接收模式
|
||
|
||
IIC1_Wait_Ack();
|
||
temp = IIC1_Read_Byte(1);
|
||
IIC1_Stop();//产生一个停止条件
|
||
return temp;
|
||
}
|
||
//在AT24CXX指定地址写一个数据
|
||
//WriteAddr:写入数据的目的地址
|
||
//data :要写入的数据
|
||
void AT24cxx_WriteOneByte(u16 WriteAddr, u8 data)
|
||
{
|
||
IIC1_Start();
|
||
|
||
if (EE_TYPE > AT24C16) {
|
||
IIC1_Write_Byte(0xa0);
|
||
IIC1_Wait_Ack();
|
||
IIC1_Write_Byte(WriteAddr / 256); //发送高地址
|
||
} else IIC1_Write_Byte(0xa0 + ((WriteAddr / 256) << 1));
|
||
|
||
IIC1_Wait_Ack();
|
||
IIC1_Write_Byte(WriteAddr % 256); //发送低地址
|
||
IIC1_Wait_Ack();
|
||
IIC1_Write_Byte(data);
|
||
IIC1_Wait_Ack();
|
||
IIC1_Stop();//产生一个停止条件
|
||
I2C_delay(2);
|
||
}
|
||
//在AT24CXX指定地址开始写入指定长度的数据
|
||
//该函数用于写入16位或32位的数据
|
||
//WriteAddr:开始写入的地址
|
||
//data :要写入的数据
|
||
//len :要写入数据的长度2,4
|
||
void AT24cxx_WriteLenByte(u16 WriteAddr, u32 data, u8 len)
|
||
{
|
||
u8 i;
|
||
|
||
for (i = 0; i < len; i++) {
|
||
AT24cxx_WriteOneByte(WriteAddr + i, (data >> (8 * i)) & 0xff);
|
||
}
|
||
}
|
||
//在AT24CXX指定地址开始读出指定长度的数据
|
||
//该函数用于读出16bit或者32bit的数据.
|
||
//ReadAddr :开始读出的地址
|
||
//返回值 :数据
|
||
//len :要读出数据的长度2,4
|
||
u32 AT24cxx_ReadLenByte(u16 ReadAddr, u8 len)
|
||
{
|
||
u8 i;
|
||
u32 temp = 0;
|
||
|
||
for (i = 0; i < len; i++) {
|
||
temp <<= 8;
|
||
temp += AT24cxx_ReadOneByte(ReadAddr + len - i - 1);
|
||
}
|
||
|
||
return temp;
|
||
}
|
||
|
||
//在AT24CXX指定地址开始写入指定长度的数据
|
||
//该函数用于写入指定的字节数
|
||
//WriteAddr:开始写入的地址
|
||
//buf :数据数组首地址
|
||
//len :要写入数据的个数
|
||
void AT24cxx_Write(u16 WriteAddr, u8 *buf, u16 len)
|
||
{
|
||
u16 i;
|
||
|
||
for (i = 0; i < len; i++) {
|
||
IWDG_Feed();
|
||
AT24cxx_WriteOneByte(WriteAddr, *buf);
|
||
WriteAddr++;
|
||
buf++;
|
||
}
|
||
}
|
||
//在AT24CXX指定地址开始读出指定长度的数据
|
||
//该函数用于读出指定的字节数
|
||
//ReadAddr:开始读出数据的地址
|
||
//len :要写入数据的个数
|
||
//buf :数据数组首地址
|
||
void AT24cxx_Read(u16 ReadAddr, u8 *buf, u16 len)
|
||
{
|
||
while (len--) {
|
||
IWDG_Feed();
|
||
*buf++ = AT24cxx_ReadOneByte(ReadAddr++);
|
||
}
|
||
}
|
||
//检查AT24CXX是否正常
|
||
//这里用了24XX的第一个地址(0)来存储标志字.
|
||
//返回1:检测失败
|
||
//返回0:检查成功
|
||
u8 AT24cxx_Check(void)
|
||
{
|
||
u8 temp1, temp2;
|
||
AT24cxx_WriteOneByte(0x010, 0x55);
|
||
temp1 = AT24cxx_ReadOneByte(0x010); //避免每次开机都写AT24CXX
|
||
temp2 = temp1;
|
||
|
||
if (temp2 == 0x55)return 0;
|
||
else {
|
||
AT24cxx_WriteOneByte(0x010, 0x55);
|
||
temp1 = AT24cxx_ReadOneByte(0x010);
|
||
temp2 = temp1;
|
||
|
||
if (temp2 == 0x55)return 0;
|
||
}
|
||
|
||
return 1;
|
||
}
|
||
|
||
//产生IIC起始信号
|
||
static void IIC1_Start(void)
|
||
{
|
||
|
||
IIC_SDA1;
|
||
IIC_SCL1;
|
||
I2C_delay(4);
|
||
IIC_SDA0;
|
||
I2C_delay(4);
|
||
IIC_SCL0;
|
||
I2C_delay(4);
|
||
}
|
||
//产生IIC停止信号
|
||
static void IIC1_Stop(void)
|
||
{
|
||
IIC_SDA0;
|
||
IIC_SCL1;
|
||
I2C_delay(2);
|
||
IIC_SDA1;
|
||
I2C_delay(4);
|
||
// IIC_SCL0;
|
||
}
|
||
//返回1,接收应答失败,返回0,接收应答成功
|
||
static u8 IIC1_Wait_Ack(void)
|
||
{
|
||
u8 i;
|
||
SDA_IN();
|
||
IIC_SCL0;
|
||
I2C_delay(2);
|
||
IIC_SCL1;
|
||
I2C_delay(2);
|
||
|
||
while (Read_IIC_SDA()) {
|
||
i++;
|
||
|
||
if (i > 250) {
|
||
|
||
IIC1_Stop();
|
||
return 1;
|
||
}
|
||
}
|
||
|
||
IIC_SCL0;
|
||
I2C_delay(2);
|
||
return 0;
|
||
}
|
||
//产生ACK应答
|
||
static void IIC1_Ack(void)
|
||
{
|
||
IIC_SCL0;
|
||
SDA_OUT();
|
||
IIC_SDA0;
|
||
I2C_delay(2);
|
||
IIC_SCL1;
|
||
I2C_delay(2);
|
||
IIC_SCL0;
|
||
}
|
||
//不产生ACK应答
|
||
static void IIC1_NAck(void)
|
||
{
|
||
IIC_SCL0;
|
||
SDA_OUT();
|
||
IIC_SDA1;
|
||
I2C_delay(2);
|
||
IIC_SCL1;
|
||
I2C_delay(2);
|
||
IIC_SCL0;
|
||
}
|
||
//IIC发送一个字节
|
||
//返回从机有无应答
|
||
//0,有应答
|
||
//1,无应答
|
||
void IIC1_Write_Byte(u8 dat)
|
||
{
|
||
u8 t;
|
||
SDA_OUT();
|
||
I2C_delay(2);
|
||
|
||
for (t = 0; t < 8; t++) {
|
||
IIC_SCL0;
|
||
|
||
if (dat & 0x80) {
|
||
IIC_SDA1;
|
||
} else {
|
||
IIC_SDA0;
|
||
}
|
||
|
||
I2C_delay(2);
|
||
IIC_SCL1;
|
||
dat <<= 1;
|
||
I2C_delay(2);
|
||
|
||
}
|
||
|
||
IIC_SCL0;
|
||
I2C_delay(2);
|
||
}
|
||
//读1个字节,ack=0时,发送ACK,ack=1,发送NACK
|
||
u8 IIC1_Read_Byte(unsigned char ack)
|
||
{
|
||
u8 i, receive;
|
||
SDA_IN();//SDA设为输入
|
||
IIC_SDA0;
|
||
I2C_delay(2);
|
||
|
||
for (i = 0; i < 8; i++) {
|
||
IIC_SCL0;
|
||
I2C_delay(2);
|
||
IIC_SCL1;
|
||
receive <<= 1;
|
||
I2C_delay(2);
|
||
|
||
if (Read_IIC_SDA())receive++;
|
||
|
||
I2C_delay(2);
|
||
}
|
||
|
||
IIC_SDA1;
|
||
I2C_delay(2);
|
||
IIC_SCL0;
|
||
I2C_delay(2);
|
||
|
||
if (!ack)
|
||
IIC1_Ack();
|
||
else
|
||
IIC1_NAck();
|
||
|
||
return receive;
|
||
}
|
||
#endif
|