本帖最后由 小智 于 2015-7-4 14:23 编辑
- //本程序是在看郭天祥老师视频后编制的,程序在郭老师的基础上做了细微的变动
- //并在部分语句后添加了自己的理解,如果有不妥欢迎大家指正出来,谢谢!!!
- //程序包含的内容很简单,只是向AT24c02中写入一个字节的数据,然后输出这个数据,并赋给P1口输出
- //虽然是51程序,但愿对刚接触IIC通信的朋友有所帮助。
- //邮箱:[email protected]
- #include <reg52.h>
- #define uchar unsigned char
- sbit scl=P2^1;//定义时钟线
- sbit sda=P2^0;//定义数据线
- void delay()//
- {;;}
- void delay_(uchar x)
- {
- uchar a,b;
- for(a=x;a>0;a--)
- for(b=100;b>0;b--);
- }
- void start()//开始,开始的信号为时钟信号高的状态下,数据线一个下降沿 不用应答
- {
- sda=1;
- delay();
- scl=1;
- delay();
- sda=0;
- delay();
- }
- void stop()//终止,终止信号为时钟信号搞得状态下,数据线一个上升沿 不用应答
- {
- sda=0;
- delay();
- scl=1;
- delay();
- sda=1;
- delay();
- }
- /***********************************************************************************************************************************/
- //每次上位机要向下位机读、写数据时都要等待下位机回应(即下位机将数据线sda置低),但是下位机要是一直不回应低上位机就不管了,毕竟有主动权嘛
- /***************************************************************************************************************************************/
- void respons()//应答
- {
- uchar i;
- scl=1;
- delay();
- while((sda==1)&&(i<250))i++;//如果下位机应答了会将数据线拉低
- scl=0;
- delay();
- }
- void init()//初始化时将数据线和时钟线都拉高
- {
- sda=1;
- delay();
- scl=1;
- delay();
- }
- void write_byte(uchar date)//写一个字节 需要应答
- {
- uchar i,temp;
- temp=date;
- for(i=0;i<8;i++)
- {
- scl=0; //一个时钟完成一位数据sda的传输,一位数据sda在一个时钟scl内是不允许变化的
- delay();
- temp=temp<<1;//左移时,左边溢出的那一位数据会自动保存在PSW的CY位,右边自动补0
- sda=CY;//赋给数据线,将要传出到下位机了
- delay();
- scl=1;
- delay();
- }
- scl=0;//这个语句是为了满足最后一位数据sda传送时时钟信号scl信号跳变的完整性 低-高-低
- delay();
- sda=1;//置1是为了接收应答信号,应答信号sda的引脚会识别低信号
- delay();
- }
- /***********************************************************************/
- //每个字节共有8位数据,要循环8次才能将一个字节的数据读走。
- //数据的写入和读走都要保证数据的稳定,
- /***********************************************************************/
- uchar read_byte()//读一个字节
- {
- uchar i,k;
- scl=0;
- delay();
- sda=1;//数据线释放,这个引脚在读数据线时要释放掉(51中默认为高),它的高低要有下位机决定,这样才能读出下位机的数据
- for(i=0;i<8;i++)
- {
- scl=1;//高线平时才允许读数据
- delay();
- //j=sda;
- k=(k<<1)|sda;//每执行这个语句,都会将刚读取的那位(sda)放在k的低位上
- scl=0;
- delay();
- }
- return k;
- }
- void write_add(uchar address,uchar date_)
- {
- start();//起始信号 此时主机想向众多从机说话。。。
- write_byte(0xa0);//写器件地址,高四位是1010,接着三位是000;因为是写,所以最后一位也是0 上位机问众多下位机:你们有谁叫0xa0的吗?我要向你发送点数据!
- respons();//发完地址和写请求后等待应答 0xa0回答道:真的啊,那快点发过来
- write_byte(address);//写该器件存储取地址 主机向从机说道:我要向你的address位发东西了哈!are you ok??
- respons();//等待回应 从机回答道:准备好啦!(内心一阵窃喜)
- write_byte(date_);//写数据喽 主机开始写数据了。。。
- respons(); // 从机向主机说道:谢谢你,我都收到啦,嘻嘻。。。
- stop(); // 此时主机停止发送数据了。。。。
- }
- /*****************************************************/
- //主机要向从机读数据
- //对比发送和接收数据两个过程不难发现,貌似接收更难一些,是不是索取比给予都要难一些,单片机通信也是????
- /*****************************************************/
- uchar read_add(uchar address_)
- {
- uchar a;
- start(); // 此时主机准备向众多下位机说话。。。
- write_byte(0xa0);//器件地址 上位机问众多下位机:你们有谁叫0xa0的吗?
- respons(); // 下位机向上位机回答道:我是0xa0,你找我有什么事吗?
- write_byte(address_);//储存区地址 上位机向0xa0说道:我打算看看你第address_位数据(以000数据为起点啊)。
- respons(); // 下位机0xa0回答道:好的,随时恭候。
-
- start(); // 此时上位机在开始准备了。。。
- write_byte(0xa1);//写器件地址,要读数据 上位机准备好了,然后对下位机说:你可以接收数据了,你把数据发过来吧!
- respons(); // 下位机回答道:好的,已发送,请注意查收
- a=read_byte();//都会来的值赋给P1引脚 此时主机开始接收了。。。
- stop(); // 接收完了一个字节的数据,就停下来通信了
- return a; // 接着返回到主程序中对接收到的数据进一步处理
-
- }
- void main()
- {
- init();//数据线,时钟线拉高
- write_add(23,0x00);//物理地址的第23个地址存入数据0x02
- delay_(100);//该延迟是为了给写入过程、读出过程留足一定的时间,也就是给硬件喘口气
- P1=read_add(23);//将读出的数据输出到引脚
- while(1);//此程序就让它运行一次
- }
-
复制代码
|