51单片机8位数码管时钟(汇编语言)

作业要求


使用8位数码管实现时间的显示,进位等操作
使用汇编语言完成作业

最终效果

理论基础

寻址

汇编语言的一些基本寻址操作

MOV A,#20H
MOV R1,20H
MOV @R1,#20H
MOV A,@R1

需要理解用法和含义

中断

实现计时器需要使用中断来完成延时
如果使用循环延迟的话,在计时过程中处理器不能进行其他操作

位码

设置具体的显示位,如 00H 是数码管的第一位
本例中使用 P2 引脚输出位码

段码

输出图形的控制
本例中使用 P1 引脚
如 40H 为 -

显示

一个数字的显示需要位码和段码同时起作用
如 P1 输入 #00H, P2 输入 #40H
在数码管的第一位会显示 “-”

这里显示需要不连续的进行显示
(数字和"-"需要分开)
所以只用一个地址位去缓存位码是不够的
(如果是连续显示,不断修改buffer为位码就行了)
这里采用了6个地址空间去对位码进行缓存

MOV index,#00H
MOV cDisplayBit,#00H
MOV cDisplayBit+1,#01H
MOV cDisplayBit+2,#03H
MOV cDisplayBit+3,#04H
MOV cDisplayBit+4,#06H
MOV cDisplayBit+5,#07H

其中 02H 和 05H需要显示为"-",我使用另外一个子程序去进行显示

显示缓冲区

本例中使用 cDisplayBuffer 表示 20H,并将 20-25H 这六位作为显示缓冲区

存储需要显示的数字的原值,如1,2,3

从指定地址中取值然后转换为段码再配合位码即可实现显示

cDisplayBuffer 作为 位码的缓存位
难点
中间需要显示"-",所以位码缓存位只使用1位是不够的,详细参见下列代码拆分

结构

内存设置

ORG 0000H
SJMP MAIN
ORG 000BH
LJMP SER0
cDisplayBuffer  EQU 20H ;
cDisplayBit     EQU 40H ;当前显示的位 40-45;47 46固定显示-
index       EQU 50H ;作为遍历index使用

设置初值

需要写到MAIN函数中

MAIN:MOV index,#00HMOV cDisplayBit,#00HMOV cDisplayBit+1,#01HMOV cDisplayBit+2,#03HMOV cDisplayBit+3,#04HMOV cDisplayBit+4,#06HMOV cDisplayBit+5,#07H

中断延迟程序

MOV SP,#70H          ;设置堆栈SP
CLR EA          ;关中断
MOV 30H,#23H            ;设置初始时间值
MOV 31H,#59H
MOV 32H,#56H
MOV TMOD,#01H       ;使用定时器0,软件控制,定时模式,方式1
MOV TH0,000H            ;定时初值
MOV TL0,0D8H
MOV R6,#28          ;设定计数次数50,作为中断次数计数的全局变量
SETB EA         ;开中断
SETB ET0            ;允许T0中断
SETB TR0            ;启动定时器0

此部分也需要放到MAIN函数中

显示程序

SHOW:LCALL LOOSE         ;调用子程序拆分BCD码并存入显示缓冲区LCALL DISP          ;调用显示子程序进行显示LJMP SHOW

DISP

有6位数需要显示,所以需要循环六次,故把 R3 置 6 然后使用 DJNZ 循环

我们不需要 2,5 两位数码管显示数字

所以循环中使用index去取得位码,位码的值已经在 40-45H 单元中设置好了

这里为了同时显示数字和"-"所以把它们两个分开了

使用index也是因为这个原因,不然的话位码缓存位只需要一个地址位就够了

这里调用了一下 Delay 是为了防止抖动,不调用的话会显示错误,

但是放到中断循环中又太快了,所以出此下策

DISP:                ; 显示子程序MOV R3,#6H           ; 总共6个位MOV index,#00H       ; index置0
M1:LCALL DelayMOV   A,#40HADD   A,indexMOV  R0,AMOV A,@R0MOV   P2,AMOV DPTR,#DispTabLeMOV  A,#20H          ;A地址指向缓存ADD A,index         ;位码的值加到A上MOV    R0,AMOV A,@R0MOVC  A,@A+DPTR     ;取段码MOV P1,AINC index           ;index 加一DJNZ   R3,M1M2:                ;显示两个"-"的子程序LCALL DelayMOV P2,#02H            ; 02和05MOV P1,#40H          ; "-"的段码为 #40HLCALL Delay MOV P2,#05HMOV P1,#40HRET

BCD转换

这里为了实现60进制所以把 30-32H 作为 十进制数 的缓存地址

取出十进制数后分别取高低位然后送入20-25H 的6位时间缓冲区

LOOSE:               ;拆分子程序,压缩BCD码->hexMOV R5,#03H            ;总共3个字节,需要循环3次MOV R0,#30H           ;时间序列存储首地址MOV R1,#20H           ;6位缓冲区
LOOP1:MOV A,@R0ANL A,#0F0H         ;取高位SWAP AMOV @R1,AINC R1MOV A,@R0            ;存高位ANL A,#0FH          ;取低位MOV @R1,A          ;存低位INC R0INC R1DJNZ R5,LOOP1RET

