24c02.c
来自「基于iic总线的eeprom at24c02的读写程序」· C语言 代码 · 共 306 行
C
306 行
/*====================================
下为此程序的说明
功能:I2C总线驱动
版本:Ver 1.0
日期:2007年
说明:由杨德富编写,在硬件(24C04)上通过。但是在PROTEUS中不通过。
====================================*/
#define uint unsigned int
#define uchar unsigned char
#include<reg52.h>
#include<intrins.h>
#include<absacc.h>
#define uchar unsigned char
#define uint unsigned int
#define NOP _nop_(); _nop_(); _nop_()
//定义数码管的段选
uchar code tab[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
//全局变量的定义
//uchar Step = 50;
bit ack; //应答信号检测
//位操作定义
sbit SDA = P1^0;
sbit SCL = P1^1; //24C04的操作线
/*====================================
非关键函数申明
====================================*/
void Initial(void); //系统初始化
void Delay(uint n); //普通延时
void Disp(uchar num); //显示数据
/*====================================
24C04函数申明
====================================*/void Start_I2C(void);
void Stop_I2C(void);
void SendByte(uchar fdata); /*24C04子函数*/
uchar RecByte(void);
void Ack_I2C(bit a);
bit SendStr(uchar Slave, uchar SubAddress, uchar *Source, uchar Num);
bit RecStr(uchar Slave, uchar SubAddress, uchar *Source, uchar Num);
/*====================================
函数功能:主函数
入口参数:
说 明 :
=====================================*/
main()
{
uchar Rec_data[2];
uchar Sen_data[2]={1,4};
uchar *ptr;
ptr = Sen_data;
Initial(); //初始化
SendStr(0xa0, 0x20,ptr,2); /*24C04的20H*/
Delay(100);
Delay(100);
ptr=Rec_data;
RecStr(0xa1,0x20,ptr,2);
while(1)
{
P2=tab[Rec_data[0]];
}
}
//初始化
void initial(void)
{
P1=0xff;
P0=0xff;
P2=0xff;
P3=0xff;
}
//////////////////////////////////////
void Delay(uint n) //延时主函数
{
uchar i,k;
for(k=0;k<n;k++)
{
for(i=0;i<200;i++);
}
}
/*************************************************************************************
对24C04进行读写操作子函数
*************************************************************************************/
/*******************************************************************
void Start_I2C();
启动I2C总线,即发送I2C起始条件。
********************************************************************/
void Start_I2C()
{
SDA = 1; /*发送起始条件的数据信号*/
_nop_();
SCL = 1;
_nop_(); /* 起始条件建立时间大于4us,延时 */
_nop_();
_nop_();
_nop_();
_nop_();
SDA = 0; /* 发送起始信号 */
_nop_(); /* 起始条件锁定时间大于4 us */
_nop_();
_nop_();
_nop_();
_nop_();
SCL = 0; /* 准备发送或接收数据 */
_nop_();
_nop_();
}
/*******************************************************************
void Stop_I2C();
结束I2C总线,即发送I2C结束条件。
********************************************************************/
void Stop_I2C()
{
SDA = 0; /* 发送结束条件的数据信号 */
_nop_(); /* 发送结束条件的时钟信号 */
SCL = 1; /* 结束条件建立时间大于4 us */
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SDA = 1; /* 发送I2C总线结束信号 */
_nop_();
_nop_();
_nop_();
_nop_();
}
/*******************************************************************
void SendByte(uchar data);
将数据data发送出去,可以是地址,也可以是数据,发完后等待应答,并对此状态
位进行操作。(不应答或非应答都使ack = 0) 发送数据正常,ack=1;ack=0
表示接收器无应答或损坏。
********************************************************************/
void SendByte(uchar fdata)
{
uchar BitCount;
ack=0;
for(BitCount = 0; BitCount < 8; BitCount ++) /* 要传送的数据长度为8位 */
{
if((fdata << BitCount) & 0x80) SDA = 1; /* 判断发送位 */
else SDA = 0;
_nop_();
SCL = 1; /* 置时钟线为高,通知被控器开始接收数据位 */
_nop_();
_nop_(); /* 保证时钟高电平周期大于4 us */
_nop_();
_nop_();
_nop_();
SCL = 0;
}
_nop_();
_nop_();
SDA = 0; /* 8位发送完后释放数据线,准备接收应答位*/
SCL=0;
_nop_();
_nop_();
SCL=1;
_nop_();
_nop_();
_nop_();
NOP;
if(SDA == 1) ack = 0; /* 无应答信号 */
else ack = 1; /* 判断是否接收到应答信号*/
ack=1;
SCL=0;
_nop_();
_nop_();
}
/*******************************************************************
uchar RecByte();
功能:
用来接收从器件传来的数据,并判断总线错误(不发应答信号),发完后请用
应答函数。
********************************************************************/
uchar RecByte()
{
uchar RecData;
uchar BitCount;
RecData = 0;
SDA = 1; /* 置数据线为输入方式 */
for(BitCount = 0; BitCount < 8; BitCount ++)
{
_nop_();
SCL=0; /* 置时钟线为低,准备接收数据位 */
_nop_();
_nop_(); /* 时钟低电平周期大于4.7us */
_nop_();
_nop_();
_nop_();
SCL= 1; /* 置时钟线为高使数据线上数据有效 */
_nop_();
_nop_();
if(SDA==1) RecData = RecData +1; /* 读数据位,接收的数据位放入retc中 */
RecData = RecData << 1;
_nop_();
_nop_();
}
SCL= 0;
_nop_();
_nop_();
return(RecData);
}
/********************************************************************
void Ack_I2C(bit a);
主控器进行应答信号,,(可以是应答或非应答信号)
/********************************************************************/
void Ack_I2C(bit a)
{
if(a == 0) SDA = 0; /* 在此发出应答或非应答信号 */
else SDA=1;
_nop_();
_nop_();
_nop_();
SCL = 1;
_nop_();
_nop_(); /* 时钟低电平周期大于4us */
_nop_();
_nop_();
_nop_();
SCL = 0; /* 清除时钟线,以便继续接收 */
_nop_();
_nop_();
}
/*******************************************************************
bit SendStr(uchar Slave, uchar SubAddress, uchar *Source, uchar Num);
从启动总线到发送地址,子地址,数据,结束总线的过程。
Slave--从器件地址
SubAddress--子地址
Source--指向发送内容的指针
Num--发送字节个数
返回值:
如果返回1表示操作成功,否则操作有误。
********************************************************************/
bit SendStr(uchar Slave, uchar SubAddress, uchar *Source, uchar Num)
{
uchar i;
Start_I2C(); /* 启动总线 */
SendByte(Slave); /* 发送器件地址 */
if(ack == 0) return(0);
SendByte(SubAddress); /* 发送器件子地址 */
if(ack == 0) return(0);
for(i = 0; i < Num; i++)
{
SendByte(*Source); /* 发送数据 */
if(ack == 0) return(0);
Source ++;
}
Stop_I2C(); /* 结束总线 */
return(1);
}
/*******************************************************************
bit RecStr(BYTE Slave, BYTE SubAddress, BYTE *Source, BYTE Num);
从启动总线到发送地址,子地址,读数据,结束总线的过程。
参数:
Slave--从器件地址。
SubAddress--子地址
Source--指向读出的内容放入的存储区的指针
Num--读字节个数。
返回值:
如果返回1表示操作成功,否则操作有误。
********************************************************************/
bit RecStr(uchar Slave, uchar SubAddress, uchar *Source, uchar Num)
{
uchar i;
Start_I2C(); /* 启动总线 */
SendByte(Slave-1); /* 发送器件地址 */
if(ack == 0) return(0);
SendByte(SubAddress); /* 发送器件子地址 */
if(ack == 0) return(0);
Start_I2C();
SendByte(Slave);
if(ack == 0) return(0);
for(i = 0; i < Num-1; i++)
{
*Source = RecByte(); /* 接收数据 */
Ack_I2C(0); /* 发送就答位 */
Source++;
}
*Source =RecByte();
Ack_I2C(1); /* 发送非应位 */
Stop_I2C(); /* 结束总线 */
return(1);
}
/*****************************************************************************
--------------------------------程序结束-------------------------------------
*****************************************************************************/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?