找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2507|回复: 1
打印 上一主题 下一主题
收起左侧

单片机虚拟I2C总线汇编与C语言软件包,很实用的

[复制链接]
跳转到指定楼层
楼主
      该软件包只用在100K或400K速度的I2C器件,如果用在低速一些的器件(如:ZLG7290)就需要调整运行时间,如在通信过程中增加NOP指令等增加延时时间.


虚拟 I2C总线汇编程序软件包概述
为了非常方便地对 I2C 从器件进行快速的 正确的读写操作,我们为此而设计出虚拟 I2C 总线操作平台软件包 本软件包是主方式下的虚拟 I2C 总线软件包,只要用户给子程序提供几个主要的参数,即可轻松地完成任何I2C 总线外围器件的应用程序设计  

全部资料51hei下载地址:
I2C软件包,很有用,移植性好.rar (67.11 KB, 下载次数: 25)


单片机源程序如下:
  1. /********************************************************************
  2.                        VIIC_C51.C
  3.   此程序是I2C操作平台(主方式的软件平台)的底层的C子程序,如发送数据
  4. 及接收数据,应答位发送,并提供了几个直接面对器件的操作函数,它很方便的
  5. 与用户程序连接并扩展.....  
  6.   
  7.     注意:函数是采用软件延时的方法产生SCL脉冲,固对高晶振频率要作
  8. 一定的修改....(本例是1us机器周期,即晶振频率要小于12MHZ)

  9. ********************************************************************/
  10.   
  11.   
  12.               
  13. #include <reg764.h>          /*头文件的包含*/
  14. #include <intrins.h>

  15. #define  uchar unsigned char /*宏定义*/
  16. #define  uint  unsigned int

  17. #define  _Nop()  _nop_()        /*定义空指令*/

  18. /* 常,变量定义区 */

  19.                                                  /*端口位定义*/
  20. sbit SDA=P1^3;            /*模拟I2C数据传送位*/
  21. sbit SCL=P1^2;            /*模拟I2C时钟控制位*/

  22.                                                  /*状态标志*/
  23. bit ack;                 /*应答标志位*/
  24.    





  25. /*******************************************************************
  26.                      起动总线函数               
  27. 函数原型: void  Start_I2c();  
  28. 功能:       启动I2C总线,即发送I2C起始条件.
  29.   
  30. ********************************************************************/
  31. void Start_I2c()
  32. {
  33.   SDA=1;   /*发送起始条件的数据信号*/
  34.   _Nop();
  35.   SCL=1;
  36.   _Nop();    /*起始条件建立时间大于4.7us,延时*/
  37.   _Nop();
  38.   _Nop();
  39.   _Nop();
  40.   _Nop();   
  41.   SDA=0;   /*发送起始信号*/
  42.   _Nop();    /* 起始条件锁定时间大于4μs*/
  43.   _Nop();
  44.   _Nop();
  45.   _Nop();
  46.   _Nop();      
  47.   SCL=0;   /*钳住I2C总线,准备发送或接收数据 */
  48.   _Nop();
  49.   _Nop();
  50. }




  51. /*******************************************************************
  52.                       结束总线函数               
  53. 函数原型: void  Stop_I2c();  
  54. 功能:       结束I2C总线,即发送I2C结束条件.
  55.   
  56. ********************************************************************/
  57. void Stop_I2c()
  58. {
  59.   SDA=0;  /*发送结束条件的数据信号*/
  60.   _Nop();   /*发送结束条件的时钟信号*/
  61.   SCL=1;  /*结束条件建立时间大于4μs*/
  62.   _Nop();
  63.   _Nop();
  64.   _Nop();
  65.   _Nop();
  66.   _Nop();
  67.   SDA=1;  /*发送I2C总线结束信号*/
  68.   _Nop();
  69.   _Nop();
  70.   _Nop();
  71.   _Nop();
  72. }




  73. /*******************************************************************
  74.                  字节数据传送函数               
  75. 函数原型: void  SendByte(uchar c);
  76. 功能:  将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
  77.      此状态位进行操作.(不应答或非应答都使ack=0 假)     
  78.      发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
  79. ********************************************************************/
  80. void  SendByte(uchar c)
  81. {
  82. uchar BitCnt;

  83. for(BitCnt=0;BitCnt<8;BitCnt++)  /*要传送的数据长度为8位*/
  84.     {
  85.      if((c<<BitCnt)&0x80)SDA=1;   /*判断发送位*/
  86.        else  SDA=0;               
  87.      _Nop();
  88.      SCL=1;               /*置时钟线为高,通知被控器开始接收数据位*/
  89.       _Nop();
  90.       _Nop();               /*保证时钟高电平周期大于4μs*/
  91.       _Nop();
  92.       _Nop();
  93.       _Nop();         
  94.      SCL=0;
  95.     }
  96.    
  97.     _Nop();
  98.     _Nop();
  99.     SDA=1;               /*8位发送完后释放数据线,准备接收应答位*/
  100.     _Nop();
  101.     _Nop();   
  102.     SCL=1;
  103.     _Nop();
  104.     _Nop();
  105.     _Nop();
  106.     if(SDA==1)ack=0;     
  107.        else ack=1;        /*判断是否接收到应答信号*/
  108.     SCL=0;
  109.     _Nop();
  110.     _Nop();
  111. }






  112. /*******************************************************************
  113.                  字节数据传送函数               
  114. 函数原型: uchar  RcvByte();
  115. 功能:  用来接收从器件传来的数据,并判断总线错误(不发应答信号),
  116.      发完后请用应答函数。  
  117. ********************************************************************/       
  118. uchar  RcvByte()
  119. {
  120.   uchar retc;
  121.   uchar BitCnt;
  122.   
  123.   retc=0;
  124.   SDA=1;             /*置数据线为输入方式*/
  125.   for(BitCnt=0;BitCnt<8;BitCnt++)
  126.       {
  127.         _Nop();           
  128.         SCL=0;       /*置时钟线为低,准备接收数据位*/
  129.         _Nop();
  130.         _Nop();         /*时钟低电平周期大于4.7μs*/
  131.         _Nop();
  132.         _Nop();
  133.         _Nop();
  134.         SCL=1;       /*置时钟线为高使数据线上数据有效*/
  135.         _Nop();
  136.         _Nop();
  137.         retc=retc<<1;
  138.         if(SDA==1)retc=retc+1; /*读数据位,接收的数据位放入retc中 */
  139.         _Nop();
  140.         _Nop();
  141.       }
  142.   SCL=0;   
  143.   _Nop();
  144.   _Nop();
  145.   return(retc);
  146. }




  147. /********************************************************************
  148.                      应答子函数
  149. 原型:  void Ack_I2c(bit a);

  150. 功能:主控器进行应答信号,(可以是应答或非应答信号)
  151. ********************************************************************/
  152. void Ack_I2c(bit a)
  153. {
  154.   
  155.   if(a==0)SDA=0;     /*在此发出应答或非应答信号 */
  156.         else SDA=1;
  157.   _Nop();
  158.   _Nop();
  159.   _Nop();      
  160.   SCL=1;
  161.     _Nop();
  162.     _Nop();              /*时钟低电平周期大于4μs*/
  163.     _Nop();
  164.     _Nop();
  165.     _Nop();  
  166. SCL=0;                /*清时钟线,钳住I2C总线以便继续接收*/
  167.     _Nop();
  168.     _Nop();   
  169. }






  170. /*******************************************************************
  171.                     向无子地址器件发送字节数据函数               
  172. 函数原型: bit  ISendByte(uchar sla,ucahr c);  
  173. 功能:     从启动总线到发送地址,数据,结束总线的全过程,从器件地址sla.
  174.            如果返回1表示操作成功,否则操作有误。
  175. 注意:    使用前必须已结束总线。
  176. ********************************************************************/
  177. bit ISendByte(uchar sla,uchar c)
  178. {
  179.    Start_I2c();               /*启动总线*/
  180.    SendByte(sla);            /*发送器件地址*/
  181.      if(ack==0)return(0);
  182.    SendByte(c);               /*发送数据*/
  183.      if(ack==0)return(0);
  184.   Stop_I2c();                 /*结束总线*/
  185.   return(1);
  186. }




  187. /*******************************************************************
  188.                     向有子地址器件发送多字节数据函数               
  189. 函数原型: bit  ISendStr(uchar sla,uchar suba,ucahr *s,uchar no);  
  190. 功能:     从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件
  191.           地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。
  192.            如果返回1表示操作成功,否则操作有误。
  193. 注意:    使用前必须已结束总线。
  194. ********************************************************************/
  195. bit ISendStr(uchar sla,uchar suba,uchar *s,uchar no)
  196. {
  197.    uchar i;

  198.    Start_I2c();               /*启动总线*/
  199.    SendByte(sla);            /*发送器件地址*/
  200.      if(ack==0)return(0);
  201.    SendByte(suba);            /*发送器件子地址*/
  202.      if(ack==0)return(0);

  203.    for(i=0;i<no;i++)
  204.     {   
  205.      SendByte(*s);               /*发送数据*/
  206.        if(ack==0)return(0);
  207.      s++;
  208.     }
  209. Stop_I2c();                 /*结束总线*/
  210.   return(1);
  211. }






  212. /*******************************************************************
  213.                     向无子地址器件读字节数据函数               
  214. 函数原型: bit  IRcvByte(uchar sla,ucahr *c);  
  215. 功能:     从启动总线到发送地址,读数据,结束总线的全过程,从器件地
  216.           址sla,返回值在c.
  217.            如果返回1表示操作成功,否则操作有误。
  218. 注意:    使用前必须已结束总线。
  219. ********************************************************************/
  220. bit IRcvByte(uchar sla,uchar *c)
  221. {
  222.    Start_I2c();                /*启动总线*/
  223.    SendByte(sla+1);           /*发送器件地址*/
  224.      if(ack==0)return(0);
  225.    *c=RcvByte();               /*读取数据*/
  226.      Ack_I2c(1);               /*发送非就答位*/
  227.   Stop_I2c();                  /*结束总线*/
  228.   return(1);
  229. }



  230. /*******************************************************************
  231.                     向有子地址器件读取多字节数据函数               
  232. 函数原型: bit  ISendStr(uchar sla,uchar suba,ucahr *s,uchar no);  
  233. 功能:     从启动总线到发送地址,子地址,读数据,结束总线的全过程,从器件
  234.           地址sla,子地址suba,读出的内容放入s指向的存储区,读no个字节。
  235.            如果返回1表示操作成功,否则操作有误。
  236. 注意:    使用前必须已结束总线。
  237. ********************************************************************/
  238. bit IRcvStr(uchar sla,uchar suba,uchar *s,uchar no)
  239. ……………………

  240. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:250287 发表于 2018-6-24 21:06 | 只看该作者
感谢!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表