打印

经过一个星期的努力成果供大家分享24c02_I2C

[复制链接]
2801|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
t86964988|  楼主 | 2009-12-26 15:33 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
//////////////////////////////////////////////////////
//基于I2C传输协议24c02读写操作程序,硬件为51单片机P1.0接
//24c02的WP端口,P1.1接24c02的SCL,P1.2接24c02的SDA,
//24C02地址口A0,A1,A2全接高电平;下面程序已经经过硬件测试
//欢迎大家参考学习,如有copy请注明来源;
//    Copyright 田峰 QQ:413336413
/////////////////////////////////////////////////////////
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define TRUE 1
#define FALSE 0
sbit WP=P1^0;
sbit scl=P1^1;
sbit sda=P1^2;
void delay(uchar z)
{
uchar x,y;
for(x=z;x>0;x++)
  for(y=100;y>0;y++);
}
void start()
{
sda=1;
_nop_();
scl=1;//起始建立时间大于4.7us
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
sda=0;//起始锁定时间大于4us
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
scl=0;
_nop_();
}
void stop()
{
sda=0;
_nop_();
scl=1;//发送停止条件的时钟信号,停止总线时间大于4us
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
sda=1;//结束总线
_nop_();//保证一个终止信号和起始信号的空闲时间大于4.7us
_nop_();
_nop_();
_nop_();
}
uchar cheak_ack()//主机发送一个字节数据后检查应答位
{
  bit FO=0;
sda=1;//释放数据线等待接收应答信号ACK
_nop_();
_nop_();
scl=1;//应答位时钟拉高
_nop_();
_nop_();
F0=sda;
scl=0;
_nop_();
_nop_();
if(F0==1)
return FALSE;
else
return TRUE;
}
void master_ack()//主机接收一个字节数据应答
{
sda=0;
scl=1;
_nop_();
_nop_();
_nop_();
_nop_();
scl=0;
sda=1;
}
void master_uack()//主机接收一个字节数据非应答
{
sda=1;
scl=1;
_nop_();
_nop_();
_nop_();
_nop_();
scl=0;
sda=0;
}
void write_byte(uchar date)//在EEPROM上写一个字节数据
{
uchar i,temp;
temp=date;
for(i=0;i<8;i++)
{
  temp=temp<<1;
  sda=CY;
  _nop_();
  scl=1;
  _nop_();
  scl=0;
  _nop_();
}
}
uchar read_byte()//从EEPROM上读一个字节数据
{
uchar i,j,k;
sda=1;
_nop_();
for(i=0;i<8;i++)
{
  scl=1;
  _nop_();
  k=sda;
  scl=0;
  _nop_();
  j=(j<<1)|k;
}
return j;
}
void write_add(uchar address,uchar date)//在EEPROM的地址address上写数据date
{
bit acktemp;
start();
write_byte(0xae);
acktemp=cheak_ack();
write_byte(address);
acktemp=cheak_ack();
write_byte(date);
acktemp=cheak_ack();
stop();
}
uchar read_add(uchar address)//从EEPROM的地址address上读数据date
{
bit acktemp;
uchar date;
start();
write_byte(0xae);
acktemp=cheak_ack();
write_byte(address);
acktemp=cheak_ack();
start();
write_byte(0xaf);
master_ack();
date=read_byte();
master_uack();
stop();
return date;
}
void main()
{
WP=0;
P2=1;
write_add(23,0x71);
delay(100);
P0=read_add(23);
while(1);
}

相关帖子

沙发
iC921| | 2009-12-26 16:17 | 只看该作者
祝贺楼主!
说一下效果吧。

使用特权

评论回复
板凳
NE5532| | 2009-12-26 21:46 | 只看该作者
在21ic成长,回21ic分享,这就是这里的精神。

使用特权

评论回复
地板
chengfei21| | 2009-12-27 13:48 | 只看该作者
共同进步

使用特权

评论回复
5
jindulyscc| | 2010-3-31 09:36 | 只看该作者
问一个问题哈 楼主写的check_ack函数有返回值,表示是否应答我还算明白
但是在write_add 写函数里 acktemp=cheak_ack(); 这条语句有什么作用? 小弟不太明白,
难道是没有应答得话,会return false  然后程序运行到这里就不进行写操作了吗?直到应答为止?
新手。。呵呵

使用特权

评论回复
6
IC_99| | 2010-3-31 15:50 | 只看该作者
我也没在write_add 函数里看出acktemp=cheak_ack(); 这句的实际作用,acktemp接收到返回值以后没有使用上...

使用特权

评论回复
7
komad| | 2010-3-31 20:39 | 只看该作者
LZ把_nop_();做成函数更清楚了,呵呵
delayus(uchar x)
{
      while(x--)
         _nop_();
}

使用特权

评论回复
8
efen| | 2010-4-1 23:58 | 只看该作者
LZ把_nop_();做成函数更清楚了,呵呵
delayus(uchar x)
{
      while(x--)
         _nop_();
}
komad 发表于 2010-3-31 20:39

这样不太好,调用和返回需要周期

使用特权

评论回复
9
fangyan2010| | 2010-4-13 21:56 | 只看该作者
楼主你好!我是个菜鸟,我冒昧的问一句:bit F0=0;是不是对某个字节定义呢?我以前没有看过这样的变量类型。谢谢!

使用特权

评论回复
10
fangyan2010| | 2010-4-13 22:28 | 只看该作者
楼主你好!小弟不才,冒昧问一句:bit FO=0;中bit是什么数据类型?盼回复,谢谢啦!

使用特权

评论回复
11
yumeinian| | 2010-5-31 15:35 | 只看该作者
想问下,你的ack返回时错误的话,也是在继续执行忙吗?那你在这里检测和没有检测不是一个样了吗?

使用特权

评论回复
12
smihtctecg| | 2010-6-20 11:28 | 只看该作者
正在看STM32的I2C接口相关的资料,多谢楼主分享!

使用特权

评论回复
13
new1988| | 2010-6-21 11:42 | 只看该作者
本帖最后由 new1988 于 2010-6-21 11:43 编辑

10# fangyan2010
bit :位数据类型,只有0和1两种状态。是单片机中一种特殊的数据类型,在标准C里面没有此数据类型。 在51单片机里面内部数据存储区的20H~2FH地址范围的存储器可以进行位寻址。而bit数据类型就是定义在此区域的。

使用特权

评论回复
14
zjswuyunbo| | 2010-6-25 17:06 | 只看该作者
恭喜

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

19

主题

77

帖子

1

粉丝