/********************************************************************
此程序是I2C操作平台(主方式的软件平台)的底层的C子程序,如发送数据
及接收数据,应答位发送,并提供了几个直接面对器件的操作函数,它很方便的
与用户程序连接并扩展.....  注意:函数是采用软件延时的方法产生SCL脉冲,固对高晶振频率要作
一定的修改....(本例是1us机器周期,即晶振频率要小于12MHZ)
********************************************************************/
#include <reg764.h>          /*头文件的包含*/
#include <intrins.h>#define  uchar unsigned char /*宏定义*/
#define  uint  unsigned int#define  _Nop()  _nop_()        /*定义空指令*//* 常,变量定义区 *//*端口位定义*/
sbit SDA=P1^3;            /*模拟I2C数据传送位*/
sbit SCL=P1^2;            /*模拟I2C时钟控制位*//*状态标志*/
bit ack;             /*应答标志位*//*******************************************************************起动总线函数
函数原型: void  Start_I2c();
功能:       启动I2C总线,即发送I2C起始条件.********************************************************************/
void Start_I2c()
{SDA=1;   /*发送起始条件的数据信号*/_Nop();SCL=1;_Nop();    /*起始条件建立时间大于4.7us,延时*/_Nop();_Nop();_Nop();_Nop();    SDA=0;   /*发送起始信号*/_Nop();    /* 起始条件锁定时间大于4μs*/_Nop();_Nop();_Nop();_Nop();       SCL=0;   /*钳住I2C总线,准备发送或接收数据 */_Nop();_Nop();
}/*******************************************************************结束总线函数
函数原型: void  Stop_I2c();
功能:       结束I2C总线,即发送I2C结束条件.********************************************************************/
void Stop_I2c()
{SDA=0;  /*发送结束条件的数据信号*/_Nop();   /*发送结束条件的时钟信号*/SCL=1;  /*结束条件建立时间大于4μs*/_Nop();_Nop();_Nop();_Nop();_Nop();SDA=1;  /*发送I2C总线结束信号*/_Nop();_Nop();_Nop();_Nop();
}/*******************************************************************字节数据传送函数
函数原型: void  SendByte(uchar c);
功能:  将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对此状态位进行操作.(不应答或非应答都使ack=0 假)     发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
********************************************************************/
void  SendByte(uchar c)
{uchar BitCnt;for(BitCnt=0;BitCnt<8;BitCnt++)  /*要传送的数据长度为8位*/{if((c<<BitCnt)&0x80)SDA=1;   /*判断发送位*/else  SDA=0;                _Nop();SCL=1;               /*置时钟线为高,通知被控器开始接收数据位*/_Nop(); _Nop();               /*保证时钟高电平周期大于4μs*/_Nop();_Nop();_Nop();         SCL=0; }_Nop();_Nop();SDA=1;               /*8位发送完后释放数据线,准备接收应答位*/_Nop();_Nop();   SCL=1;_Nop();_Nop();_Nop();if(SDA==1)ack=0;     else ack=1;        /*判断是否接收到应答信号*/SCL=0;_Nop();_Nop();
}/*******************************************************************字节数据传送函数
函数原型: uchar  RcvByte();
功能:  用来接收从器件传来的数据,并判断总线错误(不发应答信号),发完后请用应答函数。
********************************************************************/
uchar  RcvByte()
{uchar retc;uchar BitCnt;retc=0; SDA=1;             /*置数据线为输入方式*/for(BitCnt=0;BitCnt<8;BitCnt++){_Nop();           SCL=0;       /*置时钟线为低,准备接收数据位*/_Nop();_Nop();         /*时钟低电平周期大于4.7μs*/_Nop();_Nop();_Nop();SCL=1;       /*置时钟线为高使数据线上数据有效*/_Nop();_Nop();retc=retc<<1;if(SDA==1)retc=retc+1; /*读数据位,接收的数据位放入retc中 */_Nop();_Nop(); }SCL=0;    _Nop();_Nop();return(retc);
}/********************************************************************应答子函数
原型:  void Ack_I2c(bit a);功能:主控器进行应答信号,(可以是应答或非应答信号)
********************************************************************/
void Ack_I2c(bit a)
{if(a==0)SDA=0;     /*在此发出应答或非应答信号 */else SDA=1;_Nop();_Nop();_Nop();      SCL=1;_Nop();_Nop();              /*时钟低电平周期大于4μs*/_Nop();_Nop();_Nop();  SCL=0;                /*清时钟线,钳住I2C总线以便继续接收*/_Nop();_Nop();
}/*******************************************************************向无子地址器件发送字节数据函数
函数原型: bit  ISendByte(uchar sla,ucahr c);
功能:     从启动总线到发送地址,数据,结束总线的全过程,从器件地址sla.如果返回1表示操作成功,否则操作有误。
注意:    使用前必须已结束总线。
********************************************************************/
bit ISendByte(uchar sla,uchar c)
{Start_I2c();               /*启动总线*/SendByte(sla);            /*发送器件地址*/if(ack==0)return(0);SendByte(c);               /*发送数据*/if(ack==0)return(0);Stop_I2c();                 /*结束总线*/ return(1);
}/*******************************************************************向有子地址器件发送多字节数据函数
函数原型: bit  ISendStr(uchar sla,uchar suba,ucahr *s,uchar no);
功能:     从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。如果返回1表示操作成功,否则操作有误。
注意:    使用前必须已结束总线。
********************************************************************/
bit ISendStr(uchar sla,uchar suba,uchar *s,uchar no)
{uchar i;Start_I2c();               /*启动总线*/SendByte(sla);            /*发送器件地址*/if(ack==0)return(0);SendByte(suba);            /*发送器件子地址*/if(ack==0)return(0);for(i=0;i<no;i++){   SendByte(*s);               /*发送数据*/if(ack==0)return(0);s++;} Stop_I2c();                 /*结束总线*/ return(1);
}
/*******************************************************************向无子地址器件读字节数据函数
函数原型: bit  IRcvByte(uchar sla,ucahr *c);
功能:     从启动总线到发送地址,读数据,结束总线的全过程,从器件地址sla,返回值在c.如果返回1表示操作成功,否则操作有误。
注意:    使用前必须已结束总线。
********************************************************************/
bit IRcvByte(uchar sla,uchar *c)
{Start_I2c();                /*启动总线*/SendByte(sla+1);           /*发送器件地址*/if(ack==0)return(0);*c=RcvByte();               /*读取数据*/Ack_I2c(1);               /*发送非就答位*/Stop_I2c();                  /*结束总线*/ return(1);
}/*******************************************************************向有子地址器件读取多字节数据函数
函数原型: bit  ISendStr(uchar sla,uchar suba,ucahr *s,uchar no);
功能:     从启动总线到发送地址,子地址,读数据,结束总线的全过程,从器件地址sla,子地址suba,读出的内容放入s指向的存储区,读no个字节。如果返回1表示操作成功,否则操作有误。
注意:    使用前必须已结束总线。
********************************************************************/
bit IRcvStr(uchar sla,uchar suba,uchar *s,uchar no)
{uchar i;Start_I2c();               /*启动总线*/SendByte(sla);            /*发送器件地址*/if(ack==0)return(0);SendByte(suba);            /*发送器件子地址*/if(ack==0)return(0);Start_I2c();SendByte(sla+1);if(ack==0)return(0);for(i=0;i<no-1;i++){   *s=RcvByte();               /*发送数据*/Ack_I2c(0);                /*发送就答位*/  s++;} *s=RcvByte();Ack_I2c(1);                 /*发送非应位*/Stop_I2c();                    /*结束总线*/ return(1);
}/*    完毕      */

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

  1. 总线(二)CAN通讯协议介绍

    文章目录 CAN(Controller Area Network)是什么? 总线拓扑图 CAN特征 CAN协议 数据帧 遥控帧 遥控帧和数据帧相关? 仲裁优先级决定 数据帧和遥控帧的优先级 标准格式和 ...

  2. 计算机网络资料篇(二)——快速理解网络协议

    <网络编程懒人入门(一):快速理解网络通信协议(上篇)> <网络编程懒人入门(二):快速理解网络通信协议(下篇)> 一:五层模型 物理层.数据链路层.网络层.传输层.应用层 1 ...

  3. 串口RS232 RS485最本质的区别!-!I2C通讯协议 最简单的总线通讯!-深入理解SPi通讯协议!

    5分钟看懂!串口RS232 RS485最本质的区别!-4分钟看懂!I2C通讯协议 最简单的总线通讯!-深入理解SPi通讯协议,5分钟看懂! 一.5分钟看懂!串口RS232 RS485最本质的区别! 二 ...

  4. 单片机软件模拟SPI接口—加深理解SPI总线协议

    单片机软件模拟SPI接口-加深理解SPI总线协议   SPI(Serial Peripheral Interfacer 串行外设接口)是摩托罗拉公司推出的一种同步串行通讯接口,用于微处理器臌控制器和外 ...

  5. 清华大学-曾鸣-《ARM微控制器与嵌入式系统》I2C总线(二)

    I2C(Inter IC Bus)的通讯数据帧: SCL线无方向区分,SDA线上有数据的流动方向.上图中灰色的代表的是主机向从机发送数据,此时SDA线的电平控制权由主机掌控,从机只能监听该线上的电平状 ...

  6. I2S音频总线学习(二)I2S总线协议

    I2S音频总线学习(二)I2S总线协议 一.I2S总线概述 音响数据的采集.处理和传输是多媒体技术的重要组成部分.众多的数字音频系统已经进入消费市场,例如数字音频录音带.数字声音处理器.对于设备和生产 ...

  7. Linux I2C总线(二)I2C设备驱动编写方法

    Linux I2C总线 Linux I2C总线(一)I2C驱动框架 Linux I2C总线(二)I2C设备驱动编写方法 Linux I2C总线(二)I2C设备驱动编写方法 文章目录 Linux I2C ...

  8. 对I2C总线时序的一点理解以及ACK和NACK(NAK)

    http://www.cnblogs.com/zym0805/archive/2011/07/31/2122890.html I2C是由Philips公司发明的一种串行数据通信协议,仅使用两根信号线: ...

  9. PCIE学习笔记(二)PCIe总线的拓扑结构,协议层,数据传输流程

    目录 PCIe总线的拓扑结构 PCI Express协议分层 物理层(Physical Layer) 数据链路层(Link Layer) 处理层(Transaction Layer) 软件层(Soft ...

最新文章

  1. ubuntu 14 nginx php,ubuntu14.04安装nginx+php5-fpm
  2. 【备忘录】技术笔记整理。
  3. 轻量级Excel读取器ExcelReader
  4. 【代码笔记】Web-ionic-select
  5. apache mesos_试用Apache Mesos HTTP API获得乐趣和收益
  6. java 反射 代码_java反射机制学习代码
  7. Fckeditor漏洞汇总
  8. 计算机里的音乐怎么设置,realtek高清晰音频管理器怎么设置
  9. java 文档查看技巧
  10. stm32f103c8t9控制TFT显示屏
  11. 恺撒密码的python实现介绍
  12. 读书笔记17 《靠谱》大石哲之
  13. linux中管道的概念,浅谈Linux管道
  14. 「案例」如何解决公司采购与财务之间的工作矛盾?
  15. 理解逆矩阵 理解单位矩阵
  16. CSS cascading style sheet
  17. Symbian OS
  18. 光缆旋转传输器/光纤滑环(LZ-M40X)在大型堆取料机上的应用
  19. CDA Day 5 Excel透视表学习总结
  20. React配置baseUrl

热门文章

  1. mysql sql语句里连接符的使用_SQL中group_concat函数,用符号连接查询分组里字段值...
  2. leetcode46.全排列
  3. leecode刷题(4)-- 存在重复数组
  4. vscode php debug
  5. vue组件库(一):前期准备工作
  6. 【洛谷】【lca+结论】P3398 仓鼠找sugar
  7. SQL注入之Mysql报错注入
  8. 【线段树】HDU 3397 Sequence operation 区间合并
  9. 解读:百度官方公告对于6.22、6.28事件解释
  10. Java把表导出成Excel的代码