单片机大作业----16*16点阵LED点阵显示step3-plus

时间:2025-03-07 09:38:56
  • ;==================================
  • ;程序名:51单片机控制16*16LED点阵显示
  • ;作者: 呼啦啦
  • ;完成时间: 2019-6-10
  • ;step 3
  • ;完成功能:使用外部中断控制显示模式
  • ;==================================
  • ;============================================
  • ;基本功能介绍:
  • ;使用74HC154进行列选通,p2.0-p2.3作为地址输入口
  • ;一共有16个输出位,分别控制16
  • ;p0口作为上8行字形码输出口
  • ;p1口作为下8行字形码输出口
  • ;============================================
  • ;==========
  • ;常量表
  • ;常量表报错
  • ;不知道为什么
  • ;==========
  • ;===========
  • ;中断向量表
  • ;===========
  • ORG 0000H
  • SJMP MAIN ;跳转到主程序
  • ORG 0003H ;外中断0
  • SJMP EXP0
  • ORG 000BH ;定时器0
  • SJMP ETP0
  • ORG 0013H ;外中断1
  • SJMP EXP1
  • ORG 001BH ;定时器1
  • RETI
  • ORG 0023H ;串行口中断
  • RETI
  • ;==========
  • ;初始化程序
  • ;==========
  • MAIN: MOV SP, #5FH ;初始化堆栈指针
  • MOV IE, #85H ;1000 0101B,开外部中断01
  • SETB EX0 ;开中断
  • SETB EX1
  • SETB ET0 ;开定时器0中断
  • SETB TR0
  • SETB PX0 ;设置外部中断优先级为高优先级
  • SETB PX1
  • MOV TMOD, #10H ;设置工作模式为1,16位计数模式
  • MOV TH0, #00H ;计数64k*1us进行一次中断
  • MOV TH1, #00H ;64ms也就是0.064
  • MOV R5, #1
  • M1: DJNZ R5, M2
  • SETB ET0 ;开定时器0中断
  • MOV R5, #1
  • M2: ACALL DISPLAY ;不断显示初始开机画面
  • SJMP M1
  • ;================
  • ;定时器0中断程序
  • ;================
  • ETP0: PUSH 07H
  • CLR ET0 ;关定时器0中断
  • MOV R7, #1 ;*****这里控制显示的次数******
  • ET11: ACALL DISPLAYET
  • DJNZ R7, ET11
  • MOV TH0, #00H ;计数64k*1us进行一次中断
  • MOV TH1, #00H ;64ms也就是0.064
  • POP 07H
  • RETI
  • ;================
  • ;外部中断0中断程序
  • ;控制汉字滚动显示
  • ;=================
  • EXP0: CLR ET0
  • E1: MOV R7, #4H ;****这里控制要显示的字数****
  • MOV R6, #00H ;这是DPTR的偏移量,这个值不需要修改
  • E2: ACALL DISPLAY1
  • DJNZ R7, E2
  • SETB ET0
  • RETI
  • ;=================
  • ;外部中断1中断程序
  • ;控制汉字闪烁显示
  • ;================
  • EXP1: CLR ET0
  • H1: MOV R7, #4H ;****这里控制要显示的字数****
  • H2: ACALL DISPLAY2
  • DJNZ R7, H2
  • SETB ET0
  • RETI
  • ;===============================
  • ;显示主程序
  • ;显存为30H开始的32个内存单元
  • ;P0口控制低8位字形码
  • ;P1口控制高8位字形码
  • ;P2口控制字位码
  • ;P2.7口为高电平的时候不选通任何一列
  • ;先送字形码,后送字位码
  • ;然后调用延时子程序后再显示下一列
  • ;显示完一个字后
  • ;================================
  • ;这是定时器0触发中断时进入的显示程序
  • DISPLAYET: ACALL GET0 ;先将下一帧送入显存
  • PUSH 00H
  • PUSH 01H
  • PUSH 02H
  • PUSH 03H
  • PUSH 04H
  • MOV R4, #20H ;****这里控制循环次数****
  • ;初始化部分
  • D001: MOV R0, #30H ;用作上半部分显示内容指针
  • MOV R1, #30H+10H;用作下半部分显示内容指针
  • MOV R2, #10H ;进行显示内容控制
  • MOV R3, #00H ;用作字位码
  • CLR A
  • MOV P0, A
  • MOV P1, A
  • SETB P2.7
  • ;显示部分
  • D002: MOV P0, @R0 ;将低8位字形码送入P0
  • MOV P1, @R1 ;将高8位字形码送入P1
  • MOV P2, R3 ;将字位码送入P2
  • CLR P2.7 ;将P2.7口置0表示可以显示
  • ACALL DELAY5 ;延时0.5ms
  • SETB P2.7 ;关闭显示
  • INC R0
  • INC R1
  • INC R3
  • DJNZ R2, D002
  • DJNZ R4, D001
  • POP 04H
  • POP 03H
  • POP 02H
  • POP 01H
  • POP 00H
  • RET
  • ;这是没有触发中断时的显示
  • DISPLAY:
  • ACALL GET ;先将下一帧送入显存
  • PUSH 00H
  • PUSH 01H
  • PUSH 02H
  • PUSH 03H
  • PUSH 04H
  • MOV R4, #20H ;****这里控制循环次数****
  • ;初始化部分
  • D01: MOV R0, #30H ;用作上半部分显示内容指针
  • MOV R1, #30H+10H;用作下半部分显示内容指针
  • MOV R2, #10H ;进行显示内容控制
  • MOV R3, #00H ;用作字位码
  • CLR A
  • MOV P0, A
  • MOV P1, A
  • SETB P2.7
  • ;显示部分
  • D02: MOV P0, @R0 ;将低8位字形码送入P0
  • MOV P1, @R1 ;将高8位字形码送入P1
  • MOV P2, R3 ;将字位码送入P2
  • CLR P2.7 ;将P2.7口置0表示可以显示
  • ACALL DELAY5 ;延时0.5ms
  • SETB P2.7 ;关闭显示
  • INC R0
  • INC R1
  • INC R3
  • DJNZ R2, D02
  • DJNZ R4, D01
  • POP 04H
  • POP 03H
  • POP 02H
  • POP 01H
  • POP 00H
  • RET
  • ;这是滚动显示
  • DISPLAY1:
  • PUSH 00H
  • PUSH 01H
  • PUSH 02H
  • PUSH 03H
  • PUSH 04H
  • PUSH 05H
  • MOV R5, #10H ;一个字显示16次能显示完,每次都向左偏移一个单位
  • D13: ACALL GET1 ;先将下一帧送入显存
  • MOV R4, #10H ;****这里控制循环次数,也就是一个字显示多久****
  • ;初始化部分
  • D11: MOV R0, #30H ;用作上半部分显示内容指针
  • MOV R1, #30H+10H;用作下半部分显示内容指针
  • MOV R2, #10H ;进行显示内容控制
  • MOV R3, #00H ;用作字位码
  • CLR A
  • MOV P0, A
  • MOV P1, A
  • SETB P2.7
  • ;显示部分
  • D12: MOV P0, @R0 ;将低8位字形码送入P0
  • MOV P1, @R1 ;将高8位字形码送入P1
  • MOV P2, R3 ;将字位码送入P2
  • CLR P2.7 ;将P2.7口置0表示可以显示
  • ACALL DELAY5 ;延时0.5ms
  • SETB P2.7 ;关闭显示
  • INC R0
  • INC R1
  • INC R3
  • DJNZ R2, D12
  • DJNZ R4, D11
  • DJNZ R5, D13 ;控制一个字显示16次,每次偏移一个单位
  • POP 05H
  • POP 04H
  • POP 03H
  • POP 02H
  • POP 01H
  • POP 00H
  • RET
  • ;这是闪烁显示程序
  • DISPLAY2: ACALL GET2 ;先将下一帧送入显存
  • PUSH 00H
  • PUSH 01H
  • PUSH 02H
  • PUSH 03H
  • PUSH 04H
  • MOV R4, #20H ;****这里控制循环次数****
  • ;初始化部分
  • D21: MOV R0, #30H ;用作上半部分显示内容指针
  • MOV R1, #30H+10H;用作下半部分显示内容指针
  • MOV R2, #10H ;进行显示内容控制
  • MOV R3, #00H ;用作字位码
  • CLR A
  • MOV P0, A
  • MOV P1, A
  • SETB P2.7
  • ;显示部分
  • D22: MOV P0, @R0 ;将低8位字形码送入P0
  • MOV P1, @R1 ;将高8位字形码送入P1
  • MOV P2, R3 ;将字位码送入P2
  • CLR P2.7 ;将P2.7口置0表示可以显示
  • ACALL DELAY5 ;延时0.5ms
  • SETB P2.7 ;关闭显示
  • INC R0
  • INC R1
  • INC R3
  • DJNZ R2, D22
  • DJNZ R4, D21
  • POP 04H
  • POP 03H
  • POP 02H
  • POP 01H
  • POP 00H
  • RET
  • ;================================
  • ;子程序名:送数子程序
  • ;将字形码送入30H开始的32个内存单元
  • ;实现滚动只要是修改这部分代码
  • ;用到R1 R2 A DPTR
  • ;================================
  • ;触发了定时器中断的时候的送数
  • GET0: PUSH 01H ;将R1的值入栈
  • PUSH 02H ;将R2的值入栈
  • MOV R1, #30H ;指向显存的起始地址
  • MOV R2, #20H ;控制送数个数
  • MOV DPTR, #INIT0
  • G001: CLR A
  • MOVC A, @A+DPTR
  • MOV @R1, A
  • INC DPTR
  • INC R1
  • DJNZ R2, G001
  • POP 02H
  • POP 01H
  • RET
  • ;没有触发中断时候的送数
  • GET: PUSH 01H ;将R1的值入栈
  • PUSH 02H ;将R2的值入栈
  • MOV R1, #30H ;指向显存的起始地址
  • MOV R2, #20H ;控制送数个数
  • MOV DPTR, #INIT
  • G01: CLR A
  • MOVC A, @A+DPTR
  • MOV @R1, A
  • INC DPTR
  • INC R1
  • DJNZ R2, G01
  • POP 02H
  • POP 01H
  • RET
  • ;滚动显示送数
  • GET1: PUSH 01H ;将R1的值入栈
  • PUSH 02H ;将R2的值入栈
  • PUSH 03H
  • ;先送上16个字节
  • MOV R1, #30H ;指向显存的起始地址
  • MOV R2, #10H ;控制送数个数
  • MOV DPTR, #TAB1 ;每一帧都比上一帧偏移一个单位
  • PUSH 06H
  • I11: INC DPTR ;加上偏移量
  • DJNZ R6, I11
  • POP 06H
  • G11: CLR A
  • MOVC A, @A+DPTR
  • MOV @R1, A
  • INC DPTR
  • INC R1
  • DJNZ R2, G11
  • ;接着送下16字节
  • MOV R2, #10H ;控制送数个数
  • MOV DPTR, #TAB2
  • PUSH 06H
  • I12: INC DPTR ;加上偏移量
  • DJNZ R6, I12
  • POP 06H
  • G12: CLR A
  • MOVC A, @A+DPTR
  • MOV @R1, A
  • INC DPTR
  • INC R1
  • DJNZ R2, G12
  • ;完成出栈后返回
  • POP 03H
  • POP 02H
  • POP 01H
  • INC R6
  • RET
  • ;这是闪烁显示送数
  • GET2: PUSH 01H ;将R1的值入栈
  • PUSH 02H ;将R2的值入栈
  • MOV R1, #30H ;指向显存的起始地址
  • MOV R2, #20H ;控制送数个数
  • G21: CLR A
  • MOVC A, @A+DPTR
  • MOV @R1, A
  • INC DPTR
  • INC R1
  • DJNZ R2, G21
  • POP 02H
  • POP 01H
  • RET
  • ;=============================
  • ;子程序名:延时约0.5ms
  • ;51单片机频率为12MHz
  • ;时钟周期为1/12M s
  • ;一个机器周期等于12个时钟周期
  • ;所以一个机器周期为1us
  • ;想要延时5ms就需要执行500条指令
  • ;需要修改延时时间只要修改R7和R6即可
  • ;=============================
  • DELAY5: PUSH 07H
  • PUSH 06H
  • MOV R6, #2
  • LAB1: MOV R7, #250
  • LAB2: DJNZ R7, LAB2
  • DJNZ R6, LAB1
  • POP 06H
  • POP 07H
  • RET ;子程序返回
  • ;================================
  • ;字位码表,用于控制列选通
  • ;只有选通的那一列是低电平
  • ;其他列都是高电平
  • ;这些数值都要送入P2口进行字位选通信号
  • ;=================================
  • ;字位码一直是从0-16,所以不用存了
  • ;=============
  • ;这里储存字形码
  • ;=============
  • ORG 1000H
  • ;一开始屏幕一半亮一半暗
  • INIT: db 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH
  • db 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH
  • db 00H, 00H, 00H, 00H, 00H, 00H, 00H, 00H
  • db 00H, 00H, 00H, 00H, 00H, 00H, 00H, 00H
  • ;触发定时器0中断的时候的显示内容
  • INIT0: db 00H, 00H, 00H, 00H, 00H, 00H, 00H, 00H
  • db 00H, 00H, 00H, 00H, 00H, 00H, 00H, 00H
  • db 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH
  • db 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH
  • ;这是闪烁显示
  • TAB: db 08h, 28h, 48h, 88h, 68h, 18h, 00h,0FCh ;"鸡"
  • db 06h, 15h, 44h, 84h, 7Eh, 04h, 00h, 00h
  • db 10h, 08h, 06h, 01h, 02h, 14h, 10h, 13h
  • db 12h, 12h, 1Ah, 52h, 82h, 7Fh, 02h, 00h
  • db 40h, 20h,0F8h, 07h, 40h, 20h, 18h, 0Fh ;"你"
  • db 08h,0C8h, 08h, 08h, 28h, 18h, 00h, 00h
  • db 00h, 00h,0FFh, 00h, 00h, 08h, 04h, 43h
  • db 80h, 7Fh, 00h, 01h, 06h, 0Ch, 00h, 00h
  • db 20h, 20h, 20h, 20h, 20h, 20h, 20h,0FFh ;"太"
  • db 20h, 20h, 20h, 20h, 20h, 30h, 20h, 00h
  • db 40h, 40h, 20h, 20h, 10h, 0Ch, 0Bh, 30h
  • db 03h, 0Ch, 10h, 10h, 20h, 60h, 20h, 00h
  • db 80h, 88h,0A8h,0A8h,0A9h,0AAh,0AEh,0F8h ;"美"
  • db 0ACh,0AAh,0ABh,0A8h,0ACh, 88h, 80h, 00h
  • db 80h, 84h, 84h, 44h, 44h, 24h, 14h, 0Fh
  • db 14h, 24h, 24h, 44h, 46h,0C4h, 40h, 00h
  • ;这是滚动显示
  • ;这是上半部分
  • TAB1: db 08h, 28h, 48h, 88h, 68h, 18h, 00h,0FCh ;"鸡"
  • db 06h, 15h, 44h, 84h, 7Eh, 04h, 00h, 00h
  • db 40h, 20h,0F8h, 07h, 40h, 20h, 18h, 0Fh ;"你"
  • db 08h,0C8h, 08h, 08h, 28h, 18h, 00h, 00h
  • db 20h, 20h, 20h, 20h, 20h, 20h, 20h,0FFh ;"太"
  • db 20h, 20h, 20h, 20h, 20h, 30h, 20h, 00h
  • db 80h, 88h,0A8h,0A8h,0A9h,0AAh,0AEh,0F8h ;"美"
  • db 0ACh,0AAh,0ABh,0A8h,0ACh, 88h, 80h, 00h
  • ;这是中间需要预留的一部分
  • DB 00H, 00H, 00H, 00H, 00H, 00H, 00H, 00H
  • DB 00H, 00H, 00H, 00H, 00H, 00H, 00H, 00H
  • ;这是下半部分
  • TAB2: db 10h, 08h, 06h, 01h, 02h, 14h, 10h, 13h ;"鸡"
  • db 12h, 12h, 1Ah, 52h, 82h, 7Fh, 02h, 00h
  • db 00h, 00h,0FFh, 00h, 00h, 08h, 04h, 43h ;"你"
  • db 80h, 7Fh, 00h, 01h, 06h, 0Ch, 00h, 00h
  • db 40h, 40h, 20h, 20h, 10h, 0Ch, 0Bh, 30h ;"太"
  • db 03h, 0Ch, 10h, 10h, 20h, 60h, 20h, 00h
  • db 80h, 84h, 84h, 44h, 44h, 24h, 14h, 0Fh ;"美"
  • db 14h, 24h, 24h, 44h, 46h,0C4h, 40h, 00h
  • END