VIIC_C51.c
上传用户:ids068
上传日期:2013-04-04
资源大小:639k
文件大小:8k
源码类别:

USB编程

开发平台:

C/C++

  1. /********************************************************************
  2.                        VIIC_C51.C
  3.   此程序是I2C操作平台(主方式的软件平台)的底层的C子程序,如发送数据
  4. 及接收数据,应答位发送,并提供了几个直接面对器件的操作函数,它很方便的
  5. 与用户程序连接并扩展.....  
  6.   
  7.     注意:函数是采用软件延时的方法产生SCL脉冲,固对高晶振频率要作 
  8. 一定的修改....(本例是1us机器周期,即晶振频率要小于12MHZ)
  9. ********************************************************************/
  10.   
  11.   
  12.               
  13. #include <reg52.h>          /*头文件的包含*/
  14. #include <intrins.h>
  15. #define  uchar unsigned char /*宏定义*/
  16. #define  uint  unsigned int
  17. #define  _Nop()  _nop_()        /*定义空指令*/
  18. /* 常,变量定义区 */
  19.  
  20.                                                  /*端口位定义*/
  21. sbit SDA=P1^7;            /*模拟I2C数据传送位*/
  22. sbit SCL=P1^6;            /*模拟I2C时钟控制位*/
  23.                                                  /*状态标志*/
  24. bit ack;          /*应答标志位*/
  25.    
  26. /*******************************************************************
  27.                      起动总线函数               
  28. 函数原型: void  Start_I2c();  
  29. 功能:       启动I2C总线,即发送I2C起始条件.
  30.   
  31. ********************************************************************/
  32. void Start_I2c()
  33. {
  34.   SDA=1;   /*发送起始条件的数据信号*/
  35.   _Nop();
  36.   SCL=1;
  37.   _Nop();    /*起始条件建立时间大于4.7us,延时*/
  38.   _Nop();
  39.   _Nop();
  40.   _Nop();
  41.   _Nop();    
  42.   SDA=0;   /*发送起始信号*/
  43.   _Nop();    /* 起始条件锁定时间大于4μs*/
  44.   _Nop();
  45.   _Nop();
  46.   _Nop();
  47.   _Nop();       
  48.   SCL=0;   /*钳住I2C总线,准备发送或接收数据 */
  49.   _Nop();
  50.   _Nop();
  51. }
  52. /*******************************************************************
  53.                       结束总线函数               
  54. 函数原型: void  Stop_I2c();  
  55. 功能:       结束I2C总线,即发送I2C结束条件.
  56.   
  57. ********************************************************************/
  58. void Stop_I2c()
  59. {
  60.   SDA=0;  /*发送结束条件的数据信号*/
  61.   _Nop();   /*发送结束条件的时钟信号*/
  62.   SCL=1;  /*结束条件建立时间大于4μs*/
  63.   _Nop();
  64.   _Nop();
  65.   _Nop();
  66.   _Nop();
  67.   _Nop();
  68.   SDA=1;  /*发送I2C总线结束信号*/
  69.   _Nop();
  70.   _Nop();
  71.   _Nop();
  72.   _Nop();
  73. }
  74. /*******************************************************************
  75.                  字节数据传送函数               
  76. 函数原型: void  SendByte(uchar c);
  77. 功能:  将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
  78.      此状态位进行操作.(不应答或非应答都使ack=0 假)     
  79.      发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
  80. ********************************************************************/
  81. void  SendByte(uchar c)
  82. {
  83.  uchar BitCnt;
  84.  
  85.  for(BitCnt=0;BitCnt<8;BitCnt++)  /*要传送的数据长度为8位*/
  86.     {
  87.      if((c<<BitCnt)&0x80)SDA=1;   /*判断发送位*/
  88.        else  SDA=0;                
  89.      _Nop();
  90.      SCL=1;               /*置时钟线为高,通知被控器开始接收数据位*/
  91.       _Nop(); 
  92.       _Nop();               /*保证时钟高电平周期大于4μs*/
  93.       _Nop();
  94.       _Nop();
  95.       _Nop();         
  96.      SCL=0; 
  97.     }
  98.     
  99.     _Nop();
  100.     _Nop();
  101.     SDA=1;               /*8位发送完后释放数据线,准备接收应答位*/
  102.     _Nop();
  103.     _Nop();   
  104.     SCL=1;
  105.     _Nop();
  106.     _Nop();
  107.     _Nop();
  108.     if(SDA==1)ack=0;     
  109.        else ack=1;        /*判断是否接收到应答信号*/
  110.     SCL=0;
  111.     _Nop();
  112.     _Nop();
  113. }
  114. /*******************************************************************
  115.                  字节数据传送函数               
  116. 函数原型: uchar  RcvByte();
  117. 功能:  用来接收从器件传来的数据,并判断总线错误(不发应答信号),
  118.      发完后请用应答函数。  
  119. ********************************************************************/
  120. uchar  RcvByte()
  121. {
  122.   uchar retc;
  123.   uchar BitCnt;
  124.   
  125.   retc=0; 
  126.   SDA=1;             /*置数据线为输入方式*/
  127.   for(BitCnt=0;BitCnt<8;BitCnt++)
  128.       {
  129.         _Nop();           
  130.         SCL=0;       /*置时钟线为低,准备接收数据位*/
  131.         _Nop();
  132.         _Nop();         /*时钟低电平周期大于4.7μs*/
  133.         _Nop();
  134.         _Nop();
  135.         _Nop();
  136.         SCL=1;       /*置时钟线为高使数据线上数据有效*/
  137.         _Nop();
  138.         _Nop();
  139.         retc=retc<<1;
  140.         if(SDA==1)retc=retc+1; /*读数据位,接收的数据位放入retc中 */
  141.         _Nop();
  142.         _Nop(); 
  143.       }
  144.   SCL=0;    
  145.   _Nop();
  146.   _Nop();
  147.   return(retc);
  148. }
  149. /********************************************************************
  150.                      应答子函数
  151. 原型:  void Ack_I2c(bit a);
  152.  
  153. 功能:主控器进行应答信号,(可以是应答或非应答信号)
  154. ********************************************************************/
  155. void Ack_I2c(bit a)
  156. {
  157.   
  158.   if(a==0)SDA=0;     /*在此发出应答或非应答信号 */
  159.         else SDA=1;
  160.   _Nop();
  161.   _Nop();
  162.   _Nop();      
  163.   SCL=1;
  164.     _Nop();
  165.     _Nop();              /*时钟低电平周期大于4μs*/
  166.     _Nop();
  167.     _Nop();
  168.     _Nop();  
  169.  SCL=0;                /*清时钟线,钳住I2C总线以便继续接收*/
  170.     _Nop();
  171.     _Nop();    
  172. }
  173. /*******************************************************************
  174.                     向无子地址器件发送字节数据函数               
  175. 函数原型: bit  ISendByte(uchar sla,ucahr c);  
  176. 功能:     从启动总线到发送地址,数据,结束总线的全过程,从器件地址sla.
  177.            如果返回1表示操作成功,否则操作有误。
  178. 注意:    使用前必须已结束总线。
  179. ********************************************************************/
  180. bit ISendByte(uchar sla,uchar c)
  181. {
  182.    Start_I2c();               /*启动总线*/
  183.    SendByte(sla);            /*发送器件地址*/
  184.      if(ack==0)return(0);
  185.    SendByte(c);               /*发送数据*/
  186.      if(ack==0)return(0);
  187.   Stop_I2c();                 /*结束总线*/ 
  188.   return(1);
  189. }
  190. /*******************************************************************
  191.                     向有子地址器件发送多字节数据函数               
  192. 函数原型: bit  ISendStr(uchar sla,uchar suba,ucahr *s,uchar no);  
  193. 功能:     从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件
  194.           地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。
  195.            如果返回1表示操作成功,否则操作有误。
  196. 注意:    使用前必须已结束总线。
  197. ********************************************************************/
  198. bit ISendStr(uchar sla,uchar suba,uchar *s,uchar no)
  199. {
  200.    uchar i;
  201.    Start_I2c();               /*启动总线*/
  202.    SendByte(sla);            /*发送器件地址*/
  203.      if(ack==0)return(0);
  204.    SendByte(suba);            /*发送器件子地址*/
  205.      if(ack==0)return(0);
  206.    for(i=0;i<no;i++)
  207.     {   
  208.      SendByte(*s);               /*发送数据*/
  209.        if(ack==0)return(0);
  210.      s++;
  211.     } 
  212.  Stop_I2c();                 /*结束总线*/ 
  213.   return(1);
  214. }
  215. /*******************************************************************
  216.                     向无子地址器件读字节数据函数               
  217. 函数原型: bit  IRcvByte(uchar sla,ucahr *c);  
  218. 功能:     从启动总线到发送地址,读数据,结束总线的全过程,从器件地
  219.           址sla,返回值在c.
  220.            如果返回1表示操作成功,否则操作有误。
  221. 注意:    使用前必须已结束总线。
  222. ********************************************************************/
  223. bit IRcvByte(uchar sla,uchar *c)
  224. {
  225.    Start_I2c();                /*启动总线*/
  226.    SendByte(sla+1);           /*发送器件地址*/
  227.      if(ack==0)return(0);
  228.    *c=RcvByte();               /*读取数据*/
  229.      Ack_I2c(1);               /*发送非就答位*/
  230.   Stop_I2c();                  /*结束总线*/ 
  231.   return(1);
  232. }
  233. /*******************************************************************
  234.                     向有子地址器件读取多字节数据函数               
  235. 函数原型: bit  ISendStr(uchar sla,uchar suba,ucahr *s,uchar no);  
  236. 功能:     从启动总线到发送地址,子地址,读数据,结束总线的全过程,从器件
  237.           地址sla,子地址suba,读出的内容放入s指向的存储区,读no个字节。
  238.            如果返回1表示操作成功,否则操作有误。
  239. 注意:    使用前必须已结束总线。
  240. ********************************************************************/
  241. bit IRcvStr(uchar sla,uchar suba,uchar *s,uchar no)
  242. {
  243.    uchar i;
  244.    Start_I2c();               /*启动总线*/
  245.    SendByte(sla);            /*发送器件地址*/
  246.      if(ack==0)return(0);
  247.    SendByte(suba);            /*发送器件子地址*/
  248.      if(ack==0)return(0);
  249.    Start_I2c();
  250.    SendByte(sla+1);
  251.       if(ack==0)return(0);
  252.    for(i=0;i<no-1;i++)
  253.     {   
  254.      *s=RcvByte();               /*发送数据*/
  255.       Ack_I2c(0);                /*发送就答位*/  
  256.      s++;
  257.     } 
  258.    *s=RcvByte();
  259.     Ack_I2c(1);                 /*发送非应位*/
  260.  Stop_I2c();                    /*结束总线*/ 
  261.   return(1);
  262. }
  263.                         /*    完毕      */