IIC总线协议

前言:年前给老师做个红外抄表系统,,现在对当中用到的一些模块总结一下.

1.只有在总线空闲时才允许启动数据传送.

2.在数据传送过程中,当时钟线为高电平时,数据线必须保持稳定状态,不允许有跳变.时钟线为高电平时,数据线的任何电平变化将被看做总线的起始或停止信号.

3. 任何将数据传送到总线的器件作为发送器任何从总线接收数据的器件为接收器, 主器件和从器件都可以作为发送器或接收器但由主器件控制传送数据.

4.有两根数据线:

SDA : IIC数据传送位

SCL : IIC 时钟控制位

下面对IIC的底层驱动加以说明,并给出汇编和C语言的代码,以AT24C64为例.在这之前先定义一些常量和公共代码:

汇编:

SDA   BIT  P3.4            ;数据端

SCL   BIT  P3.5            ;时钟端

DELAY : NOP        ;延时子程序,根据单片机的晶振不同,延时长短略有不同

NOP        ;12MHZ晶振

NOP

NOP

NOP

NOP

RET

C语言:

  sbit SDA = P3.4;

sbit SCL = P3.5;

void delay(void)       //延时子程序

{

unsigned char i;

for(i=0;i<10;i++);

}

起始信号:

时钟线保持高电平期间,数据线电平从高到低的跳变作为IIC总线的起始信号.

汇编:

IIC_ST:                ;IIC起始代码

LCALL DELAY

CLR SCL

LCALL DELAY

LCALL DELAY

SETB SDA

LCALL DELAY

LCALL DELAY

SETB SCL

LCALL DELAY

LCALL DELAY

CLR SDA

LCALL DELAY

LCALL DELAY

CLR SCL

LCALL DELAY

RET

C语言:

void iic_start(void)

{

SCL=0;

delay();

SDA=1;

delay();

SCL=1;

delay();

SDA=0;

delay();

SCL=0;

delay();

}

停止信号:

时钟线保持高电平期间,数据线电平从低变高.

汇编:

IIC_SP:

LCALL DELAY

CLR SCL

LCALL DELAY

LCALL DELAY

CLR SDA

LCALL DELAY

LCALL DELAY

SETB SCL

LCALL DELAY

LCALL DELAY

SETB SDA

LCALL DELAY

RET

C语言:

void iic_stop(void)

{

delay();

SCL=0;

delay();

SDA=0;

delay();

SCL=1

delay();

SDA=1;

delay();

}

器件寻址:

首先发送一个起始信号,启动发送过程,然后发送它所需要的寻址的从器件的地址.8从位器件地址的高4位固定为1010,接下来的三位为器件的地址位,最低一位作为读写控制位.

1: 表示从器件进行读;

0: 表示对器件进行写.

应答信号:

IIC总线数据传送时,每成功的传送一个字节数据后,接收器都必须产生一个应答信号.应答的器件在第九个时钟周期时将SDA拉低,表示收到一个8位数据.

写操作:(字节模式)

主器件发送起始信号和从器件地址信息(R/W位清0)给从器件,在从器件送回应答信号后,主器件发送两个8位地址字写入从器件的地址指针,主器件在收到从器件的应答信号后,再发送数据到到被寻址的从器件存储单元,从器件再次应答,并在主器件产生停止信号后开始内部数据的擦写.

汇编:

;##############写数据到at24c64-ATW2##############

;说明:写一字节数据到at24c64,失败PSW.5置1

;入口参数:A

;出口参数:无

;###############################################

IIC_WB:

MOV R2,#8

CLR SCL

J4:     RLC A

LCALL DELAY

LCALL DELAY

MOV SDA,C

LCALL DELAY

LCALL DELAY

SETB SCL

LCALL DELAY

LCALL DELAY

CLR SCL

DJNZ R2,J4

SETB SDA

LCALL DELAY

LCALL DELAY

SETB SCL     ;第九个时钟周期

LCALL DELAY

LCALL DELAY

JB SDA,J1     ;正常情况下,第九个时钟周期收到的SDA应为低

CLR SCL      ;释放总线

LCALL DELAY

LCALL DELAY

CLR PSW.5      ;接收成功

LJMP edw

J1: CLR SCL  ;释放总线

SETB PSW.5 ;接收失败

edw:  RET

C语言:

void iic_write_byte(unsigned char w_byte)

{

unsigned char i;

SCL=0;

for(i=0;i<8;i++)

{

delay();

if((w_byte<<i)&0x80)

SDA=1;

else

SDA=0;

delay();

SCL=1;

delay();

SCL=0;

}

SDA=1;

delay();

SCL=1;  //第九个时钟周期

delay();

if(SDA==1)  //正常情况下,第九个时钟周期时,收到的SDA应该为低电平

{           //写入出错

SCL=0;

PSW.5=1;  //出错标志

}

else

{             //写入成功

SCL=0;

PSW.5=0;  //成功标志

}

}

