I2C总线时序模拟(二)-加深理解总线协议

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

上一篇: I2C总线学习终结,开始SPI总线的学习
下一篇: I2C总线串行输入输出结构

推荐阅读最新更新时间:2024-03-16 14:45

【STM8S103K3】 I2C
以下为.h文件: 定义了PA1为SDA,PA2为SCL #ifndef __I2C_H #define __I2C_H #include stm8s.h #include stm8s_gpio.h #include tim1.h #include uart.h #include iostm8s103f3.h #include intrinsics.h #define SCL PA_ODR_ODR2 #define SDA PA_ODR_ODR1 #define SDAM PA_IDR_IDR1 #define SET_SCL_OUT() {PA_DDR_DDR2=1; P
[单片机]
DDR3总线协议测试方法
最近接触几个客户在关注DDR3总线协议的测试,说明 DDR3总线的协议测试变得越来越重要(以前,针对DDR1和2的协议测试,客户关注的比较少),下面把DDR3总线的协议测试方法作个介绍。 1. DDR3总线协议探测 DDR3总线的协议探测是测试的难点之一,探测不当会导致没法正确捕获数据,导致协议分析的错误。 针对计算机系统和嵌入式系统,有两种不同类型的探测方法。 下图是针对计算机系统的探测方法: 针对计算机系统需要采用Interposer探头进行探测,这个探头不需要改变系统的PCB设计,在插入DIMM或SO-DIMM内存条之前,先插入DIMM或SO-DIMM探头,然后再把DIMM或SO-DIMM内存条插到探头
[测试测量]
DDR3<font color='red'>总线协议</font>测试方法
基于S3C2440的嵌入式Linux驱动——AT24C02(EEPROM I2C接口)驱动解读
本文将介绍Linux中AT24C02驱动。AT24C02是一种EEPROM,使用I2C接口来访问。 在开发板中,使用I2C控制器0和AT24C02连接,这里就不给出原理图了,如需要,可以搜索TQ2440开发板的原理图。 目标平台:TQ2440 CPU:s3c2440 内核版本:2.6.32 本文所有的代码均位于内核源码:linux/drivers/misc/eeprom/at24.c中。 1. 模块注册和注销 static int __init at24_init(void) { /* 将io_limit向下圆整到最近的2的幂*/ io_limit = rounddown_pow_of_two(
[单片机]
STM32F2系列驱动开发——模拟I2C通信
简介:一、概述 通过STM32的PC14和PC15管脚来模拟I2C通信,读写I2C接口的器件内部寄存器...... 一、概述 通过STM32的PC14和PC15管脚来模拟I2C通信,读写I2C接口的器件内部寄存器,具体定义如下: #define PIN_SCL GPIO_Pin_14 #define PIN_SDA GPIO_Pin_15 延时函数为μs延时,例如Delay(4)表示延时4μs。 二、Static型函数定义 static __inline void TWI_SCL_0(void) { GPIOC- BSRRH = PIN_SCL; } static __inline void
[单片机]
单片机 I2C 时序介绍
在硬件上,I2C 总线是由时钟总线 SCL 和数据总线 SDA 两条线构成,连接到总线上的所有器件的 SCL 都连到一起,所有 SDA 都连到一起。I2C 总线是开漏引脚并联的结构,因此我们外部要添加上拉电阻。对于开漏电路外部加上拉电阻,就组成了线“与”的关系。总线上线“与”的关系就是说,所有接入的器件保持高电平,这条线才是高电平,而任何一个器件输出一个低电平,那这条线就会保持低电平,因此可以做到任何一个器件都可以拉低电平,也就是任何一个器件都可以作为主机,如图14-1所示,我们添加了 R63 和 R64 两个上拉电阻。 图14-1 I2C 总线的上拉电阻 虽然说任何一个设备都可以作为主机,但绝大多数情况下我们都是用单片机来做
[单片机]
单片机 <font color='red'>I2C</font> 时序介绍
基于I2C总线的CMOS图像传感器接口电路设计
    1引言     数码相机等图像消费类电子产品产业正在飞速发展,这使得图像传感器和数码相机专用集成芯片的研制获得巨大的市场支持。目前广泛使用的数码相机图像传感器主要是以下两种:CCD和CMOS。CCD图像传感器具有技术成熟、图像噪声小等优点,但由于制作工艺复杂,与标准工艺不兼容,且需要高电压供电,芯片功耗大,目前仅在高级型数码相机市场上占有一席之地。而CMOS图像传感器采用了CMOS工艺,可以将图像采集单元和信号处理单元集成到同一块芯片上,因而具有集成度高、功耗低、价格便宜的优点,具有很好的发展前景。随着噪声消除技术的改进,目前CMOS图像传感器正由中、低档数码相机向高级型数码相机发展。     现在的CMOS图
[嵌入式]
基于I2C总线的多点温度采集系统
  随着社会的进步和工业技术的发展,许多产品对温度范围的要求越加严格,尤其在工业发展方面,如冶金、钢铁、石化、水泥、玻璃等行业。而目前市场上温度检测仪器大多是单点测量,不能适应当今社会生产高效率要求,且温度信息精度不高。因此设计一种能够同时测量多点温度,测量精度高,能够综合处理多点温度信息的测量系统很有必要。这里提出一种能多路采集、显示的温度采集系统设计。   1 系统硬件设计   1.1 系统整体结构   该系统设计采用I2C总线,单主机多从机的工作模式,实现多点温度的采集、读取与显示。主机由主控制器、数码管显示、电源、报警、键盘等模块组成,完成以下功能:1)主机通过按键确定进入温度测量状态以及即将读取温度的节点:2)主机
[嵌入式]
飞兆半导体转换器产品解决I2C总线应用的兼容性难题
      飞兆半导体公司(Fairchild Semiconductor)开发了一款可配置双电压电平转换器产品FXMA2102,用于I2C总线接口应用的电平转换。FXMA2102能够满足移动设备设计人员的需求,通过使用低功耗的2位电压水平转换器,来解决消费产品和手机的I2C总线应用的混合电压兼容性问题。       FXMA2102是专为从1.65V到5.5V的任何两个电平的双向电压转换而设计的高性能转换器。该器件的两个端口都具有自动方向感测功能,容许任一端口感测输入信号,再输出至另一个端口。       飞兆半导体的新器件适合标准和快速I2C总线模式,并可同时用作转换器、缓冲器和转发器。此外,FXMA2102还具
[电源管理]
飞兆半导体转换器产品解决<font color='red'>I2C</font><font color='red'>总线</font>应用的兼容性难题
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved