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来的)
感谢版主的分享 谢谢分享 谢谢分享 111111111111111111 感谢分享 这个资料很不错,感谢分享,谢谢 感谢分享 谢谢分享
