51单片机普通IO口模拟IIC总线的程序实现

http://blog.csdn.net/sdwuyulunbi/article/details/6654469

IIC是由Philips公司发明的一种串行数据通信协议,仅使用两根信号线:SerialClock(简称SCL)和SerialData(简称SDA)。

IIC是总线结构,1个Master,1个或多个Slave,各Slave设备以7位地址区分,地址后面再跟1位读写位,表示读(=1)或者写(=0),所以我们有时也可看到8位形式的设备地址,此时每个设备有读、写两个地址,高7位地址其实是相同的。
IIC数据格式如下:
无数据:SCL=1,SDA=1;
开始位(Start):当SCL=1时,SDA由1向0跳变;
停止位(Stop):当SCL=1时,SDA由0向1跳变;
数据位:当SCL由0向1跳变时,由发送方控制SDA,此时SDA为有效数据,不可随意改变SDA;
当SCL保持为0时,SDA上的数据可随意改变;
地址位:定义同数据位,但只由Master发给Slave;
应答位(ACK):当发送方传送完8位时,发送方释放SDA,由接收方控制SDA,且SDA=0;
否应答位(NACK):当发送方传送完8位时,发送方释放SDA,由接收方控制SDA,且SDA=1。
当数据为单字节传送时,格式为:
开始位,8位地址位(含1位读写位),应答,8位数据,应答,停止位。
当数据为一串字节传送时,格式为:
开始位,8位地址位(含1位读写位),应答,8位数据,应答,8位数据,应答,……,8位数据,应答,停止位。
需要注意的是:
1、SCL一直由Master控制,SDA依照数据传送的方向,读数据时由Slave控制SDA,写数据时由Master控制SDA。当8位数据传送完毕之后,应答位或者否应答位的SDA控制权与数据位传送时相反。
2、开始位“Start”和停止位“Stop”,只能由Master来发出。
3、地址的8位传送完毕后,成功配置地址的Slave设备必须发送“ACK”。否则否则一定时间之后Master视为超时,将放弃数据传送,发送“Stop”。
4、当写数据的时候,Master每发送完8个数据位,Slave设备如果还有空间接受下一个字节应该回答“ACK”,Slave设备如果没有空间接受更多的字节应该回答“NACK”,Master当收到“NACK”或者一定时间之后没收到任何数据将视为超时,此时Master放弃数据传送,发送“Stop”。
5、当读数据的时候,Slave设备每发送完8个数据位,如果Master希望继续读下一个字节,Master应该回答“ACK”以提示Slave准备下一个数据,如果Master不希望读取更多字节,Master应该回答“NACK”以提示Slave设备准备接收Stop信号。
6、当Master速度过快Slave端来不及处理时,Slave设备可以拉低SCL不放(SCL=0将发生“线与”)以阻止Master发送更多的数据。此时Master将视情况减慢或结束数据传送。

下面是本人编写的单片机普通IO口模拟IIC总线的程序源代码:

