实验八 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-4us
2、SDA拉高,保持时间约为1.2-4us;
应答信号:接收数据的IC在接收到8bit数据后,向发送数据的IC发出特定的低电平脉冲,表示已收到数据。CPU向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传递信号的判断。
若未收到应答信号,由判断为受控单元出现故障。应答信号的时序图如下所示:
应答时序图
发送时的应答信号
;**********应答信号**********
ACK: SETB SDA ;数据线置高
SETB SCL ;时钟线置高
ACALL DELAY
JB SDA,$ ;等待数据线变低
ACALL DELAY
CLR SCL ;时钟线置低
RET
注意:这里如果数据线一直为高将进入死循环,所以一般我们都会在这做一个容错的处理。具体的程序如下:
ACK: MOV R4,#00H
SETB SDA
SETB SCL
LOP0: JNB SDA,LOP
DJNZ R4,LOP0 ;循环255次
LOP: ACALL DEL
CLR SCL
RET
接收时的应答信号
ACK1: CLR SDA ;数据线置低
SETB SCL ;时钟线置高
NOP
NOP
CLR SCL ;时钟线置低
SETB SDA ;数据线置高
RET
3、字节的发送和接收
写周期时序图一字节数据发送子程序,流程如下:
图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.6
I2C_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 0000H
LJMP START
ORG 0030H
START: MOV SP,#70H
MOV I2C_Data ,#00H
MOV I2C_Addr,#0FH
ACALL I2C_READ
MOV I2C_Data ,A ;读出数据
INC I2C_Data
MOV I2C_Addr ,#0FH ;更新数据
ACALL I2C_WRITE
LCALL 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_Data
MOV B,#100
DIV AB
JZ L1 ;根据百位是否等于0确定百位的显示
MOV D_BUF2,A ;百位不等于0,直接显示百位的数字
SETB FLAG ;百位不等于0,标志位置1
AJMP NEX
L1: MOV D_BUF2,#25 ;百位等于0,对百位赋一个超过段码个数的值
NEX: MOV A,B ;对十位数的处理
MOV B,#10
DIV AB ;根据十位是否等于0确定十位的显示
JZ L2
L3: MOV D_BUF1,A ; 十位等于0,百位不等于0,显示十位的数字AJMP NEX1
L2: JB FLAG,L3 ;十位等于0,判断百位是否也为0
MOV 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,#3
MOV R7,#0FEH
MOV DPTR,#TAB
MOV R0,#D_BUF0
LOPP1: MOV A,@R0
MOVC A,@A+DPTR
MOV P0,A
MOV P2,R7
LCALL DELAY5MS ;动态扫描延时,消除余辉效应
INC R0
MOV A,R7
RL A
MOV R7,A
DJNZ R6,LOPP1
NOP
RET
;************************************************************************** ;函数名称:DELAY5MS
;输入参数:无
;输出参数:无
;占用资源:60H,61H,62H
;函数功能:延时5MS(24MHz晶振)
;************************************************************************** DELAY5MS:
MOV 60H,#1
DDD2: MOV 61H,#20
DDD1: MOV 62H,#248
DJNZ 62H,$
DJNZ 61H,DDD1
DJNZ 60H,DDD2
RET
;************************************************************************** ;函数名称:I2C_WRITE
;输入参数:I2C_Addr,I2C_data
;输出参数:无
;函数功能:24C08字节写,将I2Cdata写入24C08的Address地址单元
;************************************************************************** I2C_WRITE:
I2C_WRITE_A:
ACALL I2C_START
MOV A,#10100000B
LCALL I2C_SEND8BIT
LCALL I2C_ACK
JC I2C_WRITE_A
RS_ADDR:MOV A,I2C_Addr
LCALL I2C_SEND8BIT
LCALL I2C_ACK
JC RS_ADDR
RS_DATA:MOV A,I2C_Data
LCALL I2C_SEND8BIT
LCALL I2C_ACK
JC RS_DATA
LCALL I2C_STOP
LCALL DELAY10MS
RET
;************************************************************************** ;函数名称:I2C_READ
;输入参数:I2C_Addr
;输出参数:I2C_Data
;函数功能:24C08指定字节读,将24C08的Address地址单元的内容读到I2Cdata
;************************************************************************** I2C_READ:
I2C_READ_A:
LCALL I2C_START
MOV A,#10100000B
LCALL I2C_SEND8BIT
LCALL I2C_ACK
JC I2C_READ_A
RS_ADDR2:
MOV A,I2C_Addr
LCALL I2C_SEND8BIT
LCALL I2C_ACK
JC RS_ADDR2
LCALL I2C_START
READ_ADDR:
MOV A,#10100001B
LCALL I2C_SEND8BIT
LCALL I2C_ACK
JC READ_ADDR
ACALL I2C_RECEIVE8BIT
MOV I2C_Data ,A
ACALL I2C_ACK
LCALL I2C_STOP
RET
;************************************************************************** ;函数名称:I2C_START
;输入参数:无
;输出参数:无
;函数功能:实现24C08启动时序的编写
;************************************************************************** I2C_START:
SETB SCL
SETB SDA
NOP ;TSU:STA 延时时间最少0.6us,另外还有一个值为4us
NOP
CLR SDA
NOP ;THD:STA 延时时间最少0.6us,另外还有一个值为4us
NOP
CLR SCL
NOP
NOP
NOP
RET
;************************************************************************** ;函数名称:I2C_STOP
;输入参数:无
;输出参数:无
;函数功能:实现24C08停止时序的编写
;**************************************************************************
I2C_STOP:
CLR SDA
SETB SCL
NOP ;TSU:STO 延时时间最少0.6us,另外还有一个值为4us
NOP
SETB SDA
NOP ;TBUF 新的发送开始前的总线空闲时间,1.2us,还有一个为4.7us NOP
NOP
RET
;************************************************************************** ;函数名称:I2C_ACK
;输入参数:无
;输出参数:C
;函数功能:实现24C08应答时序的编写
;************************************************************************** I2C_ACK:
SETB SDA
SETB SCL
NOP
NOP
JB SDA,I2C_ACK0
CLR C
AJMP I2C_ACK_END
I2C_ACK0:
SETB C
I2C_ACK_END:
CLR SCL
RET
;**************************************************************************
;函数名称:I2C_SEND8BIT
;输入参数:A
;输出参数:无
;函数功能:24C08发送8位数据
;************************************************************************** I2C_SEND8BIT:
MOV B,#08H
I2C_SEND8BIT_A:
RLC A
MOV SDA,C
SETB SCL
NOP
NOP
CLR SCL
DJNZ B,I2C_SEND8BIT_A
RET
;************************************************************************** ;函数名称:I2C_RECEIVE8BIT
;输入参数:无
;输出参数:A
;函数功能:24C08接收8位数据
;************************************************************************** I2C_RECEIVE8BIT:
MOV B,#08H
CLR A
SETB SDA
I2C_RECEIVE8IT_A:
SETB SCL
NOP
NOP
RLC A
CLR SCL
DJNZ B,I2C_RECEIVE8IT_A
RET
;************************************************************************** ;函数名称:DELAY10MS
;输入参数:无
;输出参数:无
;函数功能:实现10MS延时(24MHz晶振)
;************************************************************************** DELAY10MS:
MOV 40H,#2
D2: MOV 41H,#20
D1: MOV 42H,#248
DJNZ 42H,$
DJNZ 41H,D1
DJNZ 40H,D2
RET
;************************************************************************** ; 共阴级数码管段码数据表
;************************************************************************** TAB: DB 3FH;0
DB 06H;1
DB 5BH;2
DB 4FH;3
DB 66H;4
DB 6DH;5
DB 7DH;6
DB 07H;7
DB 6FH;9
END
六、练习题:
1、上面的例题是针对指定字节读的,每个单元所存数据为0-255,请编写一段程序,
要求能存储开机次数在0-65536次。
2、用24c08来存储几句话(内容自定),用矩阵式键盘来选择读取哪一句,并将读出
的句子发送到串口调试助手显示出来。
gobackn协议实验报告
一个数据帧如图所示: 其中有效数据和校验码可能含有转义字符。 (3) 帧中各个字段的定义和编码,计算CRC校验和的多项式定义 帧的定义编码:帧中的第一比特为开头FLAG,第二比特是帧的类型,共定义了{data,ack,nak} frame_kind三种类型,用枚举常量表述,第三比特是顺序编码,用于确定到达帧的顺序,第四比特是ACK捎带确认讯息,记录了当前已收到帧的确认情况,这是数据帧的头部。若为数据帧,从第五比特开始为网路层的数据,到网路层包裹信息结束后,接上4比特的CRC校验讯息,后有一结束字符FLAG表明该帧结束。 CRC校验数:CRC校验数据由函数crc32()产生,函数crc32()返回一个32位整数为数据生成CRC-32校验和,并且把这 32比特校验和附在数据字节之后。 多项式定义:采用的CRC校验方案为CRC-32,生成多项式为: x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x1+1 校验和附加在数据帧尾部,接受方用带校验和的数据来逻辑除以生成多项式,余数为零则数据无误码,反之有误码等待发送方重传。 (4) 协议工作时两个站点之间信息交换的过程控制,尤其是发生误码条件下的控制方案 协议工作时,两个站点通过互发数据包交换数据,而控制讯息则稍带在数据讯息中传递,当遇到超时情况时,则主动发送空数据包以提供讯息。 当出现帧丢失时,如收到帧的序号有跳跃,或者出现CRC校验出错丢弃了某帧,会主动发送NAK否定帧,提示重传,接收方丢弃所有的后续帧。若长期未产生放送消息,则出现ACK超时事件,主动发送ACK帧提示确认,对方收到确认后,滑动窗口继续发送,若一直未收到确认讯息,则出现数据帧超时事件,发送方会自动重发未确认帧。 11.3 软件设计 给出程序的数据结构,模块之间的调用关系和功能,程序流程。 (1)数据结构:数据结构是整个程序的要点之一,程序维护者充分了解数据结构就可以对主 要算法和处理流程有个基本的理解。描述程序中自定义结构体中各成员的用途,定义的全局变量和主函数中的变量的变量名和变量所起的作用。 采用字符数组结构来存放数据帧:
(完整版)计网协议5和协议6程序
程序设计报告 (2011/2012学年第一学期) 题目:数据链路层滑动窗口协议的设计 与实现 专业网络工程 学生姓名朱瑞霖、李小明 学生学号 09211517 、 09211524 日期 2011-12-01
一、实验内容和实验目的 利用所学数据链路层原理,自己设计一个滑动窗口协议,在仿真环境下编程实现有噪音信道环境下两站点之间无差错双工通信。信道模型为8000bps 全双工卫星信道,信道传播时延270毫秒,信道误码率为10-5,信道提供字节流传输服务,网络层分组长度固定为256字节。通过该实验,进一步巩固和深刻理解数据链路层误码检测的CRC 校验技术,以及滑动窗口的工作机理。滑动窗口机制的两个主要目标: (1) 实现有噪音信道环境下的无差错传输; (2)充分利用传输信道的带宽。 在程序能够稳定运行并成功实现第一个目标之后,运行程序并检查在信道没有误码和存在误码两种情况下的信道利用率。为实现第二个目标,提高滑动窗口协议信道利用率,需要根据信道实际情况合理 地为协议配置工作参数,包括滑动窗口的大小和重传定时器时限以及ACK 搭载定时器的时限。这些参数的设计,需要充分理解滑动窗口协议的工作原理并利用所学的理论知识,经过认真的推算,计算出最优 取值,并通过程序的运行进行验证。 通过该实验提高同学的编程能力和实践动手能力,体验协议软件在设计上各种问题和调试难度,设计在运行期可跟踪分析协议工作过程的协议软件,巩固和深刻理解理论知识并利用这些知识对系统进行优化,对实际系统中的协议分层和协议软件的设计与实现有基本的认识。 二、实验环境 Window操作系统下,Microsoft Visual C++ 6.0 集成化开发环境。 三、实验分工 协议5主要由李小明完成,协议6主要由朱瑞霖完成,两协议的测试以及部分参数的设定、测试由两人共同完成。实验报告由李小明和朱瑞霖共同整理完成。 四、软件设计 1、数据结构分析 (a)协议五 #define inc(k)if(k