近期的几个单片机例程及详细分析
最近,我们在课上讲了几个小例子,在此再把Proteus图及程序的详细解释列出来,供大家参考。
1. 应用查询方式,对连接在 P1.4 管脚上的按键次数进行计数,每 5 次在 P
1.0 上连接的红色 LED 亮或不亮。
本题考虑点:
A、 应用查询方式,即读和检测P1.4 管脚的状态,是 1 或 0;
B、 每 5 次翻转一次,因此可设一个寄存器作为计数器,看是否到了 5 次,5 次后清零;
C、 P1.0 上的LED亮或不亮,即状态翻转,CPL P1.0。
Proteus图
应用元器件:单片机 80C51(或 80C52)、按键Button、电阻Res、LED
单片机属于微处理器库里面的,因此,应再点击Microprocessor ICS,后同。
图 1 找元器件的方法
1
图 2.
1 题图
程序:
ORG 0H
MAIN: MOV R0,#0
LOOP:
JB P1.4,$
JNB P1.4,$
INC R0
CJNE R0,#6,LOOP
MOV R0,#0
CPL P1.0
AJMP LOOP
END
;程序从程序存储器的 0 单元开始存放
;设 R0 为计数器,赋初始值 0,注意,在这儿不赋值 0,单片机一上电 R0 也等于 0
;若 P1.4 为高,表明没键按下,等待
;若 P1.4 为低,表明有键按下,等待该键的弹起
;按键弹起后,表明按键一次,计数器加 1
;若 R0 不等于 6,表明还没按够 5 次,继续查询按键信息
;若 R0=6,表明已经被按下 5 次,计数器清零
;P1.0 翻转,即 LED 的状态转换
;进入下一个循环
;程序结束
图 3 调试状态
2. 应用定时器,控制从 P1.0 和 P1.1 输出周期为 300us 和 600us 的方波程序。
本题考虑点:
首先明确为应用定时器,且输出波形为方波,周期 300us和 600us,也就是说,如果用这两个管脚输出
波形的话,其翻转的时间分别为 150us和 300us。
然后确定应用定时器的工作方式,对于 6MHz的晶振来说,对于 12 分频的单片机的机器周期为 2us,
即对机器周期的计数分别为 75 和 150,都小于 256,因此,可用 8 位定时器,并且 300us是 150us的整数倍,
因此可用一个定时器解决。在此选用自动装入的 8 位定时器,即工作方式 2,设用T0。
则TMOD的取值为:
先看TMOD的各位: GATE
因为用T0 来计时,且在本题目中T1 不用,因此,TMOD的取值可为:00000010B , 16 进制:02H
初始值的计算,应用公式:
GATE C\T M1 M0
C\T M1 M0
(
256
2)X
10
6
150
10
6
2
计算得:X=106,16 进制为 6AH,即TH0 和TL0 的赋值都为 6AH(因方式 2 位自动装入模式)
Proteus图:
程序及解释:
图 4 题 2 图及调出示波器的位置
ORG 0H
AJMP MAIN
;程序从程序存储器的 0 单元开始存放
;跳转至以 MAIN 为标号的主程序
ORG 0BH
AJMP T0INT
;0B 是定时器 0 的中断子程序入口
;跳转到以 T0INT 为标号的中断子程序
ORG 30H
;主程序从 30H 单元开始存放
MAIN: MOV TMOD,#20H
;设置定时器的工作方式,采用工作方式 2 即自动装入的 8 位
MOV TH0,#8AH
MOV TL0,#8AH
SETB EA
SETB ET0
SETB TR0
SJMP $
;给 TH0 赋初值
;给 TL0 赋初值
;打开总中断
;打开 T0 的中断
;让 T0 开始工作
;踏步,等待中断
T0INT: CPL P1.0
;时间到,翻转 P1.0
;因为 300us 正好是 150us 的整数倍,因而可用一个定时器
INC R0
CJNE R0,#2,GOON ;用 R0 作为中断几次的计数器,若中断 2 次既达到 150us 的两倍
MOV R0,#0
CPL P1.1
RETI
;若达到了两倍,翻转,计数器清零
;P1.1 翻转
;中断子程序返回
GOON:
END
;程序结束
3
3. 应用 164 带 3 只数码管,显示从 000-999 的单个跳数;
图 5 波形图
本题考虑点:
164 是移位寄存器,因此最好直接用串口,与 164 连接;
3 位数,可把三位数设为一个计数器,设从 30H-32H,其中 30H为最低位,31H为中间位,32H为最
高位,然后从 30H开始加 1,当 30H加到 10 后,30H清零,31H再加 1,31H为 10 后,变为零,32H再加 1,
当 32H为 10 后,清零。
把显示部分编写为一个子程序,30-32H内的数每改变一次,调用一次显示;
由于人的视力跟不上单片机一条指令的运算时间,因此需要延时。
因此,在软件设计上可分为三部分:一是加数部分,一是显示部分,一是延时部分。
Proteus图:
(注意RXD、TXD的接法,以及后两只 164 的接法)
图 6 题 3 图
程序:
ORG 0H
;程序从程序存储器的 0 单元开始存放
4
AJMP MAIN
;跳转到主程序
ORG 30H
MAIN: MOV 30H,#0
MOV 31H,#0
MOV 32H,#0
;主程序从程序存储器的 30H单元开始存放
;给 30H单元赋初始值 0
;给 31H单元赋初始值 0
;给 32H单元赋初始值 0
LOOP:
INC 30H
MOV R1,30H
CJNE R1,#10,NEXT
MOV 30H,#0
INC 31H
MOV R1,31H
CJNE R1,#10,NEXT
MOV 31H,#0
INC 32H
MOV R1,32H
CJNE R1,#10,NEXT
MOV 32H,#0
;30H单元内的数加 1
;将 30H单元内的数赋值给R1,以便应用 CJNE Rn,#DATA,REL语言判断并跳转
;若 30H内的数不是 10 则跳转到调用显示
;若 30H内的数是 10,则清零
;上位 30H的数等于 10 时,下一位 31H加 1
;将 31H内的数赋值给R1
;间接地判断 31H内的数是否等于 10,如不是,转显示
;若 31H等于 10,则清零,将 32H加 1
;32H加 1(此为最高位)
;判断 32H的数值
;间接判断 32H内的数是否等于 10,不是转显示
;若是 32H清零
NEXT: ACALL DISPLAY
ACALL DELAY
SJMP LOOP
;调用显示子程序
;调用延时子程序
;跳转到加 1 部分,循环
DISPLAY:MOV R0,#30H
MOV DPTR,#TAB
DISLOP:MOV A,@R0
;将显示数据的存放首单元赋值给R0,以便调用循环将数值赋值给A
;将显示码的首地址赋值给DPTR
;将以R0 内的数 30H内的数值赋值给A
;查表语句,将显示码赋值给A
;将显示码通过串行口送出去
MOVC A,@A+DPTR
MOV SBUF,A
JNB TI,$
CLR TI
INC R0
CJNE R0,#33H,DISLOP ;判断是否将 3 个单元(30H,31H,32H)的数据都送完
RET
;如果TI不等于 1,表明还没送出去,等待
;若TI=1 表明数据已经送走,将送走的标志位TI清零,以便进行下次输送
;指向下一单元
;子程序返回
DELAY: MOV R7,#0
DEL1: MOV R6,#0
DJNZ R6,$
DJNZ R7,DEL1
RET
;延时子程序,给R7 赋值 0(相当于 256)
;给R6 赋值 0
;若R6-1 不等于 0,在此语句循环
;如R0=0 则判断R7-1 是否为零,不为零则跳转到DEL1,给R6 重新赋值
;子程序返回
TAB:
DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH ;显示码表
END
;程序结束
5
图 7 运行状态图
4. 应用双机通讯,实现在A机上的数码管数字加到按另一键时的将该数发送
到B机的数码管上显示。
本题考虑点:
双机通讯,串行口的通讯方式设置;
设采用串行口方式 1,则需要设置波特率,应用T1 的工作方式 2;
双机都带一只数码管;
主机带 3 只按键。
Proteus图:
此处由于用P0 口带数码管,因此因在P0 各管脚上加上拉电阻,此处用排阻respack-8;公共端接高。
编程考虑:
图 8 题 4 图
6
波特率生成器用T1 的工作模式 2,波特率选用 9600,晶振 6MHz,则TH1 和TL1 的赋值为 0F4H,SCON
选用工作模式 1,且可接收。
C\T
0
SM1
1
TMOD= #20H
GATE
0
SCON=50H
SM0
0
编程:
主机程序:
M1
1
SM2
0
M0
0
REN
1
GATE
0
TB8
0
C\T
0
RB8
0
M1
0
TI
0
M0
0
RI
0
ORG 0H
AJMP MAIN
ORG 30H
;程序从程序存储器的 0 单元开始存放
;跳转到以 MAIN 为标号的程序去
;以下程序从程序存储器的 30H 开始存放
MAIN: MOV TMOD,#20H
;选用定时器 2 工作模式,即自动赋初始值的 8 位定时器
MOV TH1,#0F4H
MOV TL1,#0F4H
SETB EA
SETB ET1
SETB TR1
MOV SCON,#50H
;给 TH1 赋值 0F4H;
;给 TL1 赋值 0F4H;
;打开总中断允许位;
;打开定时器 1 的中断允许位;
;使定时器 1 运行
;设置串行口的工作模式,采用模式 1
MOV DPTR,#TAB
MOV R0,#0
MOV R1,#0
;赋值显示码表的首地址
;设置 R0 为显示数字的计数器
;R1 设置为讯显示码的中转寄存器
KEYSCAN:JB P1.0,KEY1
;若按键 1 没有被按下,转去查询键 2
JNB P1.0,$
INC R0
CJNE R0,#10,NEXT
MOV R0,#0
NEXT: MOV A,R0
;如键 1 被按下,则等待键 1 弹起
;键 1 弹起后,显示数加 1
;如显示数等于 10,则从 0 开始
;清零
;将显示的数给 A
MOVC A,@A+DPTR
MOV R1,A
MOV P0,A
key1: JB P1.1,KEYSCAN
JNB P1.1,$
MOV A,R1
MOV SBUF,A
JNB TI,$
CLR TI
SJMP KEYSCAN
;查表取显示的码值
;将码值给 R1 暂存
;将显示码值给 P0 显示
;检测第二个按键按下没有
;按下了等待弹起
;将显示码给 A
;将显示码送去串行口
;若 TI 不等于 1,表明正在发送中
;TI=1,则表明已经发送完毕,将标志位清零,以便下次发送
;继续检测有按键是否被按下
7
TAB:
DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH ;显示码
END
;程序结束
从机程序:
ORG 0H
AJMP MAIN
ORG 30H
;程序从程序存储器的 0 单元开始存放
;跳转到以 MAIN 为标号的程序去
;以下程序从程序存储器的 30H 开始存放
MAIN: MOV TMOD,#20H
;选用定时器 2 工作模式,即自动赋初始值的 8 位定时器
MOV TH1,#0F4H
MOV TL1,#0F4H
SETB EA
SETB ET1
SETB TR1
MOV SCON,#50H
;给 TH1 赋值 0F4H;
;给 TL1 赋值 0F4H;
;打开总中断允许位;
;打开定时器 1 的中断允许位;
;使定时器 1 运行
;设置串行口的工作模式,采用模式 1
LOOP:
JNB RI,$
CLR RI
MOV A,SBUF
MOV P0,A
SJMP LOOP
;若 RI 不等于 1,表明无数据通过串行口送入
;如 RI=1,表明有数据送入,将 RI 清零,以便下次接收
;将串行口接收到的数据给 A
;A 将接收到的数据传送给 P0,显示
;继续等待接收到数据
END
;程序结束
图 9 题 4 运行状态图
5. 应用外部中断,对连接在P3.2 管脚上的按键次数进行计数,每 5 次在P1.
8