读操作:

读操作的初始化方式和写操作一样,仅把R/W位置1.

读操作的种类:

1.       立即/当前地址读(本例未用)

2.       选择/随机读: 允许对任意字节进行读,首先发送起始信号,从器件地址和它想读的字节数数据地址,执行一个伪写操作,在AT24C64应答之后,主器件重新发送起始信号和从器件地址,此时R/W位置1.AT24C64响应并发送应答信号,然后输出所要求的一个8位字节数据.主器件不发送应答信号但产生一个停止信号.

汇编1:

;/** 单字节读 **/

;读出的一个字节存放在A中

IIC_RB:

CLR A

CLR C

LCALL DELAY

LCALL DELAY

CLR SCL

LCALL DELAY

LCALL DELAY

MOV R2,#8

J5:   SETB SCL

LCALL DELAY

LCALL DELAY

MOV C,SDA

RLC A

LCALL DELAY

LCALL DELAY

CLR SCL

LCALL DELAY

LCALL DELAY

DJNZ R2,J5

CLR SDA

LCALL DELAY

LCALL DELAY

SETB SCL   ;第九个时钟周期,应将SDA拉低作为应答信号

LCALL DELAY

LCALL DELAY

CLR SCL   ;释放总线

LCALL DELAY

LCALL DELAY

SETB SDA

RET

汇编2:

;################序列读最后一字节###############

;读最后一字节时需要发送停止信号

IIC_RL:

CLR A

CLR C

LCALL DELAY

LCALL DELAY

CLR SCL

LCALL DELAY

LCALL DELAY

MOV R2,#8

J50: SETB SCL

LCALL DELAY

LCALL DELAY

MOV C,SDA

RLC A

LCALL DELAY

LCALL DELAY

CLR SCL

LCALL DELAY

LCALL DELAY

DJNZ R2,J50

SETB SDA

LCALL DELAY

LCALL DELAY

SETB SCL                ;停止信号

LCALL DELAY

LCALL DELAY

RET

C语言1: 单字节读

unsigned char iic_read_byte(void)

{

unsigned char i,j=0;

delay();

SCL=0;

delay();

for(i=0;i<8;i++)

{

SCL=1;

delay();

j<<=1;

if(SDA==1)

j+=1;

delay();

SCL=0;

delay();

}

SDA=0;

delay();

SCL=1;

delay();

SCL=0;

delay();

SDA=1;

return j;

}

C语言2: 序列读最后一字节

unsigned char iic_read_last_byte(void)

{

unsigned char I,j=0;

delay();

SCL=0;

delay();

for(i=0;i<8;i++)

{

SCL=1;

delay();

j<<=1;

if(SDA==1)

j+=1;

delay();

SCL=0;

delay();

}

SDA=1;

delay();

SCL=1;    //停止信号

delay();

return j;

}

举例: 以AT公司生产的IIC器件EEPROM: at24c64为例,对该器件进行读写

1.      原理图

AT24C64器件简介:

2.将位于R0(buf)所指向的地址单元中的COUNT(count)个数据写入AT24C64的ADDRH,ADDRL(addrh,dddrl)地址单元中.(括号内为c语言变量)

汇编:(会用到上面给出的IIC驱动子程序以及定义的一些变量和接口)

ADDRH   EQU 13H

ADDRL   EQU 14H           ;定义读写AT24C64的首地址

STOR1:  MOV COUNT,#4      ;写入的字节数

MOV  ADDRH,#xx    ; 写入到AT24C64的地址字

MOV  ADDRL,#xx

LCALL WRDAT     ;将位于R0所指向的地址单元中的COUNT个数据写入

;AT24C64的ADDRH,ADDRL地址单元中

;###########所有参数写入AT24C64,共4字节#################

;说明:将表号和用户电量共四字节数据写入AT24C64中

;入口参数:

;    1.数据间接寻址地址-R0

;    2.写入到AT24C64的地址字-ADDRH,ADDRL

;    3.写入字节数-COUNT

;出口参数:无

;#######################################################

WRDAT:  LCALL IIC_ST         ;START

MOV A,#0A0H

LCALL IIC_WB        ;写器件寻址00H(第一片AT24C64)  将A中的字符发送

JB PSW.5,WRDAT

MOV A,ADDRH

LCALL IIC_WB

JB PSW.5,WRDAT

MOV A,ADDRL

