📄 at24c64.c
字号:
/* --------------------------------------------------------
下面是24C64的读写代码,端口已在BA_C_Port.h里定义
sbit SCK_24 =P3^6; //24C64的 时钟端口,静态0
sbit SDA_24 =P3^7; //24C64的 数据端口,静态0
---------------------------------------------------------*/
#include <reg52.h>
#include <intrins.h> //此头可以使用_nop_() 或一些循环左移;循环右移函数
#include <stdio.h> //此头用于printf
#include <stdlib.h>
#include <time_delay_12M.h>
#include <BA_D_Port.h>
void I2C_Start(void); //开始信号
void I2C_Stop(void); //停止信号
void I2C_Ack(void); //主机应答=0
void I2C_Nack(void); //主机反应答=1
unsigned char I2C_Test(void)reentrant ; //测试芯片的应答,返回应为=0
void I2C_Init(void); //I2C初始化
bit I2C_Send_Byte( unsigned char); //发送1个字节,返回应答位
unsigned char I2C_Get_Byte(void); //接受1个字节,返回接收的数据
void AT24_W_1Byte(unsigned int , unsigned char ); //向某一个地址写入1个字节
void AT24_W_2Byte(unsigned int , unsigned char,unsigned char ); //向某一个地址写入2个字节
void AT24_W_2Byte_2(unsigned int , unsigned char *); //向某一个地址写入2个字节另一种方式
unsigned char AT24_R_1Byte(unsigned int); //从芯片的某地址读出1个字节数据,
void AT24_R_2Byte(unsigned int , unsigned char * ); //从芯片的某地址读出2个字节数据并存入数组中
void AT24_R_NByte(unsigned int , unsigned char , unsigned char * ); //从芯片的某地址读出n个字节数据并存入数组中
//-----------------------------------------------
void I2C_Start(void) //开始信号
{
SDA_24 =1;
_nop_();
SCK_24 =1;
_nop_();
_nop_();
_nop_();
_nop_();
SDA_24 = 0;
_nop_();
_nop_();
_nop_();
_nop_();
SCK_24 = 0;
_nop_();
}
//------------------------------------------------
void I2C_Stop(void) //停止信号
{
SDA_24 = 0;
_nop_();
SCK_24 = 1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SDA_24 = 1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCK_24 = 0;
_nop_();
}
//-----------------------------------------------
void I2C_Init(void) //I2C初始化
{
SCK_24 = 0;
_nop_();
SDA_24 = 0;
_nop_();
SCK_24 = 1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SDA_24 = 1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCK_24 = 0; //时钟为0
SDA_24 = 0; //数据为0
}
//------------------------------------------------
void I2C_Ack(void) //主机应答信号为0
{
SDA_24=0;
_nop_();
SCK_24=1;
_nop_();
_nop_();
_nop_();
_nop_();
SCK_24=0;
_nop_();
}
//------------------------------------------------
void I2C_Nack(void) //主机反应答信号为1
{
SDA_24=1;
_nop_();
SCK_24=1;
_nop_();
_nop_();
_nop_();
_nop_();
SCK_24=0;
_nop_();
}
//----------------- 检测芯片的应答信号,有效信号应为0 (此处应用了超时处理)----------
unsigned char I2C_Test(void) reentrant //注意:再入函数不可用于 bit
{
unsigned char errtime=250; // 超时检测定位250次
unsigned char bit_test;
SDA_24=1; // 置数据线为输入方式
_nop_();
SCK_24=1;
while(SDA_24) // 等待应答为0
{ errtime-- ;
if( ! errtime) // ! errtime 等价与 errtime==0
{ I2C_Stop();
bit_test = 1;
return bit_test ; //retuen 即时中止本函数的运行,退出本函数并返回1
}
}
bit_test = 0; //把“SDA_24”线上的信号传给bit_test,也可用F0,CY
SCK_24 =0;
return bit_test; //CY是位累加器,也可以用F0,在PSW里面有定义,
}
//----------------------------------------------------------------------
//------------- 发送一个字节,并且检测芯片的应答信号 --------------------
bit I2C_Send_Byte( unsigned char d)
{
unsigned char i = 8;
SCK_24 = 0; //时钟信号为0
while( i-- ) //发送8次
{
if ( d & 0x80 ) //0x80=1000 0000
SDA_24 =1;
else
SDA_24 =0;
SCK_24 = 1; //时钟信号为1
_nop_();
_nop_();
_nop_();
SCK_24 = 0; //时钟信号为0
d = d << 1; //非循环左移一位
}
return (I2C_Test()); //返回检测信号为0正常,如果为1不对
}
//----------------------------------------------------------------------------
//--------- 接收一个字节,这里不能产生应答信号,应答信号有可能是0或1 ----------
unsigned char I2C_Get_Byte(void)
{
unsigned char i = 8;
unsigned char d = 0;
SCK_24 = 0; //时钟信号为0
SDA_24 = 1; //置数据线为输入方式
while ( i-- ) //接收8次信号
{
d = d << 1;
_nop_();
SCK_24 =1; //时钟=1
_nop_();
_nop_();
if ( SDA_24 )
{ d++; }
SCK_24 =0; //时钟=0
}
return d; //返回1个字节数据
}
//---------------------------------------------------------------------------
//------------------向AT24C64的地址 写入1个字节数据 -------------------------
void AT24_W_1Byte(unsigned int AT24_addr, unsigned char AT24_data)
{
I2C_Start(); // 启动信号
I2C_Send_Byte( 0xa0 ); // A0=1010,0000 高4位是芯片时序,次3位是芯片地址,末位0=写,1=读
I2C_Send_Byte( AT24_addr / 256 ); // 发送高字节地址 (注意/的使用=整数,余数去掉)
I2C_Send_Byte( AT24_addr % 256 ); // 发送低字节地址 (注意%的使用=余数,)
I2C_Send_Byte( AT24_data ); // 发送数据
I2C_Stop(); // 停止信号
T_2ms(); // 延迟2ms
}
//---------------------------------------------------------------------------
//--------------- 向AT24C64的地址 写入1个字节数据 ---------------------------
//--------------- 本函数仅供串口调用 ----------------------------------------
void COM_AT24_W_1Byte(unsigned int AT24_addr, unsigned char AT24_data)
{
I2C_Start(); // 启动信号
I2C_Send_Byte( 0xa0 ); // A0=1010,0000 高4位是芯片时序,次3位是芯片地址,末位0=写,1=读
I2C_Send_Byte( AT24_addr / 256 ); // 发送高字节地址 (注意/的使用=整数,余数去掉)
I2C_Send_Byte( AT24_addr % 256 ); // 发送低字节地址 (注意%的使用=余数,)
I2C_Send_Byte( AT24_data ); // 发送数据
I2C_Stop(); // 停止信号
T_2ms(); // 延迟2ms
}
//------------------------------------------------------------------------------------
//------------------向AT24C64的地址 写入2个字节数据 “第一种方式” -------------------
void AT24_W_2Byte(unsigned int AT24_addr, unsigned char AT24_data1,unsigned char AT24_data2 )
{
I2C_Start(); // 启动信号
I2C_Send_Byte( 0xa0 ); // A0=1010,0000 高4位是芯片时序,次3位是芯片地址,末位0=写,1=读
I2C_Send_Byte( AT24_addr / 256 ); // 发送高字节地址 (注意/的使用=整数,余数去掉)
I2C_Send_Byte( AT24_addr % 256 ); // 发送低字节地址 (注意%的使用=余数,)
I2C_Send_Byte( AT24_data1 ); // 发送数据1
I2C_Send_Byte( AT24_data2 ); // 发送数据2
I2C_Stop(); // 停止信号
T_2ms();
// 延迟2ms
}
//--------------------------------------------------------------------------------------
//----------------- 向AT24C64的地址 写入N个字节数据 ------------------------------------
//------------- *AT24_d 为指针变量 (指向“ 数组 ”) ----------------------------------
void AT24_W_NByte(unsigned int AT24_addr, unsigned char Count, unsigned char *char_d)
{
unsigned char i;
I2C_Start();
I2C_Send_Byte( 0xa0 ); //0xa0 向芯片写数据
I2C_Send_Byte( AT24_addr / 256 ); //高字节地址
I2C_Send_Byte( AT24_addr % 256 ); //低字节地址
for(i=0; i<Count ;i++) //循环 Count次
{
I2C_Send_Byte( char_d[i] ); //“指针变量带下标” == “数组带下标”
}
I2C_Stop(); //停止信号
T_2ms(); // 延迟2ms
}
//--------------------------------------------------------------------------------------
//----------------- 向AT24C64的地址 写入N个字节数据 ------------------------------------
//------------- *AT24_d 为指针变量 (指向“ 数组 ”) ----------------------------------
//------------- 本函数仅供串口调用 ----------------------------------------------------
void COM_AT24_W_NByte(unsigned int AT24_addr, unsigned char Count, unsigned char *char_d)
{
unsigned char i;
I2C_Start();
I2C_Send_Byte( 0xa0 ); //0xa0 向芯片写数据
I2C_Send_Byte( AT24_addr / 256 ); //高字节地址
I2C_Send_Byte( AT24_addr % 256 ); //低字节地址
for(i=0; i<Count ;i++) //循环 Count次
{
I2C_Send_Byte( char_d[i] ); //“指针变量带下标” == “数组带下标”
}
I2C_Stop(); //停止信号
T_2ms(); // 延迟2ms
}
//----------------------------------------------------------------------------------------
//--------------------------从AT24C64的地址 读出1个字节数据,并返回 ----------------------
unsigned char AT24_R_1Byte(unsigned int AT24_addr)
{
unsigned char i;
I2C_Start();
I2C_Send_Byte( 0xa0 ); //0xa0 向芯片写数据
I2C_Send_Byte( AT24_addr / 256 ); //高字节地址
I2C_Send_Byte( AT24_addr % 256 ); //低字节地址
I2C_Start();
I2C_Send_Byte( 0xa1 ); //0xa1 从芯片读数据
i = I2C_Get_Byte(); //接受一个数据
I2C_Nack();
I2C_Stop();
return i;
}
/*
//-----------------------------------------------------------------------------------------
//-----------------从AT24C64的地址 读出2个字节数据 并存入定义的“ 数组”中 ----------------
void AT24_R_2Byte(unsigned int AT24_addr, unsigned char *char_d )
{
I2C_Start();
I2C_Send_Byte( 0xa0 ); //0xa0 向芯片写数据
I2C_Send_Byte( AT24_addr / 256 ); //高字节地址
I2C_Send_Byte( AT24_addr % 256 ); //低字节地址
I2C_Start();
I2C_Send_Byte( 0xa1 ); //0xa0 从芯片读数据
char_d[0] = I2C_Get_Byte(); //读取数据“指针变量的下标” 等价 “数组的下标”
I2C_Ack(); //主机产生一个应答信号0
char_d[1] = I2C_Get_Byte(); //读取数据“指针变量的下标” 等价 “数组的下标”
I2C_Nack(); //主机产生一个非应答信号1
I2C_Stop();
}
*/
//-----------------------------------------------------------------------------------------
//-----------------从AT24C64的地址 读出n个字节数据 并存入定义的“ 数组”中 ----------------
void AT24_R_NByte(unsigned int AT24_addr, unsigned char Count, unsigned char *char_d )
{
unsigned char i;
I2C_Start();
I2C_Send_Byte( 0xa0 ); //0xa0 向芯片写数据
I2C_Send_Byte( AT24_addr / 256 ); //高字节地址
I2C_Send_Byte( AT24_addr % 256 ); //低字节地址
I2C_Start();
I2C_Send_Byte( 0xa1 ); //0xa0 从芯片读数据
for(i=0; i< Count ; i++)
{
char_d[i] = I2C_Get_Byte(); //读取数据“指针变量的下标” 等价 “数组的下标”
if (i != (Count-1)) //最后一个数据不产生应答信号
{ I2C_Ack(); } //主机产生一个应答信号0
}
/*----------------上面的程序段也可以用下面的语句 --------------------------------------
i=0;
while(Count--)
{
char_d[i] = I2C_Get_Byte();
if(Count != 1) //最后一个数据不产生应答信号
{ I2C_Ack(); }
i++;
}
*/ //----------------------------------------------------------------------------------
I2C_Nack(); //主机产生一个非应答信号1
I2C_Stop();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -