单片机课程设设计单总线和I2C总线结合实现数.docx
《单片机课程设设计单总线和I2C总线结合实现数.docx》由会员分享,可在线阅读,更多相关《单片机课程设设计单总线和I2C总线结合实现数.docx(19页珍藏版)》请在冰豆网上搜索。
![单片机课程设设计单总线和I2C总线结合实现数.docx](https://file1.bdocx.com/fileroot1/2023-1/23/e3732c75-dcf5-41d0-a007-a999e224c510/e3732c75-dcf5-41d0-a007-a999e224c5101.gif)
单片机课程设设计单总线和I2C总线结合实现数
单片机课程设计题目:
单总线和I2C总线结合实现数字温度计实验
班级:
设计者:
指导教师:
单总线和I2C总线结合实现数字温度计实验
一、实验目的
通过本实验,理解掌握单总线器件和I2C总线器件的应用,熟悉串行总线的操作
技巧。
二、实验设备及器件
IBMPC机一台
DP-51PROC单片机综合仿真实验仪一台
三、实验内容
1.编写程序,通过单片机的P3.3口控制一个DS18B20完成数字温度的采集,然后
用程序处理采集到的数据结果。
2.编写程序,通过I2C总线器件ZLG7290实现温度数据的输出显示。
3.结合以上两部分程序,编程实现数字式温度计的程序设计。
四、实验要求
熟练掌握单总线方式器件的应用,熟悉I2C总线协议,学习I2C器件的使用方法。
五、实验过程和步骤
(一、新建工程文件
1、点击工具栏Project选项,在下拉菜单中选择NewProject命令,弹出项目文件保存对话框,输入项目名后,点击保存按钮。
2、在工程建立完毕以后,uVision会弹出器件选择窗口,选择相应的器件型号。
如想修改,可点击工具栏Project选项,在下拉菜单中选择SelectDeviceforTarget…Target‟命令。
3、点击工具栏File选项,选中New命令,新建文件,输入源程序。
4、把文件保存到磁盘中,如用汇编语言编写程序用.asm为扩展名,如用C语言编写程序用.c为扩展名。
5、添加该文件到工程中,在Projectwindos窗口内,选中SourceGroup1然后点击鼠标右键,选择AddfilestoGroup“SourceGroup1”,选择刚才创建的源程序文件,单击Add按钮。
(二、程序文件的编译、链接
1.安装B4区JP12接口上的短路帽,将B4区的DQ与A2区INT1(P3.3相连。
2.安装D5区JP1接口上的短路帽,将D5区的SDA、SCL分别与A2区的P17、
P16相连。
3.将D5区的RST_L针接上高电平。
4.按照下面的程序在KeilC51集成开发环境中建立工程文件,并进行调试仿真。
TEMPER_LEQU36H;存放读出温度低位数据
TEMPER_HEQU35H;存放读出温度高位数据
TEMPER_NUMEQU37H;存放转换后的温度值
FLAG1BIT00H
DQBITP3.3;一线总线控制端口
SDABITP1.7;I2C总线定义
SCLBITP1.6
MTDEQU40H;发送数据缓冲器
MRDEQU49H;接收数据缓冲区
;定义器件地址,变量
ZLG7290EQU70H;ZLG7290的器件地址
ACKBIT10H;应答标志位
SLADATA50H;器件的从地址
SUBADATA51H;器件的子地址
NUMBYTEDATA52H;读/写的字节数变量
ORG0000H
LJMPMAIN
ORG0100H
;-------温度计主程序如下:
MAIN:
MOVSP,#70H
DISP_LOOP:
LCALLGET_TEMPER;从DS18B20读出温度数据
LCALLTEMPER_COV;转换读出的温度数据并保存
LCALLDELAY
MOVMTD,#60H
MOVMTD+1,TEMPER_NUM;温度值低位
ANLMTD+1,#0FH
MOVSLA,#ZLG7290;指定器件地址
MOVSUBA,#07H;指定子地址
MOVNUMBYTE,#02H;发送2字节数据
LCALLIWRNBYTE;调用写2字节数据程序
MOVMTD,#61H
MOVA,TEMPER_NUM
SWAPA
ANLA,#0FH
MOVMTD+1,A;温度值高位
MOVSLA,#ZLG7290;指定器件地址
MOVSUBA,#07H;指定子地址
MOVNUMBYTE,#02H;发送2字节数据
LCALLIWRNBYTE;调用写2字节数据程序
LCALLDELAY
SJMPDISP_LOOP;温度循环采集显示
;-------读出转换后的温度值
GET_TEMPER:
SETBDQ;定时入口
BCD:
LCALLINIT_1820
JBFLAG1,S22
LJMPBCD;若DS18B20不存在则返回S22:
LCALLDELAY1
MOVA,#0CCH;跳过ROM匹配------0CC
LCALLWRITE_1820
MOVA,#44H;发出温度转换命令
LCALLWRITE_1820
NOP
LCALLDELAY
LCALLDELAY
CBA:
LCALLINIT_1820
JBFLAG1,ABC
LJMPCBA
ABC:
LCALLDELAY1
MOVA,#0CCH;跳过ROM匹配
LCALLWRITE_1820
MOVA,#0BEH;发出读温度命令
LCALLWRITE_1820
LCALLREAD_18200;READ_1820
RET
;-------读DS18B20的程序,从DS18B20中读出一个字节的数据READ_1820:
MOVR2,#8
RE1:
CLRC
SETBDQ
NOP
NOP
CLRDQ
NOP
NOP
NOP
SETBDQ
MOVR3,#7
DJNZR3,$
MOVC,DQ
MOVR3,#23
DJNZR3,$
RRCA
DJNZR2,RE1
RET
;-------写DS18B20的程序
WRITE_1820:
MOVR2,#8
CLRC
WR1820:
CLRDQ
MOVR3,#6
DJNZR3,$
RRCA
MOVDQ,C
MOVR3,#23
DJNZR3,$
SETBDQ
NOP
DJNZR2,WR1820
SETBDQ
RET
;-------读DS18B20的程序,从DS18B20中读出两个字节的温度数据
READ_18200:
MOVR4,#2;将温度高位和低位从DS18B20中读出
MOVR1,#36H;低位存入36H(TEMPER_L,高位存入35H(TEMPER_HRE00:
MOVR2,#8
RE01:
CLRC
SETBDQ
NOP
NOP
CLRDQ
NOP
NOP
NOP
SETBDQ
MOVR3,#7
DJNZR3,$
MOVC,DQ
MOVR3,#23
DJNZR3,$
RRCA
DJNZR2,RE01
MOV@R1,A
DECR1
DJNZR4,RE00
RET
;-------将从DS18B20中读出的温度数据进行转换
TEMPER_COV:
MOVA,#0F0H
ANLA,TEMPER_L;舍去温度低位中小数点后的四位温度数值SWAPA
MOVTEMPER_NUM,A
MOVA,TEMPER_L
JNBACC.3,TEMPER_COV1;四舍五入去温度值
INCTEMPER_NUM
TEMPER_COV1:
MOVA,TEMPER_H
ANLA,#07H
SWAPA
ADDA,TEMPER_NUM
MOVTEMPER_NUM,A;保存变换后的温度数据
LCALLBIN_BCD
RET
;-------将16进制的温度数据转换成压缩BCD码
BIN_BCD:
MOVDPTR,#TEMP_TAB
MOVA,TEMPER_NUM
MOVCA,@A+DPTR
MOVTEMPER_NUM,A
RET
TEMP_TAB:
DB00H,01H,02H,03H,04H,05H,06H,07H
DB08H,09H,10H,11H,12H,13H,14H,15H
DB16H,17H,18H,19H,20H,21H,22H,23H
DB24H,25H,26H,27H,28H,29H,30H,31H
DB32H,33H,34H,35H,36H,37H,38H,39H
DB40H,41H,42H,43H,44H,45H,46H,47H
DB48H,49H,50H,51H,52H,53H,54H,55H
DB56H,57H,58H,59H,60H,61H,62H,63H
DB64H,65H,66H,67H,68H,69H,70H,71H
DB72H,73H,74H,75H,76H,77H,78H,79H
DB80H,81H,82H,83H,84H,85H,86H,87H
DB88H,89H,90H,91H,92H,93H,94H,95H
DB96H,97H,98H,99H
;-------DS18B20初始化程序
INIT_1820:
SETBDQ
NOP
CLRDQ
MOVR0,#80H
TSR1:
DJNZR0,TSR1;延时
SETBDQ
MOVR0,#25H;96US-25H
TSR2:
DJNZR0,TSR2
JNBDQ,TSR3
LJMPTSR4;延时
TSR3:
SETBFLAG1;置标志位,表示DS1820存在LJMPTSR5
TSR4:
CLRFLAG1;清标志位,表示DS1820不存在LJMPTSR7
TSR5:
MOVR0,#06BH;200US
TSR6:
DJNZR0,TSR6;延时
TSR7:
SETBDQ
RET
;-------重新写DS18B20暂存存储器设定值
RE_CONFIG:
JBFLAG1,RE_CONFIG1;若DS18B20存在,转RE_CONFIG1RET
RE_CONFIG1:
MOVA,#0CCH;发SKIPROM命令
LCALLWRITE_1820
MOVA,#4EH;发写暂存存储器命令
LCALLWRITE_1820
MOVA,#00H;TH(报警上限中写入00H
LCALLWRITE_1820
MOVA,#00H;TL(报警下限中写入00H
LCALLWRITE_1820
MOVA,#7FH;选择12位温度分辨率
LCALLWRITE_1820
RET
;------------------延时子程序
DELAY:
MOVR7,#00H
MIN:
DJNZR7,YS500
RET
YS500:
LCALLYS500US
LJMPMIN
YS500US:
MOVR6,#00H
DJNZR6,$
RET
DELAY1:
MOVR7,#20H
DJNZR7,$
RET
$INCLUDE(VI2C_ASM.INC;包含VIIC软件包
;
END
;启动I2C总线子程序
START:
SETBSDA
NOP
SETBSCL;起始条件建立时间大于4.7us
NOP
NOP
NOP
NOP
NOP
CLRSDA
NOP;起始条件锁定时大于4us
NOP
NOP
NOP
NOP
CLRSCL;钳住总线,准备发数据
NOP
RET
;结束总线子程序
STOP:
CLRSDA
NOP
SETBSCL;发送结束条件的时钟信号
NOP;结束总线时间大于4us
NOP
NOP
NOP
NOP
SETBSDA;结束总线
NOP;保证一个终止信号和起始信号的空闲时间大于4.7us
NOP
NOP
NOP
RET
;发送应答信号子程序
MACK:
CLRSDA;将SDA置0
NOP
NOP
SETBSCL
NOP;保持数据时间,即SCL为高时间大于4.7us
NOP
NOP
NOP
NOP
CLRSCL
NOP
NOP
RET
;发送非应答信号
MNACK:
SETBSDA;将SDA置1
NOP
NOP
SETBSCL
NOP
NOP;保持数据时间,即SCL为高时间大于4.7us
NOP
NOP
NOP
CLRSCL
NOP
NOP
RET
;检查应答位子程序
;返回值,ACK=1时表示有应答
CACK:
SETBSDA
NOP
NOP
SETBSCL
CLRACK
NOP
NOP
MOVC,SDA
JCCEND
SETBACK;判断应答位CEND:
NOP
CLRSCL
NOP
RET
;发送字节子程序
;字节数据放入ACC
;每发送一字节要调用一次CACK子程序,取应答位WRBYTE:
MOVR0,#08H
WLP:
RLCA;取数据位JCWR1
SJMPWR0;判断数据位WLP1:
DJNZR0,WLP
NOP
RET
WR1:
SETBSDA;发送1NOP
SETBSCL
NOP
NOP
NOP
NOP
NOP
CLRSCL
SJMPWLP1
WR0:
CLRSDA;发送0NOP
SETBSCL
NOP
NOP
NOP
NOP
NOP
CLRSCL
SJMPWLP1
;读取字节子程序
;读出的值在ACC
;每取一字节要发送一个应答/非应答信号
RDBYTE:
MOVR0,#08H
RLP:
SETBSDA
NOP
NOP
NOP
NOP
SETBSCL;时钟线为高,接收数据位
NOP
NOP
NOP;+1
NOP;+1
NOP;+1
NOP;+1
NOP;+1
MOVC,SDA;读取数据位
MOVA,R2
CLRSCL;将SCL拉低,时间大于4.7us
RLCA;进行数据位的处理
MOVR2,A
NOP
NOP
NOP
NOP;+1
NOP;+1
NOP;+1
NOP
NOP
NOP;+1
NOP
NOP;+1
NOP;+1
DJNZR0,RLP;未够8位,再来一次
RET
;========================================================================================
;========================================================================================
;以下是用户接口子程序
;
;无子地址器件写字节数据
;入口参数:
数据为ACC、器件从地址SLA
;占用:
A、R0、CY
IWRBYTE:
PUSHACC
IWBLOOP:
LCALLSTART;起动总线
MOVA,SLA
LCALLWRBYTE;发送器件从地址
LCALLCACK
JNBACK,RETWRB;无应答则跳转
POPACC;写数据
LCALLWRBYTE
LCALLCACK
LCALLSTOP
RET
RETWRB:
POPACC
LCALLSTOP
RET
;无子地址器件读字节数据
;入口参数:
器件从地址SLA
;出口参数:
数据为ACC
;占用:
A、R0、R2、CY
IRDBYTE:
LCALLSTART
MOVA,SLA;发送器件从地址
INCA
LCALLWRBYTE
LCALLCACK
JNBACK,RETRDB
LCALLRDBYTE;进行读字节操作
LCALLMNACK;发送非应信号
RETRDB:
LCALLSTOP;结束总线
RET
;向器件指定子地址写N字节数据
;入口参数:
器件从地址SLA、器件子地址SUBA、发送数据缓冲区MTD、发送字节数NUMBYTE
;占用:
A、R0、R1、R3、CY
IWRNBYTE:
MOVA,NUMBYTE
MOVR3,A
LCALLSTART;起动总线
MOVA,SLA
LCALLWRBYTE;发送器件从地址
LCALLCACK
JNBACK,RETWRN;无应答则退出
MOVA,SUBA;指定子地址
LCALLWRBYTE
LCALLCACK
MOVR1,#MTD
WRDA:
MOVA,@R1
LCALLWRBYTE;开始写入数据
LCALLCACK
JNBACK,IWRNBYTE
INCR1
DJNZR3,WRDA;判断写完没有RETWRN:
LCALLSTOP
RET
;向器件指定子地址读取N字节数据
;入口参数:
器件从地址SLA、器件子地址SUBA、接收字节数NUMBYTE;出口参数:
接收数据缓冲区MTD
;占用:
A、R0、R1、R2、R3、CY
IRDNBYTE:
MOVR3,NUMBYTE
LCALLSTART
MOVA,SLA
LCALLWRBYTE;发送器件从地址
LCALLCACK
JNBACK,RETRDN
MOVA,SUBA;指定子地址
LCALLWRBYTE
LCALLCACK
LCALLSTART;重新起动总线
MOVA,SLA
INCA;准备进行读操作
LCALLWRBYTE
LCALLCACK
JNBACK,IRDNBYTE
MOVR1,#MRD
RDN1:
LCALLRDBYTE;读操作开始
MOV@R1,A
;NOP;+1
;NOP;+1
DJNZR3,SACK
LCALLMNACK;最后一字节发非应答位RETRDN:
LCALLSTOP;并结束总线
RET
SACK:
LCALLMACK
INCR1
SJMPRDN1
;无子地址器件写N字节数据
;入口参数:
器件从地址SLA、发送数据缓冲区MTD、发送字节数NUMBYTE;占用:
A、R0、R1、R3、CY
;不发送子地址SUBA,直接发送多个数据.
IWRNBYTEEXT:
MOVA,NUMBYTE
MOVR3,A
LCALLSTART;起动总线
MOVA,SLA
LCALLWRBYTE;发送器件从地址
LCALLCACK
JNBACK,RETWRNE;无应答则退出
MOVR1,#MTD
WRDAE:
MOVA,@R1
LCALLWRBYTE;开始写入数据
LCALLCACK
JNBACK,RETWRNE
INCR1
DJNZR3,WRDAE;判断写完没有RETWRNE:
LCALLSTOP
RET
;无子地址器件读取N字节数据
;入口参数:
器件从地址SLA、器件子地址SUBA、接收字节数NUMBYTE
;出口参数:
接收数据缓冲区MTD
;占用:
A、R0、R1、R2、R3、CY
;说明:
此函数不发送子址,也不重新启动总线,而是直接读取多个数据.IRDNBYTEEXT:
MOVR3,NUMBYTE
LCALLSTART
MOVA,SLA
INCA
LCALLWRBYTE;发送器件从地址
LCALLCACK
JNBACK,RETRDNE
MOVR1,#MRD
RDNE1:
LCALLRDBYTE;读操作开始
MOV@R1,A
DJNZR3,SACKE
LCALLMNACK;最后一字节发非应答位
RETRDNE:
LCALLSTOP;并结束总线
RET
SACKE:
LCALLMACK
INCR1
SJMPRDNE1
软件调试的具体步骤如下:
1打开keil集成开发环境,新建一个新的工程文件。
2根据需要为工程选择目标器件组和相应的器件号。
3创建源程序文件并输入程序代码。
4保存创建的源程序项目文件。
5把源程序文件添加到项目中。
6点击菜单栏上的Project项,选择Optionfortarget…target1‟将出现调试环境设置界面。
在Debug栏内选UseSimulator用软件模拟仿真。
7编译连接环境设置,选中CreateHexFile选项,在编译时就可以自动生成目标代码文件*.hex。
硬件调试仿真的具体步骤如下:
1修改源程序入口地址为8000H;
2点击菜单栏上的Project项,选择Optionfortarget…target1‟将出现调试环境设置界面。
在Debug栏内选UseMON51选项,并在该栏后的驱动方式选择框内的选这时的驱动程序库。
对于51仿真器应选择KeilMonitoe-51Diver选项。
同时在Settings项中设置串行通信的端口和波特率9600bps,这要求和通信协议上一致。
由于MON51监控程序已经占用了0000H~7FFFH,用户应用程序必须从8000H开始存放。
故在off-chipcodememory-Eprom设为0x8000,长度0x4000。
off-chipXdatamemory-Ram设为0xC000,长度0x4000。
3配置好环境设置后,对文件进行编译。
如果编译成功,则产生目标文件。
如果有错误则更正错误,重新编译直至完全正确为止。
4连接好DP-51PROC实验仪,对实验仪上电,打开DPFlash,把仿真器上的开关拨到LOAD模式,ISP跳线JP14跳开,按下复位键,即进入下载状态。
在DPFlash上型号的下拉菜单选择DP-51PROC,然后根据你所插的通信口选择相应的通信口。
点击编程按钮,选择MON51选项,开始下载到TKSMonitor51仿真器的Flash中。
再将仿真器工作模式改为run,重启,仿真器进入调试状态。
5关掉DPFlash,点击DEBUG菜单,选中Start/StopDebugSession调试命令,这样既可以把用户程序下载到仿真器的SRAM中。
单击go!
进行控制。
脱机运行的具体步骤如下:
1修改源程序入口地址为0000H;
2点击菜单栏上的Project项,选择Optionfortarget…target1‟将出现调试环境设置界面。
Target属性的设置,设置Off-ChipCodeMemory栏内的Eprom选项,start下输入0x0000,size下输入0x4000;Off-ChipXdatamemory栏内的Eprom选项,start下输入0xC000,size下输入0x4000。
3)连接好DP-51PROC实验仪,对实验仪上电,打开DPFlash,把仿真器上的开关拨到LOAD模式,ISP跳线JP14跳开,按下复位键,即进入下载状态。
在DPFlash上型号的下拉菜单选择DP-51PROC,然后根据你所插的通信口选择相应的通信口。
装载文件,点击编程按钮,选择编程文件区选项,将生成的目标文件下载到TKSMonitor51仿真器的Flash中。
再将仿真器工作模式改为run,重启,仿真器进入脱机运行状态。
5.观察D5区数码管显示的温度数据。
然后改变DS18B20