小白学习 发表于 2026-9-2 00:06

STC12C5A60S2驱动TM1650四位共阳数码管0-9999计数

前面有一篇是固定显示数字0123的

今天是上电显示9999一秒后显示   0然后   1~   2~   3~~~9999,数字之间间隔时间是1秒,汇编代码如下:



;=====================================================
; 51单片机 + TM1650数码管驱动程序
; 晶振:12M
; 功能:T0定时器中断实现1秒计时,4位秒表 0000~9999循环
; 效果:上电显示9999一秒后显示   0一秒后显示   1~~~9999
; 引脚定义:CLK接P3.7,DIO接P3.6
;=====================================================

CLK         EQU P3.7   ;定义TM1650时钟引脚,文本替换
DIO         EQU P3.6   ;定义TM1650数据引脚,文本替换
MS10_NUM    EQU 30H    ;片内RAM30H,10ms中断计数变量
One         EQU 31H    ;片内RAM31H,个位 0~9
Ten         EQU 32H           ;片内RAM32H,十位 0~9
Hundred         EQU 33H           ;片内RAM33H,百位 0~9
Thound        EQU 34H           ;片内RAM34H,千位 0~9
DISP_TMP    EQU 35H    ;临时变量,保存当前要输出的显示值 0~10(10=熄灭)

ORG 0000H            ;程序复位入口地址,单片机上电从此处取指令
LJMPMAIN             ;长跳转,跳转到主程序MAIN执行

ORG 000BH            ;定时器0中断向量入口地址
LJMPTIMER0         ;发生T0中断,跳转到中断服务子程序

ORG40H               ;主程序起始存放地址,避开寄存器组、位寻址区

;=============================================
; MAIN:主程序,完成硬件初始化,进入主循环刷新显示
;=============================================
MAIN:
MOV      SP,#60h   ;设置堆栈指针SP=60H,堆栈从61H向上生长,避免覆盖自定义RAM变量
MOV TMOD,#01H          ;设置T0工作模式,模式1,16位定时器,无硬件自动重装
MOV TH0,#0D8H          ;定时器0高8位初值,12M晶振定时10ms
MOV TL0,#0F0H          ;定时器0低8位初值,65536?0xD8F0=10000机器周期=10ms
SETB TR0               ;置位TR0,启动定时器0开始计数
SETB ET0               ;置位ET0,使能定时器0中断允许位
SETB EA                ;置位EA,开启单片机CPU总中断开关
MOV MS10_NUM,#0      ;10ms计数变量初始化清零
MOV One,#9             ;个位初始值9
MOV Ten,#9             ;十位初始值9
MOV Hundred,#9         ;百位初始值9
MOV Thound,#9          ;千位初始值9

;==================== TM1650芯片初始化 ====================
LCALL TM1650_Start   ;调用子程序,发送I2C通信起始信号
MOV A,#48H             ;把TM1650开启显示命令0x48送入累加器A
LCALL TM1650_Writebyte ;调用写字节子程序,向TM1650发送命令0x48
MOV A,#00010001B       ;亮度配置参数,bit0~bit2控制数码管亮度
LCALL TM1650_Writebyte ;调用写字节子程序,发送亮度配置
LCALL TM1650_Stop      ;调用子程序,发送I2C停止信号,初始化完成

WAIT:                  ;主循环标签
LCALL DISP             ;调用显示子程序,刷新数码管显示
SJMPWAIT             ;相对跳转,回到WAIT,循环不停刷新屏幕

;=============================================
; TIMER0:定时器0中断服务程序,每10ms触发一次
; 功能:10ms计数,累计到100次产生1秒,执行十进制进位
;=============================================
TIMER0:
PUSH PSW               ;入栈保护程序状态字PSW,防止中断修改标志位破坏主程序
PUSH ACC               ;入栈保护累加器A,保护A原有数值
MOV TH0,#0D8H          ;16位定时器无自动重装,手动重写高8位初值
MOV TL0,#0F0H          ;手动重写低8位初值,保证定时依旧10ms
INC MS10_NUM         ;10ms计数变量自加1,每进一次中断+1
MOV A,MS10_NUM         ;把计数值送入A,用于比较判断
CJNE A,#100,T_EXIT   ;比较A是否等于100;不等于100跳转到T_EXIT退出中断
MOV MS10_NUM,#0      ;累计满100次10ms等于1秒,计数器清零重新计时

