爱玩科技网
您的当前位置:首页汇编语言单片机实验

汇编语言单片机实验

来源:爱玩科技网
软件实验一 数据传送

一、实验目的

1.熟悉KEIL软件的程序调试方法

2.掌握从外部数据存储器传送到内部存储器的指令 3.掌握算术运算指令

二、实验内容

本实验为软件实验:数据传送实验。这个实验包括两个小实验:1.从外部数据存储器传送到内部RAM中;2.求16个学生的年龄之和,数据存放在20H单元中。此实验均可在脱机模拟状态下调试运行,也可以连接上仿真器与实验箱在线仿真运行。

1.从外部数据存储器传送到内部RAM中

本实验在程序编译之前,将外部数据存储器(XDATA)和内部数据存储器(DATA)窗口打开,并在XDATA窗口在0000H、0001单元分别键入54H、55H。然后程序单步运行或全速运行,观察寄存器A,B,DPTR,R1,R2,R3的值是不是如程序所希望的那样变化,最后看R3的值是不是54H+55H=A9H。 实验源程序如下:

ORG 00H AJMP START ORG 30H START: MOV A, #56H MOV B, #78H MOV DPTR, #00H MOVX A, @DPTR MOV R1, A INC DPTR MOVX A, @DPTR ADD A, R1 MOV R3, A HERE: AJMP HERE END

2.求16个学生的年龄之和

程序运行前,先将16个学生的年龄放在内部数据区20H单元开始的地方,码制为BCD码,程序运行结束时,16个学生的年龄和放在寄存器A和B中(B为高位,A为低位)。

实验源程序如下:

ORG 00H AJMP START ORG 30H

START: MOV R0, #20H MOV R7, #16 MOV A, #00H MOV B, A LOOP: ADD A, @R0 DA A JNC NEXT INC B NEXT: INC R0

DJNZ R7, LOOP HERE: SJMP HERE END

三、实验步骤 1.运行KEIL软件

2.新建项目 project/new project/

3.保存项目 选择保存项目的名称和位置 如abc.uv2

选择单片机的CPU型号 如atmel公司的 c52 4.新建源文件 file/new 5.输入源程序

6.保存源文件 file/save as 选择保存的名称和位置,如abc.a51

7.将源文件加入项目中 source group 1 右键 选择“add file to group” 选择源文件 点击确定 8.编译项目 rebuild all target files

9.调试程序 单击start/stop debug session 进入程序调试状态 10.单步执行程序,或者全速、断点执行程序 debug/step(go)

11.查看执行结果 view/memory window address d:00h 内部RAM X:0000H 外部RAM C:0000H ROM 可以查看相应存储器内的内容

或者选择 view/watcha and call stack window 查看相应变量内容 12.给相应单元赋值,并执行程序,记录执行结果,写出实验报告。

给相应单元赋值方法:鼠标移动到相应单元,点击鼠标右键选择modify memory value输入新值。 13.记录实验中遇到的问题和解决方法。

软件实验二 排序/数制转换

一、实验目的

1.熟练使用KEIL软件调试程序

2.掌握查询指令和循环程序的设计方法 3.掌握数据转换的程序设计方法

4.掌握有关循环程序和数据转换的程序的调试

二、实验内容

1.求8个无符号数的最大值

给定8个无符号数,将其放内部数据区(DATA)中,地址从20H开始,运行下列程序,看看是否将8个数的最大值存储在A寄存器和内部数据区41H单元中。

程序清单如下:

ORG 00H SJMP START ORG 30H

START: MOV R0, #20H MOV R6, #08H MOV A, @R0 DEC R6 LOOP: INC R0

MOV 40H,@R0 CJNE A, 40H, CHK JMP DD1 CHK: JNC SQ

MOV A, 40H

SQ: DJNZ R6, LOOP DD1: MOV 41H, A HERE: SJMP HERE END

附加功能:编程实现内部RAM20H-27H单元八个数从小到大排序

2.将一个字节BCD码转换成二进制数

将R2 中的内容转换成二进制数据,并传送到20H 单元中。

程序清单如下:

ORG 00H AJMP START ORG 30H

START: MOV R2, #99H ACALL DTOB HERE: SJMP HERE DTOB: MOV A, R2 ANL A, #0F0H SWAP A

MOV B, #10 MUL AB MOV R3, A MOV A, R2 ANL A, #0FH ADD A, R3 MOV R3, A MOV 20H, A RET

三、实验步骤

要求:写出实验步骤并记录程序调试结果。

硬件实验一 并行口的使用

一、实验目的

1. 熟悉单片机仿真实验箱XL600+使用方法 2. 学会使用XLISP向单片机烧录程序 3. 学会单片机并行口的使用方法 二、实验内容

使用单片机的并行口P1接8路LED灯,通过程序控制轮流点亮8个灯。为0时灯亮,为1时灯灭。

参考程序: ORG 0000H

JMP MAIN ORG 0030H

;************************************************ MAIN:

MOV A,#0FEH ;赋初始值 LOOP:

MOV R0,#07H ;移动次数 LOOPL:

MOV P0,A MOV P2,A

RL A ;左移 CALL DELAY DJNZ R0,LOOPL

MOV R0,#07H ;移动次数 LOOPR:

MOV P0,A MOV P2,A

RR A ;右移 CALL DELAY DJNZ R0,LOOPR JMP LOOP

;************************************************ DELAY:

MOV R6,#0FFH DEL:

MOV R7,#0FFH DJNZ R7,$ DJNZ R6,DEL RET END

三、实验连线

P1(JP44)----八路指示灯(JP32) 四、实验步骤

1、 按下实验箱的电源开关,使得实验箱接通电源,此时实验箱XL600+上指示灯闪烁

显示3次后熄灭。

2、 连接实验连线 P1(JP44)---八路指示灯(JP32)

3、 新建项目,新建文件,输入源程序,编译程序,生成*.hex文件。

方法:在编译时选择project/options for target ‘target1’在生成hex前打“勾”,然后编译程序,编译成功后*.hex跟源程序在同一位置。

4、 烧录程序 方法:(1)打开lisp软件

(2)操作/检测编程器 显示编程器检测OK字样,表示编程器当前处于正常工作状态。

(3)打开*.hex文件

(4)选择智能一键通,完成*.hex文件烧录

5、烧录完成后,单片机自动执行程序,此时八路指示灯轮流点亮。如果不能正常显示请修改程序,直到能够正确显示实验现象。 6、记录实验中遇到的问题及解决方案

硬件实验二 定时计数器的使用

一、实验目的

1. 学习定时计数器的编程使用 2. 学习8位数码管的编程使用

3. 再次熟悉单片机仿真实验箱XL600+使用方法 二、实验内容

编程使用单片机的定时计数器定时1s钟,并通过8位数码管显示当前秒表的时间,分辨率为0.01s,控键K01第一次按下时, 启动开始计时,第二次按下时, 停止计时,第三次按下时, 归零。 三、实验连线

p0口-----数码管数据线(JP5) p2口-----数码管显示位控制(JP8) p3.2口---控制按键K01(JP37.0)

实验参考程序见编程实例F:\\单片机\\编程实例\\电子钟.计数器\\数码管8位秒表计时

;* --- 秒单位 ---------- 数码管端口 ---- 缓冲区 --------- 计时BCD码值寄存器 *

;* 十万位 P20 dis_buf[7] sec_bcd[7] *

;* 万位 P21 dis_buf[6] sec_bcd[6] *

;* 千位 P22 dis_buf[5] sec_bcd[5] *

;* 百位 P23 dis_buf[4] sec_bcd[4] *

;* 十位 P24 dis_buf[3] sec_bcd[3] *

;* 个位(1.s) P25 dis_buf[2] sec_bcd[2] *

;* 十分位(0.1s) P26 dis_buf[1] sec_bcd[1] *

;* 百分位(0.01s) P27 dis_buf[0] sec_bcd[0] *CODE_SEG SEGMENT CODE DATA_SEG SEGMENT DATA STACK_SEG SEGMENT IDATA RSEG DATA_SEG KEY_S: DS 1 KEY_V: DS 1 DIS_DIGIT: DS 1 DIS_INDEX: DS 1 SEC_BCD: DS 8 ; 秒计数值, BCD码 KEY_TIMES: DS 1 ; K1 按下次数 DIS_BUF: DS 8 ; 显示缓冲区 RSEG STACK_SEG

STACK: DS 20 K1 BIT P3.2

;=============================================================================== CSEG AT 0000H LJMP MAIN CSEG AT 0000BH LJMP TIMER0 CSEG AT 0001BH LJMP TIMER1

;=============================================================================== RSEG CODE_SEG MAIN: USING 0 MOV SP,#(STACK-1) MOV P0,#0FFH ; 初始化端口 MOV P2,#0FFH MOV TMOD,#011H ; MOV TH1,#0DCH CLR A MOV TL1,A MOV TH0,#0FCH MOV TL0,#017H LCALL CLR_TIME ; 清零计时值 MOV DIS_DIGIT,#07FH ; 上电时选通P27数码管 CLR A MOV DIS_INDEX,A MOV KEY_TIMES,A MOV KEY_V,#01H MOV IE,#08AH ; 使能timer0, timer1中断 SETB TR0 CLR TR1 MAIN_LP: LCALL SCAN_KEY ; 键扫描 JZ MAIN_LP ; 无键返回 MOV R7,#10 ; 延时10ms LCALL DELAYMS ; 延时去抖动 LCALL SCAN_KEY ; 再次扫描 JZ MAIN_LP ; 无键返回 MOV KEY_V,KEY_S ; 保存键值 LCALL PROC_KEY ; 键处理 SJMP MAIN_LP ; 调回主循环

;=============================================================================== CLR_TIME: CLR A MOV SEC_BCD,A ; 清零所有计时值 MOV SEC_BCD+01H,A MOV SEC_BCD+02H,A MOV SEC_BCD+03H,A MOV SEC_BCD+04H,A MOV SEC_BCD+05H,A MOV SEC_BCD+06H,A MOV SEC_BCD+07H,A LJMP UPDATE_DISBUF ; 更新显示缓冲区

;=============================================================================== SCAN_KEY: CLR A MOV KEY_S,A MOV C,K1 ; 读按键状态 RLC A ORL KEY_S,A MOV A,KEY_S XRL A,KEY_V ; RET

;=============================================================================== PROC_KEY: MOV A,KEY_V JB ACC.0,END_PROC_KEY INC KEY_TIMES MOV A,KEY_TIMES CJNE A,#01H,PROC_KEY1 SETB TR1 ; KEY_TIMES = 1,第一次按下K1, 启动开始计时 RET PROC_KEY1: MOV A,KEY_TIMES CJNE A,#02H,PROC_KEY2 CLR TR1 ; KEY_TIMES = 2, 第二次按下K1, 停止计时 RET PROC_KEY2: LCALL CLR_TIME ; 第三次按下K1, 清零计时值 CLR A MOV KEY_TIMES,A ; 清零KEY_TIMES END_PROC_KEY:

RET

;=============================================================================== TIMER0:

; 定时器0中断服程序, 用于数码管的动态扫描

; DIS_INDEX --- 显示索引, 用于标识当前显示的数码管和缓冲区的偏移量

; DIS_DIGIT --- 位选通值, 传送到P2口用于选通当前数码管的数值, 如等于0xfe时, ; 选通P2.0口数码管

; DIS_BUF --- 显于缓冲区基地址 PUSH ACC PUSH PSW PUSH AR0 MOV TH0,#0FCH MOV TL0,#017H MOV P2,#0FFH ; 先关闭所有数码管 MOV A,#DIS_BUF ; 获得显示缓冲区基地址 ADD A,DIS_INDEX ; 获得偏移量 MOV R0,A ; R0 = 基地址 + 偏移量 MOV A,@R0 ; 获得显示代码 MOV P0,A ; 显示代码传送到P0口 MOV P2,DIS_DIGIT ; MOV A,DIS_DIGIT ; 位选通值右移(P20<-P27), 下次中断时选通下一位数码管 RR A MOV DIS_DIGIT,A INC DIS_INDEX ; DIS_INDEX加1, 下次中断时显示下一位 ANL DIS_INDEX,#0x07 ; 当DIS_INDEX等于8(0000 1000)时, 清0 POP AR0 POP PSW POP ACC RETI

;=============================================================================== TIMER1: PUSH ACC PUSH B PUSH DPH PUSH DPL PUSH PSW PUSH AR7 ORL TH1,#0DCH ; 恢复定时器初值 CLR A MOV R7,A

MOV A,#LOW (SEC_BCD) MOV R0,A ; 计时值寄存器地址到R0 TIMER_INC: ; INC @R0 ; 计时值加1 MOV A,@R0 CLR C SUBB A,#10 ; JC END_INC ; 如果低位不满10, 则结束 MOV @R0,#00H ; 低位满10, 清零低位 INC R0 ; 指向高位 INC R7 ; CJNE R7,#08H,TIMER_INC ; 如果达到最高位, 则结束 END_INC: LCALL UPDATE_DISBUF POP AR7 POP PSW POP DPL POP DPH POP B POP ACC RETI

;=============================================================================== UPDATE_DISBUF:

; 根据计时寄存器的值更新显示缓冲区 MOV DPTR,#DIS_CODE ; 保存表格地址 MOV A,sec_bcd MOV DPTR,#dis_code MOVC A,@A+DPTR ; 获得显示代码 MOV dis_buf,A ; 更新显示缓冲区 MOV A,sec_bcd+01H MOVC A,@A+DPTR MOV dis_buf+01H,A MOV A,sec_bcd+02H MOVC A,@A+DPTR ANL A,#07FH ; 显示小数点 MOV dis_buf+02H,A MOV A,sec_bcd+03H MOVC A,@A+DPTR MOV dis_buf+03H,A MOV A,sec_bcd+04H MOVC A,@A+DPTR MOV dis_buf+04H,A MOV A,sec_bcd+05H

MOVC A,@A+DPTR MOV dis_buf+05H,A MOV A,sec_bcd+06H MOVC A,@A+DPTR MOV dis_buf+06H,A MOV A,sec_bcd+07H MOVC A,@A+DPTR MOV dis_buf+07H,A RET

; END OF UPDATE_DISBUF

;=============================================================================== DELAYMS: ; 延时子程序

; 传入参数:R7 --- 延时值(MS) ; 返回值:无 MOV A,R7 JZ END_DLYMS DLY_LP1: MOV R6,#185 DLY_LP2: NOP NOP NOP DJNZ R6,DLY_LP2 DJNZ R7,DLY_LP1 END_DLYMS: RET

;=============================================================================== DIS_CODE:

db 28h,7eh,0a2h,62h,74h,61h,21h,7ah,20h,60h,0ffh END

五、实验步骤

要求:写出实验步骤,并记录实验中遇到的问题和解决方案

硬件实验三 温度传感器液晶显示器的使用

一、实验目的

1. 学习温度传感器18B20的使用 2. 学习液晶显示器的使用 二、实验内容

DS18B20的管脚定义:1、GND 2、DQ 3、VCC 温度显示用四位,当温度>=100度时,第四位才显示。 检测 DS18B20 状态: DS18B20正常显示:DS18B20 OK TEMP: 25.8℃ ← 显示实际温 DS18B20不正常显示:DS18B20 ERROR TEMP: ----℃ ← 显示---- 主要功能:

一、查看温度报警值: K1 → 进入查看温度报警值状态。 LCD 1602 显示: LOOK ALERT CODE TH:028℃ TL:18℃ TH:028 高位报警值 *

TL:18 低位报警值 K3 → 退出查看温度报警值状态。 二、设定温度报警值: K2 → 进入设定温度报警值状态? LCD 1602 显示:RESET ALERT CODE TH:028℃ TL:18℃ K1 : 设定值加(UP)、减(DOWN)方式选择键(默认为减少) K2 : TH值设定键 K3 : TL值设定键

K4 : 确定键 (退出设定状态)

K2 或 K3 以减(DOWN)方式设定,当设定数值减到“0”时自动转换为加(UP)方 K2 或 K3 以加(UP)方式设定,当设定数值 TH=120、TL=99 时,设定数值均变为“0”

K4 → 确定并退出设定温度报警值状态。 将设定的温度报警值自动存入 DS18B20 的 EEROM 中,可永久保存。 每次开机时自动从 DS18B20 的 EEROM 读出温度报警值。 ;三、报警状态的显示: 1、当实际温度大于 TH 的设定值时, LCD1602 显示: DS18B20 OK TEMP: 88.8℃ > H 关闭继电器,蜂鸣器响,表示超温

2、当实际温度小于 TL 的设定值时,LCD1602 显示: DS18B20 OK TEMP: 18.8℃ < L蜂鸣器响,表示加热部分出现故障。 3、当实际温度小于 TH 的设定值时,继电器吸合,开始加热。 加热标记为“!” 三、实验连线

p1.0----- 继电器(JP18) p3.7------ 喇叭(JP16) p3.3 -----18b20

p1.4-p1.7------按键k1-k4 1602液晶

实验参考程序见编程实例F:\\单片机\\编程实例\\温度试验\\18b20液晶温度控制

TEMP_ZH DATA 24H ;实时温度值存放单元 TEMPL DATA 25H ; TEMPH DATA 26H ;

TEMP_TH DATA 27H ;高温报警值存放单元 TEMP_TL DATA 28H ;低温报警值存放单元 TEMPHC DATA 29H ; TEMPLC DATA 2AH

K1 EQU P1.4 K2 EQU P1.5 K3 EQU P1.6 K4 EQU P1.7

BEEP EQU P3.7 RELAY EQU P1.0

LCD_X EQU 2FH ;LCD 地址变量 LCD_RS EQU P2.0 LCD_RW EQU P2.1 LCD_EN EQU P2.2

flag1 equ 20H.0 ;DS18B20是否存在标记

KEY_UD EQU 20H.1 ;设定 KEY 的UP与DOWN 标记 date_line equ p3.3

;===================================================== ORG 0000H JMP MAIN

MAIN: MOV SP,#60H MOV A,#00H

MOV R0,#20H ;将 20H-2FH 单元清零 MOV R1,#10H CLEAR: MOV @R0,A INC R0

DJNZ R1,CLEAR

CALL SET_LCD CALL RE_18B20

start: CALL RESET ;18B20复位子程序 JNB FLAG1,START1 ;DS1820不存在 CALL MENU_OK CALL READ_E2

CALL TEMP_BJ ;显示温度标记

JMP START2

START1: CALL MENU_ERROR

CALL TEMP_BJ ;显示温度标记 JMP $

START2:

CALL RESET

JNB FLAG1,START1 ;DS1820不存在 MOV A,#0CCH ; 跳过ROM匹配 CALL WRITE

MOV A,#44H ; 发出温度转换命令 CALL WRITE CALL RESET

MOV A,#0CCH ; 跳过ROM匹配 CALL WRITE

MOV A,#0BEH ; 发出读温度命令 CALL WRITE CALL READ call CONVTEMP Call DISPBCD CALL CONV

CALL TEMP_COMP

CALL PROC_KEY ; 键扫描 SJMP START2

;----------------------------------------------------- PROC_KEY: JB K1,PROC_K1 ; 按键K1处理 CALL BEEP_BL JNB K1,$

MOV DPTR,#M_ALAX1 MOV A,#1

CALL LCD_PRINT CALL LOOK_ALARM JB K3,$

CALL BEEP_BL JMP PROC_K2 PROC_K1: ; 按键K2处理 JB K2,PROC_END CALL BEEP_BL JNB K2,$

MOV DPTR,#RESET_A1 MOV A,#1

CALL LCD_PRINT

CALL SET_ALARM

CALL RE_18B20 ;将设定的TH,TL值写入DS18B20内 CALL WRITE_E2 PROC_K2:

CALL MENU_OK CALL TEMP_BJ PROC_END: RET

;============================================ ;设定报警值 TH、TL

;============================================ SET_ALARM:

;CALL RESET_ALARM CALL LOOK_ALARM AS0:

JB K1,AS00 CALL BEEP_BL JNB K1,$

CPL 20H.1 ;UP/DOWN 标记 AS00: JB 20H.1,ASZ01 ;20H.1=1,UP

JMP ASJ01 ;20H.1=0,DOWN

ASZ01: JB K2,ASZ02 ;TH值调整(增加) CALL BEEP_BL INC TEMP_TH MOV A,TEMP_TH CJNE A,#120,ASZ011 MOV TEMP_TH,#0 ASZ011: CALL LOOK_ALARM MOV R5,#10 CALL DELAY JMP ASZ01

ASZ02: JB K3,ASZ03 ;TL值调整(增加) CALL BEEP_BL INC TEMP_TL MOV A,TEMP_TL CJNE A,#99,ASZ021 MOV TEMP_TL,#00H

ASZ021: CALL LOOK_ALARM ; MOV R5,#10 CALL DELAY JMP ASZ02

ASZ03: JB K4,AS0 ;确定调整 OK

CALL BEEP_BL JNB K4,$ RET

ASJ01:

JB K2,ASJ02 ;TH值调整 (减少) CALL BEEP_BL DEC TEMP_TH MOV A,TEMP_TH CJNE A,#0FFH,ASJ011 JMP ASJ022

ASJ011: CALL LOOK_ALARM MOV R5,#10 CALL DELAY JMP AS0

ASJ02: JB K3,ASJ03 ;TL值调整(减少) CALL BEEP_BL DEC TEMP_TL MOV A,TEMP_TL CJNE A,#0FFH,ASJ021 JMP ASJ022

ASJ021: CALL LOOK_ALARM ; MOV R5,#10 CALL DELAY JMP AS0 ASJ022: CPL 20H.1 JMP ASZ01 ASJ03: JMP ASZ03 RET

RESET_ALARM:

MOV DPTR,#RESET_A1 ;指针指到显示信息区 MOV A,#1 ;显示在第一行 CALL LCD_PRINT RET RESET_A1:

DB \"RESET ALERT CODE\"

;==================================================== ;实际温度值与标记温度值比较子程序

;==================================================== TEMP_COMP:

MOV A,TEMP_TH

SUBB A,TEMP_ZH ;减数>被减数,则 JC CHULI1 ;借位标志位C=1,转 MOV A,TEMP_ZH

SUBB A,TEMP_TL ;减数>被减数,则 JC CHULI2 ;借位标志位C=1,转 MOV DPTR,#BJ5 CALL TEMP_BJ3

CLR RELAY ;继电器吸合 RET CHULI1:

MOV DPTR,#BJ3 CALL TEMP_BJ3

SETB RELAY ;继电器关闭 CALL BEEP_BL RET CHULI2:

MOV DPTR,#BJ4 CALL TEMP_BJ3 CALL BEEP_BL RET

;----------------------------------------- TEMP_BJ3:

MOV A,#0CEH CALL WCOM MOV R1,#0 MOV R0,#2

BBJJ3: MOV A,R1

MOVC A,@A+DPTR CALL WDATA INC R1

DJNZ R0,BBJJ3 RET BJ3:

DB \">H\" BJ4:

DB \"DB \" !\"

;================================================== ;显示温度标记子程序

;================================================== TEMP_BJ:

MOV A,#0CBH

CALL WCOM

MOV DPTR,#BJ1 ;指针指到显示消息 MOV R1,#0 MOV R0,#2

BBJJ1: MOV A,R1

MOVC A,@A+DPTR CALL WDATA INC R1

DJNZ R0,BBJJ1 RET BJ1:

DB 00H,\"C\"

;================================================= MENU_OK:

MOV DPTR,#M_OK1 ;指针指到显示消息 MOV A,#1 ;显示在第一行 CALL LCD_PRINT

MOV DPTR,#M_OK2 ;指针指到显示消息 MOV A,#2 ;显示在第一行 CALL LCD_PRINT

RET M_OK1:

DB \" DS18B20 OK \M_OK2:

DB \" TEMP: \;----------------------------------------------- MENU_ERROR:

MOV DPTR,#M_ERROR1 ;指针指到显示消息1 MOV A,#1 ;显示在第一行 CALL LCD_PRINT

MOV DPTR,#M_ERROR2 ;指针指到显示消息1 MOV A,#2 ;显示在第一行 CALL LCD_PRINT RET M_ERROR1:

DB \" DS18B20 ERROR \M_ERROR2:

DB \" TEMP: ---- \

;==================================================== reset: setb date_line nop

clr date_line

mov r0,#6bh ;主机发出延时复位低脉冲 mov r1,#04h tsr1: djnz r0,$

mov r0,#6bh djnz r1,tsr1

setb date_line ;然后拉高数据线 nop nop nop

mov r0,#32h

tsr2: jnb date_line,tsr3 ;等待DS18B20回应 djnz r0,tsr2

jmp tsr4 ; 延时

tsr3: setb flag1 ; 置标志位,表示DS1820存在 jmp tsr5

tsr4: clr flag1 ; 清标志位,表示DS1820不存在 jmp tsr7 tsr5: mov r0,#06bh

tsr6: djnz r0,$ ; 时序要求延时一段时间 tsr7: setb date_line ret

;======================================================= RE_18B20:

JB FLAG1,RE_18B20A RET RE_18B20A:

CALL RESET

MOV A,#0CCH ;跳过ROM匹配 LCALL WRITE

MOV A,#4EH ;写暂存寄存器 LCALL WRITE

MOV A,TEMP_TH ;TH(报警上限) LCALL WRITE

MOV A,TEMP_TL ;TL(报警下限) LCALL WRITE

MOV A,#7FH ;12位精确度 LCALL WRITE RET

;------------------------------------------------------------ WRITE_E2:

CALL RESET

MOV A,#0CCH ;跳过ROM匹配 LCALL WRITE

MOV A,#48H ;把暂存器里的温度报警值拷贝到EEROM LCALL WRITE RET

;-------------------------------------------------------------- READ_E2:

CALL RESET

MOV A,#0CCH ;跳过ROM匹配 LCALL WRITE

MOV A,#0B8H ;把EEROM里的温度报警值拷贝回暂存器 CALL WRITE RET

;-------------------------------------------------------------- ;将自定义字符写入LCD1602的CGRAM中 ;-------------------------------------------------------------- STORE_DATA:

MOV A,#40H CALL WCOM MOV R2,#08H

MOV DPTR,#D_DATA MOV R3,#00H S_DATA:

MOV A,R3

MOVC A,@A+DPTR

CALL WDATA ;写入数据 INC R3

DJNZ R2,S_DATA RET

D_DATA:

DB 0CH,12H,12H,0CH,00H,00H,00H,00H

;============================================================== write: mov r2,#8 ;一共8位数据 CLR C wr1:

clr date_line ;开始写入DS18B20总线要处于复位(低)状态 mov r3,#07

djnz r3,$ ;总线复位保持16微妙以上

rrc a ;把一个字节DATA 分成8个BIT环移给C mov date_line,c ;写入一个BIT mov r3,#3CH

djnz r3,$ ;等待100微妙 setb date_line ;重新释放总线 nop

djnz r2,wr1 ;写入下一个BIT

setb date_line ret

;--------------------------------------------------------------------

read: mov r4,#4 ; 将温度低位、高位、TH、TL从DS18B20中读出 mov r1,#TEMPL ; 存入25H、26H、27H、28H re00: mov r2,#8 re01: clr cy

setb date_line nop nop

clr date_line ;读前总线保持为低 nop nop nop

setb date_line ;开始读总线释放 mov r3,#09 ;延时18微妙 djnz r3,$

mov c,date_line ;从DS18B20总线读得一个BIT mov r3,#3CH

djnz r3,$ ;等待100微妙

rrc a ;把读得的位值环移给A djnz r2,re01 ;读下一个BIT mov @r1,a inc r1

djnz r4,re00 ret

;***************************************************** ; 处理温度 BCD 码子程序

;**************************************************** CONVTEMP: MOV A,TEMPH ;判温度是否零下 ANL A,#80H

JZ TEMPC1 ;温度零上转 CLR C

MOV A,TEMPL ;二进制数求补(双字节) CPL A ;取反加1 ADD A,#01H MOV TEMPL,A MOV A,TEMPH CPL A

ADDC A,#00H MOV TEMPH,A SJMP TEMPC11

TEMPC1: MOV TEMPHC,#0AH ;+ TEMPC11: MOV A,TEMPHC SWAP A

MOV TEMPHC,A MOV A,TEMPL

ANL A,#0FH ;乘0.0625 MOV DPTR,#TEMPDOTTAB MOVC A,@A+DPTR