[cpp]  view plain copy
  1. /* 
  2. ************************************************************************************ 
  3. Fuction:GPIO模拟iic bus,实现与AT24C02的数据通信 
  4. PS:该源代码是以STC89C52为平台编写的,可通过修改包含的头文件以适用于所有51系列单片机 
  5. SD:Jason 
  6. ************************************************************************************ 
  7. */  
  8. #include <reg52.h>  
  9. #include <string.h>  
  10. sbit sda = P2^0;  
  11. sbit scl = P2^1;  
  12. unsigned char table1[11]={0,1,2,3,4,5,6,7,8,9};  
  13. unsigned char table2[11];  
  14. void init();  
  15. void somenop();  
  16. void delay(unsigned char);  
  17. void start();  
  18. void stop();  
  19. void send_ack(unsigned char);  
  20. unsigned char rec_ack();  
  21. void write_byte(unsigned char);  
  22. unsigned char read_byte();  
  23. unsigned char write_add(unsigned char,unsigned char *,unsigned char);  
  24. unsigned char read_add(unsigned char,unsigned char *,unsigned char);  
  25.   
  26. void main()  
  27. {  
  28.     init();  
  29.     write_add(0x10,table1,10);  
  30.     delay(100);  
  31.     read_add(0x10,table2,10);  
  32.     while(1);  
  33. }  
  34. //端口初始化  
  35. void init()  
  36. {  
  37.     memset(table2,0,sizeof(table2));  
  38.     sda = 1;  
  39.     scl = 1;  
  40.     somenop();  
  41. }  
  42. //起始信号  
  43. void start()  
  44. {  
  45.     sda = 1;  
  46.     somenop();  
  47.     scl = 1;  
  48.     somenop();  
  49.     sda = 0;  
  50.     somenop();  
  51. }  
  52. //终止信号  
  53. void stop()  
  54. {  
  55.     sda = 0;  
  56.     somenop();  
  57.     scl = 1;  
  58.     somenop();  
  59.     sda = 1;  
  60.     somenop();  
  61. }  
  62. //主机发送应答信号  
  63. void send_ack(unsigned char ack)  
  64. {  
  65.     scl = 0;  
  66.     somenop();  
  67.     sda = ack;  
  68.     somenop();  
  69.     scl = 1;  
  70.     somenop();  
  71.     scl = 0;  
  72.     somenop();  
  73.     sda = 1;  
  74.     somenop();  
  75. }  
  76. //主机接收应答信号  
  77. unsigned char rec_ack()  
  78. {  
  79.     scl = 1;  
  80.     somenop();  
  81.     if(sda == 1)  
  82.     {  
  83.         scl = 0;  
  84.         delay(1);  
  85.         scl = 1;  
  86.         if(sda == 1)  
  87.             return 1;  
  88.     }  
  89.     else  
  90.         return 0;  
  91. }  
  92. //写一个字节  
  93. void write_byte(unsigned char dat)  
  94. {  
  95.     unsigned char i,a;  
  96.     a = dat;  
  97.     for(i=0;i<8;i++)  
  98.     {  
  99.         a = a<<1;  
  100.         scl = 0;  
  101.         somenop();  
  102.         sda = CY;  
  103.         somenop();  
  104.         scl = 1;  
  105.         somenop();  
  106.     }  
  107.     scl = 0;  
  108.     somenop();  
  109.     sda = 1;  
  110.     somenop();  
  111. }  
  112. //读一个字节  
  113. unsigned char read_byte()  
  114. {  
  115.     unsigned char i,a;  
  116.     scl = 0;  
  117.     somenop();  
  118.     sda = 1;  
  119.     somenop();  
  120.     for(i=0;i<8;i++)  
  121.     {  
  122.         scl = 1;  
  123.         somenop();  
  124.         a = (a<<1)|sda;  
  125.         scl = 0;  
  126.         somenop();  
  127.     }  
  128.     return a;  
  129. }  
  130. //向add地址写入len长度的dat数据  
  131. unsigned char write_add(unsigned char add,unsigned char *dat,unsigned char len)  
  132. {  
  133.     unsigned char flag,i;  
  134.     start();  
  135.     write_byte(0xa0);  
  136.     if(rec_ack() == 0)  
  137.     {  
  138.         write_byte(add);  
  139.         if(rec_ack() == 0)  
  140.         {  
  141.             for(i=0;i<len;i++)  
  142.             {  
  143.                 write_byte(dat[i]);  
  144.                 if(rec_ack() == 1)  
  145.                 {  
  146.                     i = 0;  
  147.                     break;  
  148.                 }  
  149.             }  
  150.             if(i == len)  
  151.                 flag = 1;  
  152.         }  
  153.     }  
  154.     stop();  
  155.     return flag;          
  156. }  
  157. //从add地址读出len长度的数据给dat  
  158. unsigned char read_add(unsigned char add,unsigned char *dat,unsigned char len)  
  159. {  
  160.     unsigned char flag,i;     
  161.     start();  
  162.     write_byte(0xa0);  
  163.     if(rec_ack() == 0)  
  164.     {  
  165.         write_byte(add);  
  166.         if(rec_ack() == 0)  
  167.         {  
  168.             start();  
  169.             write_byte(0xa1);  
  170.             if(rec_ack() == 0)  
  171.             {  
  172.                 for(i=0;i<len;i++)  
  173.                 {  
  174.                     dat[i] = read_byte();  
  175.                     send_ack(0);  
  176.                 }  
  177.                 flag = 1;  
  178.                 send_ack(1);  
  179.                 somenop();  
  180.             }  
  181.         }  
  182.     }  
  183.     stop();  
  184.     return flag;  
  185. }  
  186. //delay 5us  
  187. void somenop()  
  188. {;;}  
  189. //delay x ms  
  190. void delay(unsigned char x)  
  191. {  
  192.     unsigned char y,z;  
  193.     for(y=x;y>0;y--)  
  194.         for(z=110;z>0;z--);  
  195. }  

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值