;========= 4位十进制进位逻辑 0000~9999 =========
INC One                ;个位+1
MOV A,One            ;将个位送入A用于判断
CJNE A,#10,T_EXIT      ;个位不到10,直接退出中断
MOV One,#0             ;个位满10,清零
INC Ten                ;十位+1
MOV A,Ten            ;将十位送入A用于判断
CJNE A,#10,T_EXIT      ;十位不到10,直接退出中断
MOV Ten,#0             ;十位满10,清零
INC Hundred            ;百位+1
MOV A,Hundred          ;将百位送入A用于判断
CJNE A,#10,T_EXIT      ;百位不到10,直接退出中断
MOV Hundred,#0         ;百位满10,清零
INC Thound             ;千位+1
MOV A,Thound         ;将千位送入A用于判断
CJNE A,#10,T_EXIT      ;千位不到10,直接退出中断
MOV Thound,#0          ;千位满10,清零,回到0000

T_EXIT:
POP ACC                ;出栈,恢复累加器A原来的值
POP PSW                ;出栈,恢复程序状态字PSW
RETI                   ;中断返回指令,回到被打断的主程序

;=============================================
; DISP:显示子程序
; 功能:4位数码管输出,前导零消隐;千/百/十前导0熄灭,个位永远显示
;=============================================
DISP:
PUSH ACC               ;保护累加器A
PUSH DPH               ;保护数据指针高8位
PUSH DPL               ;保护数据指针低8位
MOV DPTR,#TAB          ;DPTR指向段码表首地址

;判断四位是否全部为0,不再强制输出0000,直接进入普通消隐
MOV A,Thound         ;读取千位到A
JNZCHK_NORMAL      ;千位≠0,直接跳普通显示流程
MOV A,Hundred          ;千位为0,读取百位到A
JNZCHK_NORMAL      ;百位≠0,直接跳普通显示流程
MOV A,Ten            ;千、百为0,读取十位到A
JNZCHK_NORMAL      ;十位≠0,直接跳普通显示流程
MOV A,One            ;千、百、十为0,读取个位到A
JNZCHK_NORMAL      ;个位≠0,直接跳普通显示流程
SJMP CHK_NORMAL      ;四位全部为0,走普通消隐逻辑,仅点亮个位0

CHK_NORMAL:
;千位 寄存器地址68H
LCALLTM1650_Start    ;发起I2C起始
MOV A,#68H             ;TM1650千位寄存器地址
LCALL TM1650_Writebyte ;发送寄存器地址
MOV A,Thound         ;读取千位数值
JNZTH_SHOW         ;千位不为0,跳转到显示
MOV DISP_TMP,#10       ;千位为0,赋值10代表熄灭数码管
SJMP TH_SEND         ;跳过显示赋值,直接发送
TH_SHOW:
MOV DISP_TMP,A         ;千位非0,把数字存入临时变量
TH_SEND:
MOV A,DISP_TMP         ;把待输出值送入A
LCALL QUBIAO         ;调用查表输出段码/熄灭
LCALL TM1650_Stop      ;I2C停止

;百位 寄存器地址6AH
LCALLTM1650_Start    ;发起I2C起始
MOV A,#6AH             ;TM1650百位寄存器地址
LCALL TM1650_Writebyte ;发送寄存器地址
MOV A,Thound         ;读取千位
JNZHU_SHOW         ;千位非0 → 百位强制显示
MOV A,Hundred          ;千位为0,读取百位
JNZHU_SHOW         ;百位非0 → 百位显示
MOV DISP_TMP,#10       ;千、百都为0,熄灭百位
SJMP HU_SEND         ;跳过显示赋值,直接发送
HU_SHOW:
MOV A,Hundred          ;读取百位数字
MOV DISP_TMP,A         ;存入临时变量
HU_SEND:
MOV A,DISP_TMP         ;待输出值送入A
LCALL QUBIAO         ;查表输出段码/熄灭
LCALL TM1650_Stop      ;I2C停止

;十位 寄存器地址6CH
LCALLTM1650_Start    ;发起I2C起始
MOV A,#6CH             ;TM1650十位寄存器地址
LCALL TM1650_Writebyte ;发送寄存器地址
MOV A,Thound         ;读取千位
JNZTE_SHOW         ;千位非0,十位强制显示
MOV A,Hundred          ;千位为0,读取百位
JNZTE_SHOW         ;百位非0,十位强制显示
MOV A,Ten            ;千、百为0,读取十位
JNZTE_SHOW         ;十位非0,十位显示
MOV DISP_TMP,#10       ;千百十全0,熄灭十位
SJMP TE_SEND         ;跳过显示赋值,直接发送
TE_SHOW:
MOV A,Ten            ;读取十位数字
MOV DISP_TMP,A         ;存入临时变量
TE_SEND:
MOV A,DISP_TMP         ;待输出值送入A
LCALL QUBIAO         ;查表输出段码/熄灭
LCALL TM1650_Stop      ;I2C停止