MOV TEMPLC,A ;TEMPLC LOW=小数部分 BCD

MOV A,TEMPL ;整数部分 ANL A,#0F0H ;取出高四位 SWAP A

MOV TEMPL,A

MOV A,TEMPH ;取出低四位 ANL A,#0FH SWAP A

ORL A,TEMPL ;重新组合 MOV TEMP_ZH,A LCALL HEX2BCD1 MOV TEMPL,A ANL A,#0F0H SWAP A

ORL A,TEMPHC ;TEMPHC LOW = 十位数 BCD MOV TEMPHC,A MOV A,TEMPL ANL A,#0FH

SWAP A ;TEMPLC HI = 个位数 BCD ORL A,TEMPLC MOV TEMPLC,A MOV A,R4 JZ TEMPC12 ANL A,#0FH SWAP A MOV R4,A

MOV A,TEMPHC ;TEMPHC HI = 百位数 BCD ANL A,#0FH ORL A,R4

MOV TEMPHC,A TEMPC12: RET

;--------------------------------------------------------------- HEX2BCD1:

MOV B,#0H ;十六进制-> BCD

DIV AB ;B= A % 100 MOV R4,A ;R7 = 百位数 MOV A,#0AH XCH A,B

DIV AB ;B = A % B SWAP A ORL A,B RET

;------------------------------------------------------------- ; 小数部分码表

;------------------------------------------------------------- TEMPDOTTAB:

DB 00H,00H,01H,01H,02H,03H,03H,04H DB 05H,05H,06H,06H,07H,08H,08H,09H

;===================================================== LOOK_ALARM:

MOV DPTR,#M_ALAX2 ;指针指到显示信息区 MOV A,#2 ;显示在第二行 CALL LCD_PRINT

MOV A,#0C6H CALL TEMP_BJ1

MOV A,TEMP_TH ;加载TH数据 MOV LCD_X,#3 ;设置位置 CALL SHOW_DIG2H ;显示数据

MOV A,#0CEH CALL TEMP_BJ1

MOV A,TEMP_TL ;加载TL数据 MOV LCD_X,#12 ;设置位置 CALL SHOW_DIG2L ;显示数据 RET

;-------------------------------------------- M_ALAX1:

DB \" LOOK ALERT CODE\M_ALAX2:

DB \"TH: TL: \;-------------------------------------------- TEMP_BJ1:

CALL WCOM

MOV DPTR,#BJ2 ;指针指到显示信息区 MOV R1,#0 MOV R0,#2

BBJJ2: MOV A,R1

MOVC A,@A+DPTR CALL WDATA INC R1

DJNZ R0,BBJJ2 RET BJ2:

DB 00H,\"C\"

;---------------------------------------------------

SHOW_DIG2H: ;在 LCD 的第二行显示数字 MOV B,#100 DIV AB

ADD A,#30H PUSH B

MOV B,LCD_X CALL LCDP2 POP B

MOV A,#0AH XCH A,B DIV AB

ADD A,#30H INC LCD_X PUSH B

MOV B,LCD_X CALL LCDP2 POP B

INC LCD_X MOV A,B

MOV B,LCD_X ADD A,#30H CALL LCDP2 RET

SHOW_DIG2L: ;在 LCD 的第二行显示数字 MOV B,#100 DIV AB

MOV A,#0AH XCH A,B DIV AB

ADD A,#30H PUSH B

MOV B,LCD_X

CALL LCDP2 POP B

INC LCD_X MOV A,B

MOV B,LCD_X ADD A,#30H CALL LCDP2 RET

;------------------------------------------------------------- ;显示区 BCD 码温度值刷新子程序

;------------------------------------------------------------- DISPBCD:

MOV A,TEMPLC ANL A,#0FH

MOV 70H,A ;小数位 MOV A,TEMPLC SWAP A ANL A,#0FH

MOV 71H,A ;个位 MOV A,TEMPHC ANL A,#0FH

MOV 72H,A ;十位 MOV A,TEMPHC SWAP A ANL A,#0FH

MOV 73H,A ;百位 MOV A,TEMPHC ANL A,#0F0H

CJNE A,#010H,DISPBCD0 SJMP DISPBCD2

DISPBCD0: MOV A,TEMPHC ANL A,#0FH

JNZ DISPBCD2 ;十位数是0 MOV A,TEMPHC SWAP A ANL A,#0FH

MOV 73H,#0AH ;符号位不显示 MOV 72H,A ;十位数显示符号 DISPBCD2: RET

;========================================================== ; LCD 1602 显示子程序

;==========================================================

CONV:

MOV A,73H ;加载百位数据 MOV LCD_X,#6 ;设置位置 CJNE A,#1,CONV1 JMP CONV2 CONV1: MOV A,#\" \" MOV B,LCD_X CALL LCDP2 JMP CONV3

CONV2: CALL SHOW_DIG2 ;显示数据 CONV3: INC LCD_X ; mov a,72h ;十位 CALL SHOW_DIG2 inc LCD_X

