当前位置: 首页 > news >正文

单片机学习笔记9.数码管

0到99计数 ,段选共阴极

;0到99计数 
ORG 0000H
LJMP MAIN
ORG 000BH
LJMP TIMER0_ISR
ORG 0100H; 定义位选控制位
DISPLAY_SELECT BIT 20H.0MAIN:; 定时器 0 初始化MOV TMOD, #01H ; 设置定时器 0 为模式 1MOV TH0, #3CH  ; 定时器 0 高 8 位初值,定时 50msMOV TL0, #0B0H ; 定时器 0 低 8 位初值,定时 50msSETB TR0       ; 启动定时器 0; 中断初始化SETB ET0       ; 使能定时器 0 中断SETB EA        ; 全局中断使能; 变量初始化MOV R0, #0     ; 存储当前秒数,范围 0 - 99MOV R1, #0     ; 50ms 计数,20 次为 1 秒CLR DISPLAY_SELECT ; 初始化位选控制位为 0MAIN_LOOP:SJMP MAIN_LOOP ; 主循环,等待中断TIMER0_ISR:; 重新加载定时器初值MOV TH0, #3CHMOV TL0, #0B0H; 50ms 计数INC R1CJNE R1, #20, DISPLAY ; 未到 1 秒,直接进行显示操作; 1 秒时间到,重置计数MOV R1, #0; 秒数加 1INC R0CJNE R0, #100, DISPLAY ; 未到 100 秒,进行显示操作; 秒数达到 100,重置为 0MOV R0, #0DISPLAY:; 分离十位和个位MOV A, R0MOV B, #10DIV AB ; A 为十位,B 为个位; 根据位选控制显示JB DISPLAY_SELECT, DISPLAY_LOW ; 若 DISPLAY_SELECT 为 1,显示个位MOV P2, #0FEH       ; 十位位选,假设通过 P2.0 控制SJMP COMMON_DISPLAYDISPLAY_LOW:MOV P2, #0FDH       ; 个位位选,假设通过 P2.1 控制MOV A, B            ; A 中为个位数字COMMON_DISPLAY:MOV DPTR, #SEG_CODE_TABLEMOVC A, @A+DPTR     ; 从段码表获取段码MOV P0, A           ; 段码输出到 P0 口; 切换位选控制CPL DISPLAY_SELECTRETI                ; 中断返回SEG_CODE_TABLE:DB 3FH, 06H, 5BH, 4FH, 66H, 6DH, 7DH, 07H, 7FH, 6FHEND

0-99计数


1. 代码整体结构

ORG 0000H
LJMP MAIN
ORG 000BH
LJMP TIMER0_ISR
ORG 0100H

  • ORG 0000H:指定程序的起始地址为 0000H
  • LJMP MAIN:长跳转指令,跳转到 MAIN 标号处开始执行主程序。
  • ORG 000BH:定时器 0 中断服务程序的入口地址为 000BH,当定时器 0 产生中断时,程序会跳转到这个地址执行。
  • LJMP TIMER0_ISR:跳转到 TIMER0_ISR 标号处执行定时器 0 的中断服务程序。
  • ORG 0100H:指定主程序从 0100H 地址开始执行。

2. 位定义

DISPLAY_SELECT BIT 20H.0

  • 使用 BIT 伪指令将 20H 字节的第 0 位定义为 DISPLAY_SELECT,用于控制数码管显示十位还是个位。

3. 主程序 MAIN

