资源描述
单片机实验报告
孙洪悦 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
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 ;31高低四位分别存十和百位
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 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写表格数据
LOOP2: MOV R1,#30H ;将起始地址给R1
MOV A,R0 ;R0为执行31次
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指向的数交换位置, 即 ;前一个数和后一个数交
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
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写表格数据
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位溢出,溢出则说明前一个数小,要换位
JC LOOP4 ;前一个数小的情况下,两个数交换位置 ,否则,继续执行
;MOV A,R3 ; 把后一个数存到累加器下
;XCH A,@R1 ;累加器的数与R1指向的数交换位置, 即 ;前一个数和后一个数交
;DEC R1 ;R1自减,准备将后面的数存到前面
;MOV @R1,A ;将后面的数存到前面
;INC R1 ;R1自增,准备下次转换,以上五行为交换
DJNZ R2,LOOP3 ;R2自减,为下次冒泡准备
LOOP4:
MOV 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相邻的两个数比较,记下最大的数的位置,直到一轮遍历后将找到的最大的数与最后一个数交换,实现排序
2.3 C语言程序实验
自我完成实验
(1)实验内容
将片内 RAM 30H 开始的 32 个单元中分布着随机的有符号 8 位二进制数,请按从小到大
的顺序进行排序,排序后的数据仍然保存到 30H 开始的 32 个单元中(低地址存放小数据)。
#include<reg51.h>
#include<stdio.h>
#include<stdlib.h>
#define uchar unsigned char
#define uint unsigned int
//uchar 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;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<j)
{
if(a[t]>=a[t+1])
{
temp = a[t+1];
a[t+1] = a[t];
a[t] = temp;
}
t++;
}
t = 0;
}
}
*/
//第二种方法实现冒泡
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]<c[m])
{
weizhi = m;
}
}
temp = c[weizhi];
c[weizhi] = c[maxloc];
c[maxloc] = temp;
maxloc--;
}
}
void main()
{
fuzhi();
maopao(a,31);
while(1);
}
总结与提高:C语言编写的代码也是用两种方法写的,其中一种已经被注释掉了。所谓冒泡法,有两种理解方式:1.相邻的两个数比较,大的数放后一个位置,直到一轮循环后,最后一个数为此轮遍历的最大的数。2相邻的两个数比较,记下最大的数的位置,直到一轮遍历后将找到的最大的数与最后一个数交换,实现排序
3.1基本并行I/O口实验
实验功能为:
当按键 SW1 按下之后,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:MOV R5,#250
DJNZ R5,$
DJNZ R6,L1
RET
SJMP $
END
总结与提高:1.按键去抖动是必要的 2用移位操作可以很方便的实现一些功能3多使用调试工具,程序不是写出来的,而是调出来的。
3.2扩展并行I/O口实验
实验功能为:
仿真实现交通信号灯控制功能。
控制顺序为:
① 南北绿灯亮,同时东西红灯亮 10s;
② 南北黄灯亮,同时东西红灯亮 2s;
③ 南北红灯亮,同时东西绿灯亮 10s;
④ 东西黄灯亮,同时南北红灯亮 2s;
⑤ 重复①~④。
ORG 0000H
AJMP START
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 DPTR,#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,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显示实验
控制要求
图 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
ORG 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: ;定时器中断等待
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 @DPTR,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,0A4H,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 ;熄灭LED
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
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
用于设定旋转方向为顺时针旋转或者逆时针旋转,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 ;定时器初始化
;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 0200H
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 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 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
RETI
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
展开阅读全文