当前位置:文档之家› 实验八 IIC通信协议

实验八 IIC通信协议

实验八I2C通信协议一、实验目的:1、培养学生阅读资料的能力;2、加深学生对I2C总线通信协议的理解;3、加强学生对模块化编程的理解;二、实验环境:1、硬件环境:PC机一台、单片机实验板一块、母头串口交叉线、USB电源线;2、软件环境:keil uVision2集成开发环境;STC-ISP下载上位机软件;三、实验原理:要学会I2C通信协议的编程,关键是要看懂并掌握其时序图,理解对I2C通信协议相关子程序的实验编写。

I2C通信协议的总线时序图如下所示:I2C总线时序图I2C相关子程序的详细介绍1、起始信号:SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。

2、结束信号:SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据。

起始信号和结束信号的时序图如下所示:起始信号和结束信号的时序图起始信号的流程如下:1、SCL和SDA拉高,保持时间约为0.6us-4us;2、拉低SDA,保持时间为约为0.6us-4us;3、拉低时钟线结束信号的流程如下:1、SCL置高电平,SDA置低电平,保持时间约为0.6us-4us2、SDA拉高,保持时间约为1.2-4us;应答信号:接收数据的IC在接收到8bit数据后,向发送数据的IC发出特定的低电平脉冲,表示已收到数据。

CPU向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传递信号的判断。

若未收到应答信号,由判断为受控单元出现故障。

应答信号的时序图如下所示:应答时序图发送时的应答信号;**********应答信号**********ACK: SETB SDA ;数据线置高SETB SCL ;时钟线置高ACALL DELAYJB SDA,$ ;等待数据线变低ACALL DELAYCLR SCL ;时钟线置低RET注意:这里如果数据线一直为高将进入死循环,所以一般我们都会在这做一个容错的处理。

具体的程序如下:ACK: MOV R4,#00HSETB SDASETB SCLLOP0: JNB SDA,LOPDJNZ R4,LOP0 ;循环255次LOP: ACALL DELCLR SCLRET接收时的应答信号ACK1: CLR SDA ;数据线置低SETB SCL ;时钟线置高NOPNOPCLR SCL ;时钟线置低SETB SDA ;数据线置高RET3、字节的发送和接收写周期时序图一字节数据发送子程序,流程如下:图6-22 发送子程序流程图(2)一字节数据接收子程序,流程如下:图6-23 接收子程序流程图7、写操作(1)字节写图6-24 字节写时序图流程如下:图6-25 字节写的流程图(2)页写图6-26 页写时序图页写流程如下:8、读操作(1)选择读图6-28 选择读时序图图6-29 NO ACK时序图(2)连续读图6-30 连续读时序图四、实验原理图:I2C总线电路图五、实验例题:例题一编写一程序,实现I2C的指定字节读写,用24C08来记录单片机复位或者开机的次数,并将复位或者开机的次数显示在数码管上。

程序分析本程序利用单片机复位时程序总是从0000H开始执行的特性。

用24C08的一个单元来存储开机的次数,程序一开始就将次数读出来,加上本次的开机,显示在数码管上。

再将加1之后的数据存入24c08的对应单元。

