1.实验效果
LED滚动字幕
2. 74HC595芯片
(1)使用74HC595芯片实现51单片机I/O口扩展
74HC595芯片具有串行输入并行输出功能,这样就可以让单片机以较少的引脚控制更多的LED灯
如上图:只需要在SER引脚配合时钟串行输入8位数据,就可以在右侧得到相应的并行输出的8位数据,从而将单片机的一个引脚扩展为8个引脚
此外9号接口是串行输出口,这让74HC595支持级联,可以一直扩展到16,24,32……
(2)74HC595原理
本次使用的是595芯片的输出状态,所以OE引脚接地,RC:复位引脚接P1.0,SC:时钟引脚接P1.1,SE:串行输入引脚P1.2
3.595芯片数据寄存代码(部分)
…………
MOV R2,#00H ;595寄存器(P1.2)查表
…………
TTT:
CLR P1.0
MOV R1,#00H ;循环计数(行,595移位寄存器赋值)
MOV DPTR,#TAP_ROW ;P1.2查表
MOV A,R2
MOVC A,@A+DPTR
MOV R0,A ;从表中取出595寄存器存储的数据
…………
LOOP:
INC R1 ;计数累加
CLR P1.1 ;P1.1时钟引脚,时钟方波起始状态
MOV A,R0 ;(A)<-(R0)
RRC A ; 带进位右移函数
MOV R0,A ;重新将右移后的数据给R0
JC SETB_1 ;判断移位后Cy得到的数据是否为1,为1跳转存1程序
SJMP CLR_0 ;为0跳转存0程序
SETB_1:
SETB P1.2 ;P1.2串行输送口,输出1
LCALL TIME_1MS ;调用延时1ms子程序
SETB P1.1 ;P1.1时钟上升沿595芯片存入数据 1
SJMP LUUP ;跳转判断右移次数
CLR_0:
CLR P1.2 ;P1.2输出0
LCALL TIME_1MS
SETB P1.1 ;存入数据 0
………………
3.字幕滚动思想
(1)编码表
字符的显示是靠动态刷新实现的,而且一次只能刷新8行,那么在刷新次数方向上无法做出改变,但是刷新用的编码表是可以改变的
那么在单个字符刷新程序外面再设置一个程序包含它,让他在单个字符持续刷新一定时间后改变它的编码表,就可以改变他在这个时间段内显示的字符,至于如何让它像字幕一样滚动起来,这在于编码表的数据刷新顺序
TAP_ROW:DB 80H,40H,20H,10H,08H,04H,02H,01H ;行点亮编码表
TAP_CUL:DB 0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,
00H,0DBH,0FDH,0B8H,056H,0BAH,056H,090H,0FFH,0FFH,
00H,0DBH,0FDH,0B8H,056H,0BAH,056H,090H,0FFH,0FFH,
0EBH,0EFH,000H,0EFH,0D5H,0D3H,0A6H,070H,0FFH,0FFH,
0BFH,0BFH,0BFH,0A3H,09DH,0BDH,0BDH,0BDH,0FFH,0FFH,
0C7H,0FBH,0C3H,0BBH,0BBH,0BAH,0C5H,0FFH,0FFH,0FFH,
087H,0BBH,0BBH,087H,0BFH,0BFH,0BFH,0BFH,0FFH,0FFH,
087H,0BBH,0BBH,087H,0BFH,0BFH,0BFH,0BFH,0FFH,0FFH,
0DBH,0DBH,0DBH,0E3H,0FBH,0FBH,0DBH,0E7H,0FFH,0FFH,
0FFH,0FFH,0FFH,0FFH,0FFH,0FFH ;列点亮编码表(药药龙happy)编码
(2)刷新框架
通过定时器计时判断从数据表第几行开始刷新,通过中断程序送刷新初值
…………
MAIN :
JB TF1,TF_1
…………
TF_1:
CLR TF1 ;清楚计时器1溢出位
INC R6 ;R6累加用于判断计时是否满0.6s,
CJNE R6,#0AH,UULL ;满0.6s开启一次定时中断,实现滚动一行LED屏幕
UULL:
JC LUO ;从程序开始字符显示时间小于0.6s,跳转赋值计时器初值再次计时
SJMP YUY ;字符显示时间达到0.6s跳转开启中断,并赋值计时器初值等待中断
LUO:
MOV TH1,#02H ;计时器赋初值
MOV TL1,#18H
SETB TR1 ;打开计时器,开始计时
LJMP TTT ;返回调用地址
YUY:
SETB EA ;开总总中断
SETB ET1 ;开定时器中断
LJMP TTT ;返回调用地址
TIME_1: ;定时器中断程序
PUSH ACC ;压栈ACC
PUSH PSW ;压栈状态字
CLR EA ;关总中断
CLR ET1 ;关定时器1中断
CLR TF1 ;清楚定时器1中断标志位
INC R7 ;R7累加,确定查表初始位
CJNE R7,#058H,UO ;###############改变字符数,R7的最大值
UO:
JC LO ;未循环遍历所有表格元素跳转继续遍历循环
MOV R7,#00H ;循环遍历完所有元素,清零R7从头开始循环
LO:
MOV TH1,#02H ;计时器初值赋值,60ms
MOV TL1,#18H
MOV R6,#00H
SETB TR1
POP PSW ;出栈程序状态字
POP ACC ;出栈Acc累加器
RETI
…………………
4.汇编程序
;###########################
;RC:复位引脚 P1.0
;SC:时钟引脚 P1.1
;SE:串行输入引脚P1.2
;R7控制显示字符数
;消隐思想:先送数——>后选通——>再延时——>再切断——>再延时——>最后跳转循环送数
;###########################
ORG 0000H
SJMP MA ;跳转主程序
ORG 001BH
LJMP TIME_1 ;跳转中断程序
MA:
MOV TMOD,#01H ;使用计时方式1
MOV R2,#00H ;595寄存器(P1.2)查表计数累加
MOV R7,#00H ;滚动屏显示累加位
MOV R6,#00H ;计时0.6s判断位
MOV R5,#00H ;p0查表初始位
CLR C
MOV TH1,#02H ;计时器初值60ms
MOV TL1,#18H
SETB TR1 ;开计时器
;#########################################单字符显示子程序
MAIN :
JB TF1,TF_1
TTT:
CLR P1.0
MOV R1,#00H ;循环计数(行,595移位寄存器赋值)
MOV DPTR,#TAP_ROW ;P1.2查表
MOV A,R2
MOVC A,@A+DPTR
MOV R0,A ;从表中取出595寄存器存储的数据
MOV DPTR,#TAP_CUL ;p0查表
MOV A,R5
MOVC A,@A+DPTR
MOV R3,A ;将查表得到的P0I/O数据给R3
INC R2 ;INC加一操作:累加
INC R5
LOOP:
INC R1 ;计数累加
CLR P1.1 ;P1.1时钟引脚,时钟方波起始状态
MOV A,R0 ;(A)<-(R0)
RRC A ; 带进位右移函数
MOV R0,A ;重新将右移后的数据给R0
JC SETB_1 ;判断移位后Cy得到的数据是否为1,为1跳转存1程序
SJMP CLR_0 ;为0跳转存0程序
SETB_1:
SETB P1.2 ;P1.2串行输送口,输出1
LCALL TIME_1MS ;调用延时1ms子程序
SETB P1.1 ;P1.1时钟上升沿595芯片存入数据 1
SJMP LUUP ;跳转判断右移次数
CLR_0:
CLR P1.2 ;P1.2输出0
LCALL TIME_1MS
SETB P1.1 ;存入数据 0
SJMP LUUP ;跳转判断右移次数
LUUP:
CJNE R1,#08H,SU ;判断右移和寄存次数是否满8次
SJMP SU ;右移和寄存次数等于8次复位
SU:
JC LOOP ;计数等于和大于8顺序执行,小于8循环
SETB P1.0 ;串行数据传输完毕清零寄存器
CJNE R2,#09H,SUU ;判断 是否查表超过7次,小于或大于7次跳转
SUU:
JC MM ;小于7次跳转初始化
MOV R2,#00H ;大于7次清零R2
MOV A,R7 ;将R7的值给R5,格式化P0查表初始值
MOV R5,A
MOV P0,#0FFH ;给P0口高电平,实现消隐操作
LCALL TIME_1MS
LJMP MAIN ;跳转循环主函数
MM:
MOV P0,R3 ;给p0赋值
;LCALL TIME_1S
LCALL TIME_10MS ;延时0.5ms
MOV P0,#0FFH ;断开p0消隐
LJMP MAIN ;跳转循环
;#########################################滚动屏刷新子程序
TF_1:
CLR TF1 ;清楚计时器1溢出位
INC R6 ;R6累加用于判断计时是否满0.6s,
CJNE R6,#0AH,UULL ;满0.6s开启一次定时中断,实现滚动一行LED屏幕
UULL:
JC LUO ;从程序开始字符显示时间小于0.6s,跳转赋值计时器初值再次计时
SJMP YUY ;字符显示时间达到0.6s跳转开启中断,并赋值计时器初值等待中断
LUO:
MOV TH1,#02H ;计时器赋初值
MOV TL1,#18H
SETB TR1 ;打开计时器,开始计时
LJMP TTT ;返回调用地址
YUY:
SETB EA ;开总总中断
SETB ET1 ;开定时器中断
LJMP TTT ;返回调用地址
TIME_1: ;定时器中断程序
PUSH ACC ;压栈ACC
PUSH PSW ;压栈状态字
CLR EA ;关总中断
CLR ET1 ;关定时器1中断
CLR TF1 ;清楚定时器1中断标志位
INC R7 ;R7累加,确定查表初始位
CJNE R7,#058H,UO ;###############改变字符数,R7的最大值
UO:
JC LO ;未循环遍历所有表格元素跳转继续遍历循环
MOV R7,#00H ;循环遍历完所有元素,清零R7从头开始循环
LO:
MOV TH1,#02H ;计时器初值赋值,60ms
MOV TL1,#18H
MOV R6,#00H
SETB TR1
POP PSW ;出栈程序状态字
POP ACC ;出栈Acc累加器
RETI
TIME_1MS: ;延时0.1MS程序
MOV TH0,#0FFH
MOV TL0,#09CH
SETB TR0
JNB TF0,$
CLR TF0
RET
TIME_10MS: ;延时0.2MS程序
MOV TH0,#0FFH
MOV TL0,#038H
SETB TR0
JNB TF0,$
CLR TF0
RET
TIME_1S: MOV R7,#20 ;延时0.5S子程序 ,调试阶段使用
DL1: MOV R6,#80
DL2: MOV R5,#248
DJNZ R5,$
DJNZ R6,DL2
DJNZ R7,DL1
RET
TAP_ROW:DB 80H,40H,20H,10H,08H,04H,02H,01H ;行点亮编码表
TAP_CUL:DB 0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,
00H,0DBH,0FDH,0B8H,056H,0BAH,056H,090H,0FFH,0FFH,
00H,0DBH,0FDH,0B8H,056H,0BAH,056H,090H,0FFH,0FFH,
0EBH,0EFH,000H,0EFH,0D5H,0D3H,0A6H,070H,0FFH,0FFH,
0BFH,0BFH,0BFH,0A3H,09DH,0BDH,0BDH,0BDH,0FFH,0FFH,
0C7H,0FBH,0C3H,0BBH,0BBH,0BAH,0C5H,0FFH,0FFH,0FFH,
087H,0BBH,0BBH,087H,0BFH,0BFH,0BFH,0BFH,0FFH,0FFH,
087H,0BBH,0BBH,087H,0BFH,0BFH,0BFH,0BFH,0FFH,0FFH,
0DBH,0DBH,0DBH,0E3H,0FBH,0FBH,0DBH,0E7H,0FFH,0FFH,
0FFH,0FFH,0FFH,0FFH,0FFH,0FFH ;列点亮编码表
END