mov a,71h ;个位 CALL SHOW_DIG2 inc LCD_X MOV A,#'.'

MOV B,LCD_X CALL LCDP2

MOV A,70h ;加载小数点位 INC LCD_X ;设置位置 CALL SHOW_DIG2 ;显示数据 RET

;-------------------------------------------------------

SHOW_DIG2: ;在 LCD 的第二行显示数字 ADD A,#30H MOV B,LCD_X CALL LCDP2 RET

;---------------------------------------------------------

LCDP2: ;在LCD的第二行显示字符 PUSH ACC ;

MOV A,B ;设置显示地址

ADD A,#0C0H ;设置LCD的第二行地址 CALL WCOM ;写入命令 POP ACC ;由堆栈取出A CALL WDATA ;写入数据 RET

;---------------------------------------------------------

SET_LCD: ;对 LCD 做初始化设置及测试 CLR LCD_EN

CALL INIT_LCD ;初始化 LCD

CALL STORE_DATA ;将自定义字符存入LCD的CGRAM RET

INIT_LCD: ;8位I/O控制 LCD 接口初始化 MOV A,#38H ;双列显示,字形5*7点阵 CALL WCOM call delay1 MOV A,#38H CALL WCOM call delay1

MOV A,#38H CALL WCOM call delay1

MOV A,#0CH ;开显示,显示光标,光标不闪烁 CALL WCOM call delay1

MOV A,#01H ;清除 LCD 显示屏 CALL WCOM call delay1 RET

;================================================== CLR_LINE1: ;清除LCD的第一行字符 MOV A,#80H ;设置 LCD 的第一行地址 CALL WCOM ;

MOV R0,#24 ;设置计数值

C1: MOV A,#' ' ;载入空格符至LCD CALL WDATA ;输出字符至LCD DJNZ R0,C1 ;计数结束 RET

;================================================== LCD_PRINT: ;在LCD的第一行或第二行显示字符

CJNE A,#1,LINE2 ;判断是否为第一行

LINE1: MOV A,#80H ;设置 LCD 的第一行地址 CALL WCOM ;写入命令

CALL CLR_LINE ;清除该行字符数据

MOV A,#80H ;设置 LCD 的第一行地址 CALL WCOM ;写入命令 JMP FILL

LINE2: MOV A,#0C0H ;设置 LCD 的第二行地址 CALL WCOM ;写入命令

CALL CLR_LINE ;清除该行字符数据

MOV A,#0C0H ;设置 LCD 的第二行地址 CALL WCOM

FILL: CLR A ;填入字符

MOVC A,@A+DPTR ;由消息区取出字符 CJNE A,#0,LC1 ;判断是否为结束码 RET

LC1: CALL WDATA ;写入数据 INC DPTR ;指针加1 JMP FILL ;继续填入字符 RET

;========================================= CLR_LINE: ;清除该行 LCD 的字符 MOV R0,#24 CL1: MOV A,#' ' CALL WDATA DJNZ R0,CL1 RET

DE: MOV R7,#250 DJNZ R7,$ RET

;============================================

WCOM: ;以8位控制方式将命令写至LCD MOV P0,A ;写入命令

CLR LCD_RS ;RS=L,RW=L,D0-D7=指令码,E=高脉冲 CLR LCD_RW SETB LCD_EN

ACALL DELAY1 CLR LCD_EN RET

;=============================================

WDATA: ;以8位控制方式将数据写至LCD MOV P0,A ;写入数据 SETB LCD_RS CLR LCD_RW

SETB LCD_EN CALL DE CLR LCD_EN CALL DE RET

;============================================= ;PRINT A CHAR ON LINE 1 ;A=ASC DATA, B=LINE X POS

;============================================== LCDP1: ;在LCD的第一行显示字符

PUSH ACC ;

MOV A,B ;设置显示地址

ADD A,#80H ;设置LCD的第一行地址 CALL WCOM ;写入命令 POP ACC ;由堆栈取出A CALL WDATA ;写入数据 RET

;============================================== BEEP_BL:

MOV R6,#100 BL2: CALL DEX1 CPL BEEP DJNZ R6,BL2 MOV R5,#10 CALL DELAY RET

DEX1: MOV R7,#180 DE2: NOP

DJNZ R7,DE2 RET

DELAY: ;(R5)*延时10MS MOV R6,#50 DL1: MOV R7,#100 DJNZ R7,$ DJNZ R6,DL1 DJNZ R5,DELAY RET

DELAY1: ;延时5MS MOV R6,#25 DL2: MOV R7,#100 DJNZ R7,$ DJNZ R6,DL2 RET

;================================================ END

四、实验步骤

要求:记录实验步骤,并详细分析程序,学习温度传感器和液晶显示器的单片机控制。

因篇幅问题不能全部显示,请点此查看更多更全内容