;个位 寄存器地址6EH,永远显示,无消隐逻辑
LCALLTM1650_Start    ;发起I2C起始
MOV A,#6EH             ;TM1650个位寄存器地址
LCALL TM1650_Writebyte ;发送寄存器地址
MOV A,One            ;直接读取个位数值
LCALL QUBIAO         ;查表输出段码
LCALL TM1650_Stop      ;I2C停止

DISP_EXIT:
POP DPL                ;恢复DPL
POP DPH                ;恢复DPH
POP ACC                ;恢复ACC
RET                  ;子程序返回

;=============================================
; QUBIAO:查表输出子程序
; 输入A:0~9输出对应段码;等于10直接输出00H熄灭数码管
;=============================================
QUBIAO:
CJNE A,#10,QUBIAO_NORMAL ;A不等于10,跳转到查表
MOV A,#00H               ;A等于10,输出00H,数码管熄灭
LCALL TM1650_Writebyte   ;发送熄灭数据
RET
QUBIAO_NORMAL:
MOVC A,@A+DPTR         ;查表取出对应数字的段码
LCALL TM1650_Writebyte   ;发送段码给TM1650
RET

;=============================================
; TM1650_Writebyte:模拟I2C发送1字节数据
; 输入参数:A寄存器存放待发送的1字节
;=============================================
TM1650_Writebyte:
MOV R6,#8            ;R6赋值8,一个字节共8bit,循环发送8次
WB1:
CLR CLK                ;CLK时钟引脚拉低,准备输出一位数据
RLC A                  ;累加器A带进位循环左移,最高位移入进位标志C
MOV DIO,C            ;把进位C电平输出到DIO数据引脚
SETB CLK               ;CLK拉高,TM1650上升沿采样DIO的数据
DJNZ R6,WB1            ;R6自减1,R6不等于0跳回WB1继续发送bit
CLR CLK                ;8位全部发送完成,拉低时钟线
SETB CLK               ;TM1650不需要应答,跳过应答等待,拉高时钟
RET

;=============================================
; TM1650_Start:I2C总线产生起始信号
; I2C规则:CLK高电平期间,DIO产生下降沿为起始条件
;=============================================
TM1650_Start:
SETB DIO               ;DIO数据线置高,总线空闲状态
SETB CLK               ;CLK时钟线置高,总线空闲状态
CLR DIO                ;CLK保持高,DIO拉低,产生下降沿,起始信号
CLR CLK                ;拉低CLK时钟,准备传输数据位
RET

;=============================================
; TM1650_Stop:I2C总线产生停止信号
; I2C规则:CLK高电平期间,DIO产生上升沿为停止条件
;=============================================
TM1650_Stop:
CLR CLK                ;先把CLK时钟拉低
CLR DIO                ;DIO数据线拉低
SETB CLK               ;CLK时钟拉高
SETB DIO               ;CLK保持高,DIO拉高,产生上升沿,停止信号
RET

;=============================================
; TAB:共阴极数码管七段段码表
; 顺序对应数字0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F
;=============================================
TAB:
DB 3FH               ;数字0的七段段码
DB 06H               ;数字1的七段段码
DB 5BH               ;数字2的七段段码
DB 4FH               ;数字3的七段段码
DB 66H               ;数字4的七段段码
DB 6DH               ;数字5的七段段码
DB 7DH               ;数字6的七段段码
DB 07H               ;数字7的七段段码
DB 7FH               ;数字8的七段段码
DB 6FH               ;数字9的七段段码
DB 00H               ;索引10,熄灭用
DB 77H               ;字母A的七段段码
DB 7CH               ;字母B的七段段码
DB 39H               ;字母C的七段段码
DB 5EH               ;字母D的七段段码
DB 79H               ;字母E的七段段码
DB 71H               ;字母F的七段段码

END                  ;程序结束

看完后觉得有帮助的可以打赏楼主,1块钱都可以,谢谢,有问题可以加QQ询问:3113509683(备注逆天PCB来的)

bidezhi7777 发表于 2026-9-2 06:42

billtest36 发表于 2026-9-2 07:28

感谢版主的分享

鼎盛电子 发表于 2026-9-2 08:02

谢谢分享

io357 发表于 2026-9-2 08:29

谢谢分享

x198956 发表于 2026-9-2 08:51

111111111111111111

Mr_Jiyang 发表于 2026-9-2 08:58

感谢分享

鼹鼠先生 发表于 2026-9-2 08:58

这个资料很不错,感谢分享,谢谢

竹青 发表于 2026-9-2 09:09

感谢分享

techlink81 发表于 2026-9-2 09:12

谢谢分享
页: [1] 2 3
查看完整版本: STC12C5A60S2驱动TM1650四位共阳数码管0-9999计数