LCALL IIC_WB       ;存储单元地址

JB PSW.5,WRDAT

MOV R7,COUNT

WRDAT0: MOV A,@R0

LCALL IIC_WB        ;写入数据

JB PSW.5,WRDAT

INC R0

DJNZ R7,WRDAT0

LCALL IIC_SP     ;停止

LCALL DL20MS   ;延时,等待将数据擦写到at24c64中

RET

C语言:

unsigned char count=0x04;

unsigned char addrh=0xxx;

unsigned char addrl=0xxx;

unsigned char t_buf[];

while(!write_byte(t_buf,addrh,addrl,count));

/*###########所有参数写入AT24C64,共4字节#################

//说明:将表号和用户电量共四字节数据写入AT24C64中

//入口参数:

;    1.数据间接寻址地址-buf

;    2.写入到AT24C64的地址字-addh,addrl

;    3.写入字节数-count

;出口参数:1表示写成功,0表示写失败

;#######################################################*/

bit write_byte(unsigned char * buf,             //

unsigned char addrh,

unsigned char addrl,

unsigned char count)

{

unsigned char i;

iic_start();             //start

iic_write_byte(0x0a0);          //写器件寻址0x00(第一片at24c64)

if(PSW.5)

return 0;

iic_write_byte(addrh);

if(PSW.5)

return 0;

iic_write_byte(addrl);

if(PSW.5)

return 0;

for(i=0;i<count;i++)

{

iic_write_byte(*buf);

if(PSW.5)

return 0;

buf++;

}

iic_stop();

return 1;

}

2.      从at24c64的ADDRH,ADDRL(addrh,addrl)地址单元中读出COUNT(count)个数据存放到单片机R0(buf)指定的地址单元中.(括号中为C语言变量)

汇编: (会用到上面给出的IIC驱动子程序以及定义的一些变量和接口)

ADDRH   EQU 13H

ADDRL   EQU 14H           ;定义读写AT24C64的首地址

STOR1:  MOV COUNT,#4      ;读出入的字节数

MOV  ADDRH,#xx    ; 读入的AT24C64的地址字

MOV  ADDRL,#xx

LCALL LDDAT      ; 从at24c64中读数据

;/*############从at24c64中读数据#########################

; 入口参数:

LDDAT:  LCALL IIC_ST         ;START

MOV A,#0A0H                ;对器件进行写

LCALL IIC_WB        ;虚写操作器件寻址00H(第一片AT24C64)

JB PSW.5,LDDAT

MOV A,ADDRH

LCALL IIC_WB       ;

JB PSW.5,LDDAT

MOV A,ADDRL

LCALL IIC_WB        ;虚写存储单元地址

JB PSW.5,LDDAT

;以上为先初始化一个读数据地址

LCALL IIC_ST         ;START

MOV A,#0A1H

LCALL IIC_WB        ;读操作器件寻址00H(第一片AT24C64)

JB PSW.5,LDDAT

MOV R7,COUNT

CJNE R7,#01,LD01

LJMP LDDAT1

LD01:   DEC R7

LDDAT0: LCALL IIC_RB        ;现行地址读(0000H)

MOV @R0,A

INC R0

DJNZ R7,LDDAT0

LDDAT1: LCALL IIC_RL            ;读最后一字节,读完后给AT24C64发停止信号

MOV @R0,A

inc r0

LCALL IIC_SP                    ;停止信号

RET

C语言:

unsigned char count=0x04;

unsigned char addrh=0xxx;

unsigned char addrl=0xxx;

unsigned char r_buf[];

while(!read_byte(r_buf,addrh,addrl,count));

/*            */

bit read_byte(unsigned char *buf,        //存放读到的数据

unsigned char addrh,

unsigned char addrl,        //要读的数据地址

unsigned char count)              //需要读的个数

{

unsigned char i;

iic_start();

iic_write_byte(0x0a0);                 //对器件进行寻址,虚写操作器件 寻址00H(第一片)

if(PSW.5)

return 0;

iic_write_byte(addrh);                  //虚写存储单元地址

if(PSW.5)

return 0;

iic_write_byte(addrl);                   //虚写存储单元地址

if(PSW.5)

return 0;

//以上为初始化一个读数据地址

iic_start();                           //重发起始信号

iic_write_byte(0x0a1);        //对器件读命令

if(PSW.5)

return 0;

if(count==1)

{

*buf=iic_read_last_byte();

buf++;

}

else

{

for(i=0;i<count;i++)

{

*buf=iic_read_byte();

buf++;

}

}

iic_stop();

return 1;

}