程序代码;************************************************************************** ;****程序功能:实现对24C08的字节读写,用24C08记录开机次数,显示在数码管上;****程序编写: 李代勇;****编写日期: 2007/2/04;************************************************************************** ;************************************************************************** ;初始化数据设置;************************************************************************** SDA EQU P1.7 ;定义数据线为P1.7(实验板上已固定,不可更改)SCL EQU P1.6 ;定义始终线为P1.6I2C_Addr EQU 10H ;定义地址缓冲区,存储要读写24C08的单元地址I2C_Data EQU 12H ;用于缓冲要读写的数据D_BUF0 EQU 55H ;数码管显示缓冲区(个位)D_BUF1 EQU 56H ;数码管显示缓冲区(十位)D_BUF2 EQU 57H ;数码管显示缓冲区(百位)FLAG BIT 00H ;定义标志位,确定百位是否等于0,不等于0置1;************************************************************************** ;程序段:主程序;************************************************************************** ORG 0000HLJMP STARTORG 0030HSTART: MOV SP,#70HMOV I2C_Data ,#00HMOV I2C_Addr,#0FHACALL I2C_READMOV I2C_Data ,A ;读出数据INC I2C_DataMOV I2C_Addr ,#0FH ;更新数据ACALL I2C_WRITELCALL DATAEDIT ;数据加工WAIT: LCALL DISPLAY ;显示数据AJMP W AIT;************************************************************************** ;函数名称:DA TAEDIT;输入参数:I2C_Data;输出参数:D_BUF0,D_BUF1,D_BUF2;函数功能:处理数据,确定每一位数码管要显示的数字,; 因为01,只要求显示1,10只要求显示10(而不是显示010); 101要求显示101;************************************************************************** DA TAEDIT:MOV A,I2C_DataMOV B,#100DIV ABJZ L1 ;根据百位是否等于0确定百位的显示MOV D_BUF2,A ;百位不等于0,直接显示百位的数字SETB FLAG ;百位不等于0,标志位置1AJMP NEXL1: MOV D_BUF2,#25 ;百位等于0,对百位赋一个超过段码个数的值NEX: MOV A,B ;对十位数的处理MOV B,#10DIV AB ;根据十位是否等于0确定十位的显示JZ L2L3: MOV D_BUF1,A ; 十位等于0,百位不等于0,显示十位的数字AJMP NEX1L2: JB FLAG,L3 ;十位等于0,判断百位是否也为0MOV D_BUF1,#22 ;百位、十位等于0,十位赋超过段码个数的值NEX1: MOV D_BUF0,B ;个位的赋值RET;************************************************************************** ;函数名称:DISPLAY;输入参数:D_BUF0,D_BUF1,D_BUF2;输出参数:无;占用资源:R6,R7,R0;函数功能:将D_BUF0,D_BUF1,D_BUF2显示在数码管上;************************************************************************** DISPLAY:MOV R6,#3MOV R7,#0FEHMOV DPTR,#TABMOV R0,#D_BUF0LOPP1: MOV A,@R0MOVC A,@A+DPTRMOV P0,AMOV P2,R7LCALL DELAY5MS ;动态扫描延时,消除余辉效应INC R0MOV A,R7RL AMOV R7,ADJNZ R6,LOPP1NOPRET;************************************************************************** ;函数名称:DELAY5MS;输入参数:无;输出参数:无;占用资源:60H,61H,62H;函数功能:延时5MS(24MHz晶振);************************************************************************** DELAY5MS:MOV 60H,#1DDD2: MOV 61H,#20DDD1: MOV 62H,#248DJNZ 62H,$DJNZ 61H,DDD1DJNZ 60H,DDD2RET;************************************************************************** ;函数名称:I2C_WRITE;输入参数:I2C_Addr,I2C_data;输出参数:无;函数功能:24C08字节写,将I2Cdata写入24C08的Address地址单元;************************************************************************** I2C_WRITE:I2C_WRITE_A:ACALL I2C_STARTMOV A,#10100000BLCALL I2C_SEND8BITLCALL I2C_ACKJC I2C_WRITE_ARS_ADDR:MOV A,I2C_AddrLCALL I2C_SEND8BITLCALL I2C_ACKJC RS_ADDRRS_DATA:MOV A,I2C_DataLCALL I2C_SEND8BITLCALL I2C_ACKJC RS_DATALCALL I2C_STOPLCALL DELAY10MSRET;************************************************************************** ;函数名称:I2C_READ;输入参数:I2C_Addr;输出参数:I2C_Data;函数功能:24C08指定字节读,将24C08的Address地址单元的内容读到I2Cdata;************************************************************************** I2C_READ:I2C_READ_A:LCALL I2C_STARTMOV A,#10100000BLCALL I2C_SEND8BITLCALL I2C_ACKJC I2C_READ_ARS_ADDR2:MOV A,I2C_AddrLCALL I2C_SEND8BITLCALL I2C_ACKJC RS_ADDR2LCALL I2C_STARTREAD_ADDR:MOV A,#10100001BLCALL I2C_SEND8BITLCALL I2C_ACKJC READ_ADDRACALL I2C_RECEIVE8BITMOV I2C_Data ,AACALL I2C_ACKLCALL I2C_STOPRET;************************************************************************** ;函数名称:I2C_START;输入参数:无;输出参数:无;函数功能:实现24C08启动时序的编写;************************************************************************** I2C_START:SETB SCLSETB SDANOP ;TSU:STA 延时时间最少0.6us,另外还有一个值为4usNOPCLR SDANOP ;THD:STA 延时时间最少0.6us,另外还有一个值为4usNOPCLR SCLNOPNOPNOPRET;************************************************************************** ;函数名称:I2C_STOP;输入参数:无;输出参数:无;函数功能:实现24C08停止时序的编写;**************************************************************************I2C_STOP:CLR SDASETB SCLNOP ;TSU:STO 延时时间最少0.6us,另外还有一个值为4usNOPSETB SDANOP ;TBUF 新的发送开始前的总线空闲时间,1.2us,还有一个为4.7us NOPNOPRET;************************************************************************** ;函数名称:I2C_ACK;输入参数:无;输出参数:C;函数功能:实现24C08应答时序的编写;************************************************************************** I2C_ACK:SETB SDASETB SCLNOPNOPJB SDA,I2C_ACK0CLR CAJMP I2C_ACK_ENDI2C_ACK0:SETB CI2C_ACK_END:CLR SCLRET;**************************************************************************;函数名称:I2C_SEND8BIT;输入参数:A;输出参数:无;函数功能:24C08发送8位数据;************************************************************************** I2C_SEND8BIT:MOV B,#08HI2C_SEND8BIT_A:RLC AMOV SDA,CSETB SCLNOPNOPCLR SCLDJNZ B,I2C_SEND8BIT_ARET;************************************************************************** ;函数名称:I2C_RECEIVE8BIT;输入参数:无;输出参数:A;函数功能:24C08接收8位数据;************************************************************************** I2C_RECEIVE8BIT:MOV B,#08HCLR ASETB SDAI2C_RECEIVE8IT_A:SETB SCLNOPNOPRLC ACLR SCLDJNZ B,I2C_RECEIVE8IT_ARET;************************************************************************** ;函数名称:DELAY10MS;输入参数:无;输出参数:无;函数功能:实现10MS延时(24MHz晶振);************************************************************************** DELAY10MS:MOV 40H,#2D2: MOV 41H,#20D1: MOV 42H,#248DJNZ 42H,$DJNZ 41H,D1DJNZ 40H,D2RET;************************************************************************** ; 共阴级数码管段码数据表;************************************************************************** TAB: DB 3FH;0DB 06H;1DB 5BH;2DB 4FH;3DB 66H;4DB 6DH;5DB 7DH;6DB 07H;7DB 6FH;9END六、练习题:1、上面的例题是针对指定字节读的,每个单元所存数据为0-255,请编写一段程序,要求能存储开机次数在0-65536次。

相关主题