MAIN:; 定时器 0 初始化MOV TMOD, #01H ; 设置定时器 0 为模式 1MOV TH0, #3CH  ; 定时器 0 高 8 位初值,定时 50msMOV TL0, #0B0H ; 定时器 0 低 8 位初值,定时 50msSETB TR0       ; 启动定时器 0; 中断初始化SETB ET0       ; 使能定时器 0 中断SETB EA        ; 全局中断使能; 变量初始化MOV R0, #0     ; 存储当前秒数,范围 0 - 99MOV R1, #0     ; 50ms 计数,20 次为 1 秒CLR DISPLAY_SELECT ; 初始化位选控制位为 0MAIN_LOOP:SJMP MAIN_LOOP ; 主循环,等待中断
定时器 0 初始化
  • MOV TMOD, #01H:将 TMOD 寄存器设置为 01H,使定时器 0 工作在模式 1(16 位定时器模式)。
  • MOV TH0, #3CH 和 MOV TL0, #0B0H:给定时器 0 的高 8 位 TH0 和低 8 位 TL0 赋初值,这样定时器 0 每计数到溢出时,时间间隔约为 50ms。
  • SETB TR0:启动定时器 0 开始计数。
中断初始化
  • SETB ET0:使能定时器 0 的中断功能,当定时器 0 溢出时会触发中断。
  • SETB EA:全局中断使能,允许所有中断源产生中断。
变量初始化
  • MOV R0, #0:将 R0 寄存器初始化为 0,用于存储当前的秒数,范围是 0 - 99。
  • MOV R1, #0:将 R1 寄存器初始化为 0,用于对 50ms 的中断次数进行计数,每 20 次中断表示经过了 1 秒。
  • CLR DISPLAY_SELECT:将位选控制位 DISPLAY_SELECT 清 0,表示初始时显示数码管的十位。
主循环
  • SJMP MAIN_LOOP:无限循环,程序会一直停在这里等待定时器 0 中断的发生。

4. 定时器 0 中断服务程序 TIMER0_ISR

TIMER0_ISR:; 重新加载定时器初值MOV TH0, #3CHMOV TL0, #0B0H; 50ms 计数INC R1CJNE R1, #20, DISPLAY ; 未到 1 秒,直接进行显示操作; 1 秒时间到,重置计数MOV R1, #0; 秒数加 1INC R0CJNE R0, #100, DISPLAY ; 未到 100 秒,进行显示操作; 秒数达到 100,重置为 0MOV R0, #0DISPLAY:; 分离十位和个位MOV A, R0MOV B, #10DIV AB ; A 为十位,B 为个位; 根据位选控制显示JB DISPLAY_SELECT, DISPLAY_LOW ; 若 DISPLAY_SELECT 为 1,显示个位MOV P2, #0FEH       ; 十位位选,假设通过 P2.0 控制SJMP COMMON_DISPLAYDISPLAY_LOW:MOV P2, #0FDH       ; 个位位选,假设通过 P2.1 控制MOV A, B            ; A 中为个位数字COMMON_DISPLAY:MOV DPTR, #SEG_CODE_TABLEMOVC A, @A+DPTR     ; 从段码表获取段码MOV P0, A           ; 段码输出到 P0 口; 切换位选控制CPL DISPLAY_SELECTRETI                ; 中断返回
重新加载定时器初值
  • MOV TH0, #3CH 和 MOV TL0, #0B0H:每次定时器 0 溢出产生中断后,重新给 TH0 和 TL0 赋初值,以便下一次计时。
50ms 计数和秒数更新
  • INC R1R1 寄存器的值加 1,表示又经过了一个 50ms 的时间间隔。
  • CJNE R1, #20, DISPLAY:比较 R1 的值是否等于 20,如果不等于 20,说明还未经过 1 秒,直接跳转到 DISPLAY 处进行显示操作。
  • MOV R1, #0:如果 R1 的值等于 20,说明经过了 1 秒,将 R1 重置为 0,准备下一次的 1 秒计时。
  • INC R0:秒数 R0 加 1。
  • CJNE R0, #100, DISPLAY:比较 R0 的值是否等于 100,如果不等于 100,说明还未达到 99 秒,跳转到 DISPLAY 处进行显示操作。
  • MOV R0, #0:如果 R0 的值等于 100,说明秒数达到了 99 秒,将 R0 重置为 0,重新开始计时。
