jianghuai/SYSTEM/24cxx.c
2024-05-07 09:36:09 +08:00

290 lines
5.1 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 "24cxx.h"
#include "led.h"
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 = 5*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_PP;//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 :要写入数据的长度24
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;
}