IIC总线协议---以存储芯片at24c64为例相关推荐

  1. FPGA IIC总线协议简介

    1.1 FPGA IIC总线协议简介 1.1.1 本节目录 1)本节目录: 2)本节引言: 3)FPGA简介: 4)FPGA IIC总线协议简介: 5)结束语. 1.1.2 本节引言 "不积 ...

  2. IIC总线协议及应用

    IIC总线协议及应用 I2C总线知识 I2C总线物理拓扑结构 I2C总线特征 I2C总线协议 数据有效性 响应 I2C总线操作 IIC总线应用案例 RT1052的LPI2C总线特性及架构 通讯引脚 驱 ...

  3. IIC 总线协议(Verilog)

    IIC (Inter - Integrated Circuit BUS) 集成电路总线,它是一种串行通信总线,多使用主从架构.IIC 接口共有两条总线线路,即 SCL(串行时钟线).SDA(串行数据线 ...

  4. IIC总线协议基本原理以及GPIO虚拟IIC接口

    IIC 一般应用于芯片之间的通信,是半双工串行同步通信总线,它的传输距离短,但其好处是 IIC 支持一主多从的挂载方式,因此主机和多个从机之间的通信线只要两条就够了, IIC硬件结构: IIC 串行总 ...

  5. IIC总线协议,7位,8位,10位地址

    IIC总线 1.1. 概述 IIC开发于1982年,当时是为了给电视机内的CPU和外围芯片提供更简易的互连方式.电视机是最早的嵌入式系统之一,而最初的嵌入系统是使用内存映射(memory-mapped ...

  6. 【STM32】【STM32CubeMX】STM32CubeMX的使用之四:IIC总线协议驱动SHT30温湿度传感器

    文章目录 0.前言 1.传感器介绍 1.1.传感器简介 1.2.传感器板原理图 1.3.传感器引脚定义 1.4.数据采集工作流程 1.4.1.单次数据采集模式 1.4.2.周期型数据采集模式 1.5. ...

  7. STM32使用IIC总线通讯协议在OLED屏幕上显示字符串、汉字、图像(硬件IIC)

    参考:基于STM32-Oled(IIC)的使用 作者:奋斗的小殷 发布时间: 2021-05-07 13:09:26 网址:https://blog.csdn.net/boybs/article/de ...

  8. 用Proteus学习51单片机之I2C(IIC)总线

    最近刚做好一个站,基于rails 3,教程为主,大家捧场看看,谢谢!www.yo945.com 在学习单片机的过程中,我常有这样的烦恼:随随便便一个芯片,少则占用三五个IO口,一般的就占用8个,稍微想 ...

  9. IIC总线的原理与Verilog实现

    IIC总线的原理与Verilog实现 1. 软件平台与硬件平台 2. 原理介绍 2.1 IIC总线的特点: 2.2 IIC总线协议详解: 2.2.1 IIC主机往从机里面写入数据的步骤 2.2.2 I ...

最新文章

  1. CV之FE:基于TF进行FE——去除异常(被损坏)图像 和单通道图像
  2. Java虚拟机(JVM)以及跨平台原理
  3. 结合awk列举大于指定容量大小所有文件目录
  4. 验证码之字符的特征提取
  5. 嵌入式web服务器预研报告(转)
  6. API网关如何实现对服务下线实时感知
  7. win10自动切换日夜模式
  8. typora使用pandoc导出功能
  9. [数位dp] Jzoj P4239 光棍
  10. 循环减肥c语言,最好的减肥方法
  11. 对variable-sized object may not be initialized的一点理解
  12. 详谈PC端软件 - 加壳与脱壳
  13. 应届生落北京集体户口
  14. Razorpay 印度第三方支付机构 Razorpay 支付,放款,还款实际操作
  15. (67)TCL脚本命令【incr(一个参数)】
  16. html阴影 渐变,CSS 阴影 轮廓 渐变详解
  17. SNMP采集测试工具使用方法
  18. linux ad接口实验结论,计算机输入输出系统接口实验报告 · 东南大学Linux俱乐部...
  19. centos7 npm bulid编译报错解决
  20. 盛大的娱乐帝国路线图

热门文章

  1. Okhttp 接入HttpDNS(支持http/https,)达到IP直连
  2. 在JS数组特定索引处指定位置插入或修改元素的技巧
  3. 什么是内存泄露?该怎么排查?Java内存泄漏策略
  4. dotween 的学习1.DoTween.To()的了解
  5. ZYNQ开发系列——ZYNQ系统的搭建
  6. 灰色预测GM(1,1)代码
  7. 基于Opencv的车距检测系统(源码&教程)
  8. 马斯洛的需要层次理论
  9. 如何将ppt转换为jpg图片
  10. AutoLayout -Masonry