秒数自增

BCD转换完成后可以使用 CJNE 命令来实现进位

看注释即可明白,不过多叙述

NUMINC:              ;时间序列加一秒子程序MOV R1,#32H          ;时间序列末地址(秒)MOV A,@R1ADD A,#01H           ;加1DA A             ;转BCD码MOV @R1,A            ;保存CPL P3.0CJNE @R1,#60H,TORET         ;若未到60秒,直接返回,否则执行下面程序MOV @R1,#00H          ;秒数清零DEC R1         ;进行分钟位的操作MOV A,@R1ADD A,#01HDA AMOV @R1,ACJNE @R1,#60H,TORET     ;若未到60分,直接返回,否则执行下面程序MOV @R1,#00H          ;分钟数清零DEC R1            ;进行时数的操作MOV A,@R1ADD A,#01HDA AMOV @R1,ACJNE @R1,#24H,TORET      ;若未到24时,直接返回,否则执行下面程序MOV @R1,#00H          ;小时数清零

完整源代码

汇编源码

ORG 0000H
SJMP MAIN
ORG 000BH
LJMP SER0cDisplayBuffer     EQU 20H     ;6位段码实际值的缓冲区
cDisplayBit     EQU 40H     ;6位位码的缓冲区 40-45;47 46固定显示"-"
index       EQU 50HMAIN:MOV index,#00HMOV cDisplayBit,#00HMOV cDisplayBit+1,#01HMOV cDisplayBit+2,#03HMOV cDisplayBit+3,#04HMOV cDisplayBit+4,#06HMOV cDisplayBit+5,#07H; 存在2 5两位需要显示为 - 所以选用六个内存空间作为位码缓存MOV SP,#70H           CLR EA          MOV 30H,#22H            ;设置初始时间值MOV 31H,#59HMOV 32H,#55HMOV TMOD,#01H       MOV TH0,000H            MOV TL0,0D8HMOV R6,#28          SETB EA         SETB ET0            SETB TR0
SHOW:LCALL LOOSE            LCALL DISP          LJMP SHOW
SER0:               MOV TH0,#000H       MOV TL0,#0D8HDJNZ R6,EXIT           MOV R6,#28          LCALL NUMINC            EXIT:RETILOOSE:             MOV R5,#03H         ;总共3个字节,需要循环3次MOV R0,#30H           ;时间序列存储首地址MOV R1,#20H           ;6位缓冲区
LOOP1:MOV A,@R0ANL A,#0F0H         ;取高位SWAP AMOV @R1,AINC R1MOV A,@R0            ;存高位ANL A,#0FH          ;取低位MOV @R1,A          ;存低位INC R0INC R1DJNZ R5,LOOP1RETDISP:               ; 显示子程序MOV R3,#6H           ; 总共6个位MOV index,#00H       ; index置0
M1:LCALL DelayMOV   A,#40HADD   A,indexMOV  R0,AMOV A,@R0MOV   P2,AMOV DPTR,#DispTabLeMOV  A,#20H          ;A地址指向缓存ADD A,index         ;位码的值加到A上MOV    R0,AMOV A,@R0MOVC  A,@A+DPTR     ;取段码MOV P1,AINC index           ;index 加一DJNZ   R3,M1M2:                ;显示两个"-"的子程序LCALL DelayMOV P2,#02H            ; 02和05MOV P1,#40H          ; "-"的段码为 #40HLCALL Delay MOV P2,#05HMOV P1,#40HRETNUMINC:                MOV R1,#32H         ;时间序列末地址(秒)MOV A,@R1ADD A,#01H           ;加1DA A             ;转BCD码MOV @R1,A            ;保存CPL P3.0CJNE @R1,#60H,TORET         MOV @R1,#00H           DEC R1          MOV A,@R1ADD A,#01HDA AMOV @R1,ACJNE @R1,#60H,TORET      MOV @R1,#00H           DEC R1          MOV A,@R1ADD A,#01HDA AMOV @R1,ACJNE @R1,#24H,TORET      MOV @R1,#00H           TORET:RETDispTable: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FHDelay:MOV R0,#10MOV   R1,#10DJNZ  R1,$DJNZ    R0,$-4RETEND

原理图

这里注意区分一下自己单片机的段码位码输出IO,前面已经说过了

后记

后面使用示波器抓波然后对循环和中断部分进行微调可以实现微秒级别的误差

这里我使用了CPL输出所以T=2s
“-” 的显示上还有其他方案,望读者自行思考
同学有的使用不判断进位来实现 “-” 的显示,这样displaybuffer仅需1位
不必像本文这样冗杂
希望读者能够有所收获!

参考了这篇文章
基于MCS-51单片机使用定时器编写时钟程序(汇编)
数码管显示部分在我的另一篇文章中有更详细的讲解
51单片机出租车计价器(汇编语言)
仿真文件下载 传送门
文章允许规范转载

