1、 单片机实验报告 孙洪悦 2011 2.1实验1:汇编程序实验1 2.1.2 自我完成实验 (1)实验内容 将片内 RAM 30H 单元中的 8 位二进制数转换成 10 进制数。希望转换后的结果保存于 31H 和 32H,31H 低 4 位存放个位,高 4 位存放十位,32H 低 4 位存放百位,高 4 位为 0 自我完成实验程序 ORG 0000H AJMP MAIN ORG 0030H MAIN: MOV SP,#62H ; MOV 30H,#0AFH ;先将30H写上100 MOV R0,#32H ;将百位地址送R0
2、MOV A,30H ;这句写错了,应该是将30H的内容送给A,而不是30H,我误写成了#30H MOV B,#64H ;除数为100 DIV AB ;AB相除 MOV @R0,A ;将百位的数送给32H地址 MOV A,B ;将余数送给A MOV B,#0AH ;将10送B DIV AB ;AB相除 SWAP A ;高低四位交换 DEC R0 ;R0减1 到31H MOV @R0,A ;将十位送31H的高四位 MOV A,B ANL A,#0FH ORL 31H,A ;3
3、1高低四位分别存十和百位 SJMP $ END 2.1总结与提高:本程序用了一个小算法,一个三位数数X除以100,商a为百位,余数为:X-100*a 再用此余数除10,商为十位,余数为个位。 2.2实验2:汇编程序实验2 2.2.2 自我完成实验 (1)实验内容 将片内 RAM 30H 开始的 32 个单元中分布着随机的有符号 8 位二进制数,请按从小到大 的顺序进行排序,排序后的数据仍然保存到 30H 开始的 32 个单元中(低地址存放小数据)。 程序及其注释 ② 自我完成实验程序 第一种排序方法: ORG 0000H AJMP M
4、AIN ORG 0090H MAIN: MOV SP,#62H ; MOV A,#0H MOV R1,#30H MOV R7,#20H MOV DPTR,#TABLE MOV R0,#1FH ;执行31次 LOOP1: MOVC A,@A+DPTR MOV @R1,A INC R1 INC DPTR MOV A,#0H DJNZ R7,LOOP1 ;执行32次循环,在30-4F写表格数据 LOOP2: MOV R1,#30H ;将起始地址给R1 MOV A,R0 ;R0为执行31次
5、MOV R2,A ; 把进行一次冒泡的次数存到R2中 LOOP3: CLR C ;清C MOV A,@R1 ; ;比较开始,取第一个数 MOV R3,A ; 腾出累加器 INC R1 ;指向下一个地址 SUBB A,@R1 ;取后一个数 ,并与前一个数相减,看是否有CY位溢出,溢出则说明前一个数小,要换位 JC LOOP4 ;前一个数小的情况下,两个数交换位置 ,否则,继续执行 MOV A,R3 ; 把后一个数存到累加器下 XCH A,@R1 ;累加器的数与R1指
6、向的数交换位置, 即 ;前一个数和后一个数交 DEC R1 ;R1自减,准备将后面的数存到前面 MOV @R1,A ;将后面的数存到前面 INC R1 ;R1自增,准备下次转换,以上五行为交换 LOOP4: DJNZ R2,LOOP3 ;R2自减,为下次冒泡准备 DJNZ R0,LOOP2 ;跳回去进行下一轮冒泡 SJMP $ ORG 30H TABLE: DB 1,3,9,2,17,4,11,6 DB 5,20,100,64,21,14,79,35 DB 92,7,91,23,65,16,13,18
7、DB 18,73,65,101,27,19,62,69 END 第二种排序方法; ORG 0000H AJMP MAIN ORG 0090H MAIN: MOV SP,#62H ; MOV A,#0H MOV R1,#30H MOV R7,#20H MOV DPTR,#TABLE MOV R0,#1FH ;执行31次 LOOP1: MOVC A,@A+DPTR MOV @R1,A INC R1 INC DPTR MOV A,#0H DJNZ R7,LOOP1 ;执行32次循环,在30-4F写表格数据
8、 LOOP2: MOV R1,#30H ;将起始地址给R1 MOV A,R0 ;R0为执行31次 MOV R2,A ; 把进行一次冒泡的次数存到R2中 MOV R4,#30H ;R4存的是最大数的位置 LOOP3: CLR C ;清C MOV A,@R1 ; ;比较开始,取第一个数 MOV R3,A ; 腾出累加器 INC R1 ;指向下一个地址 MOV A,@R4 SUBB A,@R1 ;取后一个数 ,并与前一个数相减,看是否有CY位溢出,溢出
9、则说明前一个数小,要换位 JC LOOP4 ;前一个数小的情况下,两个数交换位置 ,否则,继续执行 ;MOV A,R3 ; 把后一个数存到累加器下 ;XCH A,@R1 ;累加器的数与R1指向的数交换位置, 即 ;前一个数和后一个数交 ;DEC R1 ;R1自减,准备将后面的数存到前面 ;MOV @R1,A ;将后面的数存到前面 ;INC R1 ;R1自增,准备下次转换,以上五行为交换 DJNZ R2,LOOP3 ;R2自减,为下次冒泡准备 LOOP4: MOV
10、A,R1 ; MOV R4,A DJNZ R2,LOOP3 DJNZ R0,LOOP2 ;跳回去进行下一轮冒泡 SJMP $ ORG 30H TABLE: DB 1,3,9,2,17,4,11,6 DB 5,20,100,64,21,14,79,35 DB 92,7,91,23,65,16,13,18 DB 18,73,65,101,27,19,62,69 END 总结与提高:所谓冒泡法,有两种理解方式:1.相邻的两个数比较,大的数放后一个位置,直到一轮循环后,最后一个数为此轮遍历的最大的数。2相邻的
11、两个数比较,记下最大的数的位置,直到一轮遍历后将找到的最大的数与最后一个数交换,实现排序
2.3 C语言程序实验
自我完成实验
(1)实验内容
将片内 RAM 30H 开始的 32 个单元中分布着随机的有符号 8 位二进制数,请按从小到大
的顺序进行排序,排序后的数据仍然保存到 30H 开始的 32 个单元中(低地址存放小数据)。
#include
12、r data a[32] _at_ 0x30; //设定数组a的起始地址为30 uchar data a[32] _at_ 0x30; //设定数组a的起始地址为30 uint i _at_ 0x55; uchar data b[32] = {1,3,9,2,17,4,11,6, 5,20,100,64,21,14,79,35, 92,7,91,23,65,16,13,18 ,18,73,65,101,27,19,62,69}; void fuzhi() { uchar j; //srand(5); for(j=0;j<=31
13、j++)
{
//a[j] = rand();
a[j] = b[j];
}
}
/*
void maopao(uchar a[],uchar num)
{
uchar j = 0,temp = 0,t = 0;
for(j=(num-1);j>0;j--)
{
while(t
14、
}
*/
//第二种方法实现冒泡
void maopao(uchar c[],uchar num)
{
uchar j = 0,temp = 0,m = 0;
uchar weizhi = 0;
uchar maxloc = 31;
for(j=num;j>0;j--)
{
weizhi = 0;
for(m=1;m<=j;m++)
{
if(c[weizhi] 15、loc];
c[maxloc] = temp;
maxloc--;
}
}
void main()
{
fuzhi();
maopao(a,31);
while(1);
}
总结与提高:C语言编写的代码也是用两种方法写的,其中一种已经被注释掉了。所谓冒泡法,有两种理解方式:1.相邻的两个数比较,大的数放后一个位置,直到一轮循环后,最后一个数为此轮遍历的最大的数。2相邻的两个数比较,记下最大的数的位置,直到一轮遍历后将找到的最大的数与最后一个数交换,实现排序
3.1基本并行I/O口实验
实验功能为:
当按键 SW1 按下 16、之后,D1-D8 轮流点亮,点亮时间为 100ms,当按键停下后,停止轮换,
再次按下后继续轮换。
ORG 0000H
AJMP MAIN
ORG 0030H
MAIN:
MOV SP,#60H
MOV P2,#0FFH
MOV 20H,#0FEH
MOV R7,#8
LOOP:
SETB P1.0
JNB P1.0,LOOP1
AJMP L
LOOP1:
MOV A,20H
MOV P2,A
ACALL DELAY
MOV A,P2
RL A
MOV 20H,A
L:DJNZ R7,LOOP
DELAY:
MOV R6,#200
L1:MO 17、V R5,#250
DJNZ R5,$
DJNZ R6,L1
RET
SJMP $
END
总结与提高:1.按键去抖动是必要的 2用移位操作可以很方便的实现一些功能3多使用调试工具,程序不是写出来的,而是调出来的。
3.2扩展并行I/O口实验
实验功能为:
仿真实现交通信号灯控制功能。
控制顺序为:
① 南北绿灯亮,同时东西红灯亮 10s;
② 南北黄灯亮,同时东西红灯亮 2s;
③ 南北红灯亮,同时东西绿灯亮 10s;
④ 东西黄灯亮,同时南北红灯亮 2s;
⑤ 重复①~④。
ORG 0000H
AJMP STAR 18、T
ORG 0003H
START:
MOV SP,#60H
MOV P0,#0FFH
CLR P3.6
STATE1:
MOV DPTR,#0FE00H
MOV A,#0F3H
MOVX @DPTR,A
MOV DPTR,#0FD00H
MOV A,#0CH
MOVX @DPTR,A
ACALL DELAY2
STATE2:
MOV DPTR,#0FE00H
MOV A,#0C3H
MOVX @DPTR,A
MOV DPTR,#0FD00H
MOV A,#0FH
MOVX @DPTR,A
ACALL DELAY1
STATE3:
MOV DPT 19、R,#0FE00H
MOV A,#0FCH
MOVX @DPTR,A
MOV DPTR,#0FD00H
MOV A,#03H
MOVX @DPTR,A
ACALL DELAY2
STATE4:
MOV DPTR,#0FE00H
MOV A,#3CH
MOVX @DPTR,A
MOV DPTR,#0FD00H
MOV A,#0FH
MOVX @DPTR,A
ACALL DELAY1
AJMP STATE1
DELAY1:
MOV R7,#20
DL2:
MOV R6,#200
DL1:
MOV R5,#250
DJNZ R5,$
DJNZ R6 20、DL1
DJNZ R7,DL2
RET
DELAY2:
MOV R7,#100
L2:
MOV R6,#200
L1:
MOV R5,#250
DJNZ R5,$
DJNZ R6,L1
DJNZ R7,L2
RET
END
总结与提高:1.用汇编写程序比C难的一个地方我觉得就是控制逻辑不是那么直观,所以一定要注意程序的格式规范,尽量使用缩进,标号命名尽量通俗易懂2用移位操作可以很方便的实现一些功能3多使用调试工具,程序不是写出来的,而是调出来的4多积累一些常用代码,比如延时程序,只需简单改些参数就可以再次使用
3.3静态LED显示实验
控制要求
21、图 3.9 中 7SEG2 为十位显示数码管,7SEG1 为个位显示数码管,KEY_LOAD 为倒计时初
值按钮,KEY_START 为倒计时启动按钮。要求实现的功能是:当 KEY_LOAD 按钮按下时加载
倒计时初值(如:10s),当按下 KEY_START 按钮时,开始倒计时,每过 1s,计时器减 1,
直到减到“00”为止。减到“00”时使 P3.0 引脚上的 LED 按 10Hz 频率进行闪烁,直到再次
按下 KEY_LOAD 按钮才重新加载初值,并熄灭 LED。再次按下 KEY_START 按钮又一次开始倒
计时,如此反复。
ORG 0000H
AJMP MAIN
O 22、RG 000BH
AJMP T0INT
ORG 001BH
AJMP T1INT
ORG 0100H
MAIN:
SETB P1.0
SETB P1.1
CLR P1.2
CLR P1.3
CLR P1.4
MOV R4,#0
MOV TMOD,#21H
MOV TH1,#56 ;直接赋值就可
MOV TL1,#56
MOV TH0,#0B1H
MOV TL0,#0E0H
SETB ET1
SETB ET0
SETB EA
SETB TR1
SETB TR0
WAIT1: ;定时器中断等待
23、
JB P1.2,S4
JB P1.3,S5
SJMP WAIT1
S4:
CLR P1.2 ;清标志位
MOV R3,#9
MOV DPTR,#0FD00H ;十位显示0,个位循环
MOV A,#0C0H
MOVX @DPTR,A
LOOP: ;09-00循环
JB P1.2,S4 ;判断显示过程中有无按键被按下
JB P1.3,S5
MOV A,R3
MOV DPTR,#TABLE
MOVC A,@A+DPTR
MOV DPTR,#0FE00H
MOVX @DPT 24、R,A
LCALL DELAY2 ;此处容易出错误
DEC R3
MOV A,R3
INC A ;
JNZ LOOP
SETB P1.4 ;到00后才闪灯
SJMP WAIT1
S5: ;装载初值
CLR P1.3 ;清标志位
MOV DPTR,#0FD00H
MOV A,#0F9H
MOVX @DPTR,A
MOV DPTR,#0FE00H
MOV A,#0C0H
MOVX @DPTR,A
SJMP WAIT1
TABLE:
DB 0C0H,0F9H,0A4 25、H,0B0H,99H
DB 92H,82H,0F8H,80H,90H
T0INT:
MOV TH0,#0B1H ;T0工作在方式1 ,要装载初值
MOV TL0,#0E0H ;T0工作在方式1 ,20ms 检测按键
JNB P1.1, S2 ;检测装载初值键
JNB P1.0, S3 ;检测开始键
RETI
S2:
CLR P1.4 ;检测装载初值键
SETB P3.0 ;熄灭LED
SETB P1.3 ;装载显示初值
RETI
S3:
CLR P1.4 ;检测开始键
SETB P3.0 ;熄灭LE 26、D
SETB P1.2
RETI
T1INT: ;T1 工作在方式2 8位重装
JB P1.4,S6
RETI
S6:
INC R4
MOV A,#50 ;LED 闪烁
CLR C
SUBB A,R4
JZ S1
RETI
S1: ;控制LED
MOV R4,#0
CPL P3.0;
RETI ;必须要写中断返回
DELAY2: ;1s 换一次
MOV R7,#10
L2:
MOV R6,#200
L1:
MOV R5,#250
DJNZ R5,$
DJNZ R6,L1
27、 DJNZ R7,L2
RET
END
总结与提高:1.此程序我用了T1的8位重装的定时方式 2我用T0定时器每隔20ms,来检测有无按键按下,但是也得加入按键去抖动的程序
3.4矩阵键盘扫描实验
控制要求
图 3.11 中 D1~D8 八个发光二极管构成彩色旋转灯,D9~D13 为档位指示灯,一档旋转
速度最慢(周期 1s,D13 亮),二档较快(周期 0.8s,D12 亮),三档更快(周期 0.6s,
D11 亮),四档再快(周期 0.4s,D10 亮),五档最快(周期 0.2s,D10 亮)。四个按键 KEY0-KEY1
用于设定旋转方向为顺时针旋转 28、或者逆时针旋转,KEY2-KEY3 用于增快或则减慢旋转速度。
ORG 0000H
AJMP MAIN
ORG 0003H
AJMP PINT0
ORG 000BH
AJMP T0INT
ORG 0013H
AJMP PINT1
ORG 0100H
MAIN:
CLR P0.6
CLR P0.7
MOV SP,#40H
MOV R4,#1 ;默认为1档;the fastest 0.2s
MOV R3,#0 ;控制旋转间隔时间
MOV P1,#07FH
MOV TMOD,#21H ;定时器初始化
29、
;MOV TH1,#56 ;直接赋值就可
;MOV TL1,#56
MOV TH0,#0B1H
MOV TL0,#0E0H
;SETB ET1
SETB ET0
SETB EA
;SETB TR1
;SETB PT0 ;响应外部中断0 就把定时器给关了,所以还是两级嵌套
;SETB PX0 ;?
;SETB PX1 ;必须设计成高优先级
SETB EX0
SETB EX1
SETB IT0 ;边沿触发
SETB IT1
WAIT1:
SJMP WAIT1
S2:
ORG 020 30、0H
PINT0: ;控制旋转与停止旋转
CPL P2.0
LCALL Delay10ms ;按键去抖动
CPL TR0 ;关闭打开定时器,实现开始和暂停
RETI
PINT1: ;控制循环变速
CPL P2.1
LCALL Delay10ms ;按键去抖动
INC R4
CLR C
MOV A,#6
SUBB A,R4
JZ S8
RETI
S8:
MOV R4,#1
RETI
Delay10ms: ;10ms 改参数R6
MOV R6,#20
L:
MOV R5,#250
DJNZ 31、 R5,$
DJNZ R6,L
RET
T0INT:
MOV TH0,#0B1H ;T0工作在方式1 ,要装载初值
MOV TL0,#0E0H ;T0工作在方式1 ,20ms 检测按键
S0:
CJNE R4,#1,S3 ;1 档
MOV P0,#0FFH
CPL P0.0
INC R3
MOV A,#10 ;LED 200ms
CLR C
SUBB A,R3
JZ S01
RETI
S3: ;2档
CJNE R4,#2,S5
MOV P0,#0FFH
CPL P0.1
INC R3
MOV 32、 A,#20 ;LED 400ms
CLR C
SUBB A,R3
JZ S01
RETI
S5: ;3档
CJNE R4,#3,S6
MOV P0,#0FFH
CPL P0.2
INC R3
MOV A,#30 ;LED 600ms
CLR C
SUBB A,R3
JZ S01
RETI
S6: ;4档
CJNE R4,#4,S7
MOV P0,#0FFH
CPL P0.3
INC R3
MOV A,#40 ;LED 800ms
CLR C
SUBB A,R3
JZ S01
RET 33、I
S7: ;5档
CJNE R4,#5,S0 ;返回1档
MOV P0,#0FFH
CPL P0.4
INC R3
MOV A,#50 ;LED 1000ms
CLR C
SUBB A,R3
JZ S01
RETI
S01: ;循环灯的实现
MOV A,P1
RL A
MOV P1,A
MOV R3,#0
RETI
END
总结与提高:1.此程序我用了T0,工作在方式1,我通过赋给TH0,TL0不同的初值,达到变速的母的2用移位实现彩灯的循环比较方便3写程序一定要一个整体的概念,有一个整体的把握,当写代码的时候肯定是一部分一部分的写,每写好一部分,就要调试好一部分,这样写到最后了,整个程序也就调通了
18