显示部分
  • 分离十位和个位
    • MOV A, R0:将当前秒数 R0 送入累加器 A
    • MOV B, #10:将立即数 10 送入寄存器 B
    • DIV AB:执行除法运算,A 中存储商(即十位数字),B 中存储余数(即个位数字)。
  • 根据位选控制显示
    • JB DISPLAY_SELECT, DISPLAY_LOW:判断 DISPLAY_SELECT 位是否为 1,如果为 1,跳转到 DISPLAY_LOW 处显示个位数字。
    • MOV P2, #0FEH:如果 DISPLAY_SELECT 位为 0,将 P2 口输出 0FEH,假设通过 P2.0 控制数码管的十位显示。
    • SJMP COMMON_DISPLAY:跳转到 COMMON_DISPLAY 处进行段码显示。
    • DISPLAY_LOW
      • MOV P2, #0FDH:将 P2 口输出 0FDH,假设通过 P2.1 控制数码管的个位显示。
      • MOV A, B:将个位数字从 B 寄存器送入累加器 A
  • 获取段码并显示
    • MOV DPTR, #SEG_CODE_TABLE:将段码表的起始地址送入数据指针 DPTR
    • MOVC A, @A+DPTR:根据 A 中的数字(十位或个位)从段码表中获取对应的段码。
    • MOV P0, A:将获取到的段码输出到 P0 口,用于驱动数码管显示相应的数字。
  • 切换位选控制
    • CPL DISPLAY_SELECT:对 DISPLAY_SELECT 位取反,以便下次中断时显示另一位数字。
  • 中断返回
    • RETI:中断返回指令,结束本次中断服务程序,返回到主程序继续执行。

5. 段码表

SEG_CODE_TABLE:DB 3FH, 06H, 5BH, 4FH, 66H, 6DH, 7DH, 07H, 7FH, 6FH

  • SEG_CODE_TABLE 是一个段码表,存储了数字 0 - 9 对应的数码管段码。DB 是定义字节的伪指令,依次定义了数字 0 - 9 的段码。例如,3FH 是数字 0 的段码,06H 是数字 1 的段码,以此类推。

综上所述,整个代码通过定时器 0 产生 50ms 的定时中断,每 20 次中断(即 1 秒)更新一次秒数,同时利用数码管动态显示当前的秒数,实现了 0 - 99 秒的计时功能。

相关文章:

  • Java大师成长计划之第5天:Java中的集合框架
  • Python语言基础知识详解:数据类型及运算
  • DJL FastText (FtModel) 使用指南
  • xe-upload上传文件插件
  • 堆和二叉树的概念和操作
  • 【算法笔记】贪心算法
  • node20的安装和vue的入门准备
  • Python语言基础知识详解:分支结构控制语句
  • babel和loader的关系
  • 【数据挖掘】时间序列预测-时间序列的平稳性
  • 猿人学web端爬虫攻防大赛赛题第15题——备周则意怠-常见则不疑
  • DeepSeek:重构人类文明的智能引擎
  • 使用CubeMX新建USART1不定长接收工程
  • log4cpp 编译说明文档
  • Transformer数学推导——Q25 分析视觉-语言模型中区域注意力(Region Attention)的边界框投影公式
  • 机器学习day2-seaborn绘图练习
  • RagFlow文档切块提升
  • 基于亚马逊云科技搭建企业问答系统
  • LeetCode42_接雨水
  • 北冰洋:突破热力极限!99℃离心热泵机组,开启工业节能新时代!
  • 李祥翔评《孔子哲学思微》︱理性秩序与美学秩序的碰撞
  • 国家发改委:建立实施育儿补贴制度
  • 广州一人均500元的日料店回收食材给下一桌?市场监管部门介入调查
  • VR数字沉浸体验又添新节目,泰坦尼克号驶进文旅元宇宙
  • 调查丨当节气出现“时差”,陕西的果农们经历着什么?
  • 记录发生真相,南沙岛礁生态调查纪实片《归巢》发布