51单片机8位数码管计时器(汇编语言)相关推荐

  1. 51单片机一位数码管汇编程序

    51单片机一位数码管汇编程序 程序: ;数码管从0-9显示ORG 0000HAJMP MAINORG 0030HMAIN: MOV R4, #00H ;记录码表的值MOV DPTR, #TABLE ; ...

  2. 51单片机8位数码管简易计算器(4*4矩阵键盘)

    筒子们,上周参考了好多单片机计算器的文章,但是全文阅读基本都是付费,看了好几篇:参考了某个思路,终于完成了一个简易版的计算器: 1.8位数码管显示 2.简单的四则运算(加减乘除) 3.PS,以下代码目 ...

  3. 51单片机4位数码管按键显示

    定义一个数g,初始化为0,每按下一次键盘g都加1,把第一次的数赋给b显示在数码管上,第二次的数赋给c显示在数码管上,依次类推直到第四位.定义一个确认按键按下后检查密码是否为1112,如果是就..... ...

  4. 单片机学习笔记————51单片机实现带数码管显示的象棋比赛专用计时器

    一.使用proteus绘制简单的电路图,用于后续仿真 二.编写程序 /***************************************************************** ...

  5. 单片机学习笔记————51单片机实现在数码管中实现iphone4S开机密码锁的程序

    一.使用proteus绘制简单的电路图,用于后续仿真 二.编写程序 /***************************************************************** ...

  6. 51单片机入门——动态数码管显示详解

    51单片机:动态数码管显示 - 模块图 - 显示原理 – 消抖 静态数码管技术 + 人眼视觉停留 显示原理类似于以前的 胶片机放影视,也就是只要我切换的速度足够快你就看不出来其实我是一次次显示的(滑稽 ...

  7. 51单片机:静态数码管详细教程

    51单片机:静态数码管详细教程 目录 51单片机:静态数码管详细教程 一.数码管通电 1.原理图 2.数码管真值表 二.实现程序 1.程序编写 2.接线问题 三.结果与总结 1.成果展示 2.总结 一 ...

  8. 【51单片机】七段数码管显示实验+详细讲解

    [51单片机]七段数码管显示实验 前言 一.兵马未动,粮草先行--认识七段数码管 1.关于显示器 2.七段数码管 3.七段数码管的结构 4.数码管显示方法 二.数码管显示程序 1.静态显示 效果 2. ...

  9. 基于51单片机8位竞赛抢答器_倒计时可调+LED跑马灯

    基于51单片机8位竞赛抢答器_倒计时可调+LED跑马灯仿真设计 (程序+proteus仿真+报告) Proteus仿真版本:proteus 7.8 程序编译器:keil 4/keil 5 编程语言:C ...

  10. 51单片机控制系统的人机交互接口设计【51单片机与LED数码管的动态显示接口案例分析】

    本章节利用Keil uVision5和ISIS 7 Professional两个软件来进行仿真实验. [例]运用51单片机实现8位8段数码管的动态显示,LED数码管的段选数据由51单片机的P0口控制, ...

最新文章

  1. 3.7 非极大值抑制-深度学习第四课《卷积神经网络》-Stanford吴恩达教授
  2. android dpi
  3. oracle19c xp安装 客户端_windows下安装oracle19c
  4. linux Boot目录满了之后的解决方法
  5. 计算机网络物理层之物理层之下的传输媒体
  6. python程序编写应注意哪些问题_Python程序员鲜为人知但你应该知道的17个问题
  7. python 批量修改图片尺寸
  8. 台式计算机怎么设置自动锁屏,台式机win7怎么设置自动锁屏
  9. 为什么html中使用不了样式,css不起作用是什么原因?
  10. 分门别类刷leetcode——贪心算法(C++实现)
  11. 前端白屏问题_首页白屏的引发的思考(一)
  12. ESIM卡移动联通电信ESIM卡价格ESIM卡
  13. 微信最强花式操作,带你玩转 wxpy
  14. iview解决打包后icon不显示问题
  15. C8051F单片机端口配置
  16. 利用数码管从左向右和从右向左显示学号
  17. unity3d广东麻将算法
  18. CheckedListBox拖拽或者拖动选项
  19. Linux环境快速搭建elasticsearch6.5.4集群和Head插件
  20. (难得要死)求一批整数中出现最多的个位数字

热门文章

  1. 基于javaweb+jsp的小蜜蜂扩音器网上商城系统(java+JSP+Servlet+JDBC+Ajax+mysql)
  2. js配合css3开发流畅的web拾色器功能
  3. 数据库:简述对数据库的认识
  4. 微信服务号、订阅号和企业号的区别(运营和开发两个角度)
  5. 应急响应-winlinux分析后门勒索病毒攻击
  6. 华为 荣耀 等手机解锁BootLoader
  7. VUE 文字转语音播放
  8. cdrx4自动排版步骤_如何在CorelDRAW软件排版CDR怎么快速排版技巧?
  9. keil4和烧录软件的基本使用
  10. 传感器 动态误差计算