LED显示屏驱动程序 几年前本人得到一块双色LED显示屏,因为没有控制器,所以对显示屏的工作原理进行了一番研究,利用手头上的元件,搭了一块电路板,编写了一段程序就放置一边了,这几天有时间,把原来的89C51汇编程序改了一下,改为AT89C2051和STC11F04E单片机能用的程序,放到博客上希望有兴趣的同行可以参考一下。下面是显示效果图:  下面是接口电路板图:

下面是电路原理图:

工作原理:这块显示屏是分为上下共32行LED点阵,水平有4块16*16点阵,所以能显示16*16点阵8个汉字。工作原理是用74ls138做为行扫描,列用74ls595控制,当138扫描到某一行时,595决定哪一列该亮,就这样快速扫描,就形成了图像了。参见下图: 以单色单元板为例走线方式如下图:

各信号走向如下:
l JP1排针16脚信号A->74HC245的第2脚(信号放大)->74HC245的第18脚->74HC138的第1脚->JP2排针16脚 l JP1排针15脚信号B->74HC245的第3脚(信号放大)->74HC245的第17脚->74HC138的第2脚->JP2排针15脚 l JP1排针1脚信号OE->74HC245的第4脚(信号放大)->74HC245的第16脚->74HC04D的第1脚->74HC04D的2脚->①74HC138的第5脚->②74HC04D的3脚->74HC04D的4脚->JP2排针1脚 l JP1排针11脚信号R->74HC245的第9脚(信号放大)->74HC245的第11脚->最左上角74HC595-1的第14脚->74HC595-1的9脚->74HC595-2的14脚->74HC595-2的9脚->最右下角74HC595-16的14脚->74HC595-16的9脚->JP2排针11脚
我现在用的是双色板,JP1各端口含义如下:

ABCD是显示屏电路板上的74LS138地址译码端, 单片机寄存器R3控制行扫描,当R3从00000000到00010000增加时ABCD的变化给138译码,当R3=0FH时正好扫描16行,当进位到10时扫描结束,OE是138的片选使能端,低电平有效。G1,G2是给595送绿色数据,R1R2是给595送红色数据的,ST是595数据锁存脉冲,SC是595时钟输入端。所有11个接线端都要通过74HC244总线驱动器接入。正常工作时因为按行扫描,首先扫描第一行和第17行同时进行,依次扫描到第16行和32行结束,所以送数据时,要把“黑龙江省哈尔滨市”8个汉字分成上面4个和下面4个,首先取“黑”字的16*16点阵数据的第一行第一个字节(一个汉字32个字节)存入单片机寄存器R6中,再取“哈” 字的16*16点阵数据的第一行第一个字节存入单片机寄存器R4中,调用送字节子程序送出到595中,接下来再取“黑”字的16*16点阵数据的第一行第二个字节存入单片机寄存器R6中,接着取“哈” 字的16*16点阵数据的第一行第二个字节存入单片机寄存器R4中,调用送字节子程序送出到595中,如此共取8次,用R2控制,这样就扫描完了第一行和第17行,用R3控制ABCD共扫描16行(因为一次扫描2行)就完成一屏的数据显示。为了配合这种扫描方式,8个汉字的点阵数据要进行重新排列才行,这在后续的程序中再说。 下面是51单片机汇编语言代码,主要由显示程序和送字节数据程序2段程序组成:
ORG 0000H
AJMPKS ;显示绿色黑龙江省哈尔滨市,11.0592MHZ,STC11F04E单片机
ORG 0003H
RETI
ORG 000BH
; LJMP 0C00H RETI
ORG 001BH
RETI
ORG 0023H
;AJMPS ;接收数据转S
A1 EQU P1.0 ;P1.0=A 接2针
B1 EQU P1.1 ;P1.1=B 接4针
C1 EQU P1.2 ;P1.2=C 接6针
D1 EQU P1.3 ;P1.3=D 接8针
G1 EQU 0B3H ;数据输出G1=B4
G2 EQU 0B7H ;数据输出 G2=B5
STB EQU 0B2H ;595数据锁存脉冲=L 12脚
SCK EQU 0B4H ;595时钟输入=S 11脚
R11 EQU 0B0H ;改为81,R22改为80,上下显示颠倒
R22 EQU 0B1H
EN EQU 0B5H ;138片选,行输出使NENG
DELBUF EQU 7FH
WDT_CONTR EQU 0C1H
AUX EQU 0A2H ;
KS: MOVSP,#65H ;设堆栈指针
MOV SCon,#50h; 方式1,REN=1.SM0,SM1,SM2,REN,TB8,RB8,TI,RI
MOV TMOD,#21H;波特率发生器T1工作在模式2上
MOV TH1,#0FDH;预置初值(按照波特率9600BPS预置初值) 11.0592=9600=FD
MOV TL1,#0FDH;
MOV TH0,#88H ;8800=12t,7000=stc1t
MOV TL0, #00H
ORL IE, #92H ;EA=1,ES=1;ET0=1
SETBPS ;串口中断优先
SETBTR1 ;启动定时器1
MOV WDT_CONTR ,#27H;;;;;;看门狗设置使能
Q: MOV A,#0;FFH
MOVR2,#64D ;清数据区
MOV R0,#20H
QING: MOV@R0,A ;清数据区
INC R0
DJNZ R2,QING
Q1: SETB G1
SETBG2 ;G1,G2送数显示绿色
SETB R11
SETBR22 ;R11R22送数显示红色
T1: MOVR3,#00H ;行扫描 R3控制行数从00000000到00010000,ABCD的变化给138译码0F扫描16行,当10时扫描结束
MOV DPTR , #0500H ;取数字
TZ: MOV R2, #8 ;送一行8个汉字
SETBEN ;138片选,行输出使能
ZJ1: CLRA
MOVC A, @A+DPTR ;16*16点阵,每行显示4个汉字,32条水平线,(1个汉字占16条水平线)2行显示8个汉字,所以先取第一行的一个字节,显示半个汉字(黑)
CPL A ;再跳过8个字节(4个汉字)取第二行1个字节数据(哈)
MOV R6,A
INC DPTR
CLR A
MOVC A, @A+DPTR
CPL A
MOV R4,A
ACALLBIN ;BIN2显示绿色
INC DPTR
DJNZ R2,ZJ1
SETB STB
CALL SDELAY
CLR STB
MOVA,R3 ;送138地址ABCD
MOVP1,A ;P2.0-P2.3=ABCD
INC R3
MOV A,R3
XRLA,#10H ;00-08是前8行,08-10H是后8行;
JNZTZ ;送前16行
MOV WDT_CONTR ,#17H;喂狗CLREN
AJMP T1
BIN: MOV R5, #08H ;往G1G2,或R11R22中写一个字节数据
BIN1: RLC A
; MOV R11, C ;写上半屏红色
MOV G1,C ;写上半屏红色
MOV R4,A
MOV A,R6
RLC A
; MOV R22,C ;下半屏红色
MOV G2,C ;下半屏绿色
MOV R6,A
MOV A,R4
SETB SCK
CALL SDELAY
CLR SCK
DJNZ R5, BIN1
RET
SDELAY: MOV DELBUF, #8D
SDEL1: NOP
NOP
DJNZ DELBUF, SDEL1
RET
ORG0500h ;黑龙江省哈尔滨市
DB00H,00H,08H,40H,02H,08H,00H,00H,40H,00H,00H,80H,01H,02H,00H,00H
DB3FH,00H,0FCH,40H,02H,0CH,40H,00H,30H,40H,08H,40H,09H,01H,20H,00H
DB21H,08H,08H,0A0H,02H,08H,20H,08H,17H,2FH,0FCH,0FEH,09H,00H,10H,04H
DB31H,7CH,28H,0A0H,02H,1FH,04H,0FCH,00H,28H,40H,02H,11H,0FFH,0CH,0FEH
DB2DH,49H,38H,10H,0FFH,20H,0FEH,08H,80H,10H,40H,64H,11H,01H,24H,00H,25H
DB49H,48H,08H,02H,41H,80H,10H,60H,83H,40H,80H,20H,01H,0C0H,08H,21H,4AH
DB08H,0EH,02H,81H,88H,00H,20H,52H,40H,10H,03H,3FH,00H,0FCH,3FH,4DH,0F8H
DB0F4H,04H,01H,88H,00H,08H,13H,40H,0F8H,0CH,21H,08H,08H,01H,48H,00H,00H
DB04H,09H,90H,40H,10H,12H,40H,20H,3FH,21H,0FCH,08H,7FH,48H,0FCH,08H,04H
DB09H,0A0H,20H,20H,22H,40H,20H,0C8H,21H,08H,08H,01H,4BH,00H,0FCH,08H,11H
DB0C0H,10H,0E0H,0E2H,40H,24H,0FH,21H,0F8H,08H,0FFH,7AH,0FEH,08H,08H,11H,82H
DB18H,20H,3FH,40H,0FEH,08H,21H,08H,08H,00H,4AH,00H,08H,11H,21H,82H,08H,20H
DB20H,44H,00H,0FH,21H,0F8H,28H,28H,02H,90H,08H,16H,01H,82H,00H,2FH,23H,0FEH
DB20H,08H,21H,08H,10H,24H,03H,4CH,0F8H,20H,05H,7EH,00H,20H,22H,00H,18H,0FH
DB01H,0F8H,00H,44H,02H,44H,08H,40H,02H,00H,00H,20H,24H,00H,08H,08H,01H,08H,00H
END
获取汉字点阵数据的VB程序
新建一个vb工程,新建桌面如下图:

在Form1上放置4个文本框,6个命令按钮,5个标签Label,一个下拉框ComboBox,分别把命令按钮的caption改成“获取汉字点阵信息”,“清空EEPROM”,“发送数据”,“读EEPROM”,“读时钟”,”修改时钟“。把4个Textbox的Text清空。在“工程”菜单下,选部件,如下图:

引入串口通信控件,如下图:

然后把 拉到桌面上,就可以应用vb自带的串口通信部件了。
下面把代码复制到工程代码区中:
Private Sub Combo1_Click()
On Error Resume Next
Label4.Caption = 8 ' Combo1.Text
MSComm1.CommPort = Right(Combo1.Text,1)
MSComm1.Settings = "9600,n,8,1"
If MSComm1.PortOpen = False Then MSComm1.PortOpen= True
MSComm1.InputLen = 0
MSComm1.RThreshold = 1
MSComm1.SThreshold = 0
MSComm1.InputMode = comInputModeBinary 'comInputModeText
MSComm1.InBufferSize = 2048
MSComm1.OutBufferSize = 2048
MSComm1.InBufferCount = 0
MSComm1.OutBufferCount = 0
Label4.Caption = "串口号:" &MSComm1.CommPort
End Sub
Private Sub Command1_Click()
Dim zf$, q$, w$, X, zf1, p, o,l, cc, B, s, Y
Dim m, k, j, i, c1, c2, c3, c4,c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16
Dim S11, s12, s13, s14, s15,s16, SS
Dim C(32), a(32) AsString
Dim a1 As Byte
On Error Resume Next
zf$ = Text1.Text
X = Len(zf$)
For j = 1 To X
zf1 = Hex(Asc(Mid$(zf$, j, 1)))
If zf1 <"A0" Then
q$ = "&H" & Left(zf1, 1)
w$ = "&H" & Right(zf1, 1)
q = Val(q$)
w = Val(w$)
m = (q * 16 + w) * 16
k = 16
Open "G:\单片机\LED显示屏\汉字点阵\asc16" ForBinary As #1
Else
q$ = "&H" & Left(zf1, 2)
w$ = "&h" & Right(zf1, 2)
q = Val(q$) - 160
w = Val(w$) - 160
m = ((q - 1) * 94 + w - 1) * 32
k = 32
Open "G:\单片机\LED显示屏\汉字点阵\hzk16" ForBinary As #1
End If
or i = 1 To k
m = m + 1
Seek #1, m
Get #1, m, a1
B = a1
For l = 1 To 8'把一个字节的十六进制数转换二进制数
cc =B / 2 '被2除,余数为1
If B/ 2 = Int(B / 2) Then
s =0 & s
Else
s =1 & s
EndIf
B =Int(cc)
Next l
C(i) = s
'Text2.Text = Text2.Text + C(i)
If k = 32 Then
c1 = C(1) + C(2): c2 = C(3) + C(4)'16*16点阵,每个字每行2个字节相加。
c3 = C(5) + C(6): c4 = C(7) + C(8)
c5 = C(9) + C(10): c6 = C(11) + C(12)
c7 = C(13) + C(14): c8 = C(15) + C(16)
c9 = C(17) + C(18): c10 = C(19) + C(20)
c11 = C(21) + C(22): c12 = C(23) +C(24)
c13 = C(25) + C(26): c14 = C(27) +C(28)
c15 = C(29) + C(30): c16 = C(31) +C(32)
a(1) = C(1)
a(2) = C(2)
a(3) = C(3)
a(4) = C(4)
a(5) = C(5)
a(6) = C(6)
a(7) = C(7)
a(8) = C(8)
a(9) = C(9)
a(10) = C(10)
a(11) = C(11)
a(12) = C(12)
a(13) = C(13)
a(14) = C(14)
a(15) = C(15)
a(16) = C(16)
a(17) = C(17)
a(18) = C(18)
a(19) = C(19)
a(20) = C(20)
a(21) = C(21)
a(22) = C(22)
a(23) = C(23)
a(24) = C(24)
a(25) = C(25)
a(26) = C(26)
a(27) = C(27)
a(28) = C(28)
a(29) = C(29)
a(30) = C(30)
a(31) = C(31)
a(32) = C(32)
Else
c1 = C(1): c2 = C(2)
c3 = C(3): c4 = C(4)
c5 = C(5): c6 = C(6)
c7 = C(7): c8 = C(8)
c9 = C(9): c10 = C(10)
c11 = C(11): c12 = C(12)
c13 = C(13): c14 = C(14)
c15 = C(15): c16 = C(16)
'源码,没经过处理
a(1) = C(1)
a(2) = C(2)
a(3) = C(3)
a(4) = C(4)
a(5) = C(5)
a(6) = C(6)
a(7) = C(7)
a(8) = C(8)
a(9) = C(9)
a(10) = C(10)
a(11) = C(11)
a(12) = C(12)
a(13) = C(13)
a(14) = C(14)
a(15) = C(15)
a(16) = C(16)
End If
s = ""
Next i
Close
l = 0: o = 0
Forl = 1 To k '32
p = a(l)
For o = 1 To 8
Y = Mid(p, o, 1)
Y = "&H" & Y
Y = Val(Y) * 2 ^ (8 - o)
cc = cc + Y
Next o
a(l) = Hex(cc)
If Len(a(l)) = 1 Then a(l) = "0" & a(l)
' s = s +a(l) & "H,"
s =s + a(l) & ","
cc = 0
Nextl
s15 = s15 + s
'Text1.Text = Text1.Text + s15
'Exit Sub
o = 0: cc = 0: p = 0: l = 0: Y = 0: s =0
Next j
k = Len(s15)
Text2.Text = s15 + "字符数=" & k& Chr(13) + Chr(10)
'下面对多字节(8)个点阵汉字进行处理,行扫描
Dim Bq() As String
Bq = Split(s15, ",") '分割为数组
l = X * 32 / 2
s1 = ""
For i = 0 To 15 ' Step 4
c1 = "H,"
For j = 0 To l - 1 Step 32
s1 = Bq(2 * i + j) + c1 + Bq(2 * i + l + j) + c1 +Bq(2 * i + j + 1) + c1 + Bq(2 * i + l + j + 1) + c1
Text3.Text = Text3.Text + s1 '加 l = X * 32 /2是把8个汉字分成一半,同时显示上面4个汉字和下面4个汉字,先取上面一个字节,再取下面一个字节,加32是取第二个汉字,加64是取地个汉字,加96是取第4个汉字,一次取完一行
Next j
For j = 0 To l - 1 Step 32
s2 = Bq(2 * i + j) + Bq(2 * i + l + j) + Bq(2 * i+ j + 1) + Bq(2 * i + l + j + 1)
Text4.Text = Text4.Text + s2
Next j
Next i
End Sub
Private Sub Command2_Click()
If MSComm1.PortOpen = False Then MSComm1.PortOpen= True
MSComm1.Output = "66"
Text3.Text = "66OK"
MSComm1.PortOpen = False
End Sub
Private Sub Command3_Click()
Dim s1, s2, s3 As String
If MSComm1.PortOpen = False Then MSComm1.PortOpen= True
zf$ = Text1.Text
X = Len(zf$)
If X = 16 Then X = "10"
If X = 24 Then X = "18"
s1 = Text4.Text
If X < 10 Then X = "0" & X
s2 = Mid$(s1, 1, 512)
MSComm1.Output = X & s2
s3 = Mid$(s1, 513, 512)
MSComm1.Output = s3
S4 = Mid$(s1, 1025, 512)
MSComm1.Output = S4
Text3.Text = X & s2 & s3 &S4
MSComm1.PortOpen = False
End Sub
Private Sub Command4_Click()
If MSComm1.PortOpen = False Then MSComm1.PortOpen= True
MSComm1.Output = "77"
End Sub
Private Sub Command5_Click()
MSComm1.Output = "99"
End Sub
Private Sub Command6_Click()
sj = Format(Now, "yyyy年mm月dd日hh时mm分ss秒")
w = Weekday(Date) - 1
xq = "0" & w
sj1 = Mid(sj, 3, 2) + Mid(sj, 6, 2) + Mid(sj, 9,2) & xq
sj2 = Mid(sj, 12, 2) + Mid(sj, 15, 2) + Mid(sj,18, 2)
Text3.Text = "88" + sj1 + sj2
MSComm1.Output = "88" + sj1 + sj2
End Sub
Private Sub Form_Load()
Text1.Text = "黑龙江省哈尔滨市"'黑龙江省哈尔滨市道里区红军街一号
MSComm1.Settings = "9600,n,8,1"
MSComm1.InputMode = comInputModeBinary
MSComm1.InputLen = 0
MSComm1.InBufferSize = 2048
MSComm1.OutBufferSize = 2048
MSComm1.RThreshold = 1 '
MSComm1.InBufferCount = 0
MSComm1.OutBufferCount = 0
MSComm1.PortOpen = True
End Sub
Private Sub MSComm1_OnComm()
Dim strBuff As String
Dim str() As Byte
Select Case MSComm1.CommEvent
Case comEvReceive
MSComm1.InputLen = 0
strBuff = MSComm1.Input
str() = strBuff
'接收数据处理为16进制
For i = 0 To UBound(str)
If Len(Hex(str(i))) = 1 Then
strData = strData & "0" &Hex(str(i))
Else
strData = strData & Hex(str(i))
End If
Next
Text3.Text = Text3.Text + strData
End Select
End Sub
点击工具栏上的启动按钮,如下图,看是否出错,能正常运行就大功告成。如果出错

可能是缺少HZK16,ASC16两个文件,或文件路径不正确,需要改动路径。文件目录如下图:可到我的网盘下载。(连接在我的前面文章中)

本程序有4个功能,在最上面的文本框中输入要获取的点阵汉字,可以是8个,16个(与显示屏对应),点击“获取汉字点阵信息”按钮,获得的数据如下图:

Text2中显示的是单个汉字的点阵信息,每32个字节是一个汉字,如00,08,3F,FC,21,08,31,28,2D,38,25,48,21,08,3F,F8,01,00,7F,FC,01,00,FF,FE,00,00,28,90,24,4C,44,44是“黑”字的点阵,接下来的是“龙”字的点阵02,00,02,40,02,20,02,04,FF,FE,02,80,02,88,04,88,04,90,04,A0,08,C0,08,82,11,82,16,82,20,7E,40,00,以此类推。
Text3中显示的是按汉字字符串“黑龙江省哈尔滨市”的1/2,相隔4个汉字分离出来的点阵信息,因为我用的显示屏每块是32*128的点阵,所以上下可以显示2行16*16的点阵,每行可以显示4个16*16的汉字,单片机程序是上下2行汉字同时扫描,所以要进行1/2汉字点阵分离。如果要扩充到2块显示屏,就可以显示16个汉字,如显示“黑龙江省哈尔滨市道里区红军街一号”,就需要从1和9个汉字同时扫描,相应的点阵信息要从第9个开始分离,再重新组合。为了便于贴到单片机程序中,加上了“,”号和“H”符号。
Text4中显示的与TEXT3中的内容一致,只不过去掉了“,”号和“H”符号,便于和单片机通信。
点击“清空EEPROM”按钮,功能是清空单片机STC11F04E中EEPROM的数据,刷新数据之前必须先清空。STC11F04E有1K字节的EEPROM,有2个扇区,每隔扇区512字节,地址是“0000—01FF”是第一扇区,“0200—03FF”是第二扇区。
点击“发送数据”按钮,是把Text4中的点阵数据通过串口发送到单片机STC11F04E中到EEPROM中,串口波特率是9600,应用时注意你自己微机的串口号,默认是“com8”。在串口发送数据时,会把汉字字符串的长度信息发送到EEPROM的“0000”单元中,便于单片机自动改变扫描长度。
点击“读EEPROM”按钮是读出单片机STC11F04E中的EEPROM数据。
点击“读时钟”可以读出时钟模块的日期和时间,如”16011801143533”的asii码“31363031313830313134353333”表示16年、1月18日、星期一、14点35分33秒。
点击“修改时钟”,会把微机系统的时钟写入时钟模块。
STC11F04E单片机程序
;可显示绿色8个、16个、24个汉字,11.0592MHZ,9600波特率,STC11F04E单片机,可串口接收8、16、24个汉字并显示,2016-01-12通过

ORG0000H
AJMPKS
ORG 0003H
RETI
ORG 000BH
; LJMP CT
RETI
ORG 001BH
RETI
ORG 0023H AJMPS ;接收数据转S
A1 EQU P1.0 ;P1.0=A 接2针
B1 EQU P1.1 ;P1.1=B 接4针
C1 EQU P1.2 ;P1.2=C 接6针
D1 EQU P1.3 ;P1.3=D 接8针
G1 EQU 0B3H ;数据输出G1=B4
G2 EQU 0B7H ;数据输出 G2=B5
STB EQU 0B2H ;595数据锁存脉冲=L 12脚
SCK EQU 0B4H ;595时钟输入=S 11脚
R11 EQU 0B0H ;改为81,R22改为80,上下显示颠倒
R22 EQU 0B1H
EN EQU 0B5H ;138片选,行输出使NENG
DELBUF EQU 7FH
DBUF EQU 60H
ZS EQU 61H
HM EQU 1EH ;定时器毫秒存储
WDT_CONTR EQU 0C1H
FLAG_1 EQU 20H.1 ;
;声明与IAP/ISP/EEPROM有关的特殊功能寄存器的地址
IAP_DATA EQU 0C2H
IAP_ADDRH EQU 0C3H
IAP_ADDRL EQU 0C4H
IAP_CMD EQU 0C5H
IAP_TRIG EQU 0C6H
IAP_CONTR EQU 0C7H
;定义ISP/IAP命令
ISP_IAP_BYTE_READ EQU 1H ;字节读
ISP_IAP_BYTE_PROGRAM EQU 2H ;字节编程,可以将1写成0,要将1变成0,必须执行字节编程
ISP_IAP_SECTOR_ERASE EQU 3H ;扇区擦除,可以将0擦成1,要将0变成1,必须擦除整个扇区
;定义Flash 操作等待时间及允许IAP/ISP/EEPROM操作的常数
ENABLE_IAP EQU 84H ;系统工作时钟<6MHz时,对IAP_CONTR寄存器设置此值
KS: MOVSP,#65H ;设堆栈指针
MOV SCon,#50h; 方式1,REN=1.SM0,SM1,SM2,REN,TB8,RB8,TI,RI
MOV TMOD,#21H;波特率发生器T1工作在模式2上
MOV TH1,#0FDH;预置初值(按照波特率9600BPS预置初值) 11.0592=9600=FD 14400=FE 7200=FC
MOV TL1,#0FDH;预置初值(按照波特率9600BPS预置初值) 11.0592=4800=FA 2400=F4 1200=E8
MOV TH0,#88H ;8800=12t,7000=stc1t
MOV TL0, #00H
ORL IE, #92H ;EA=1,ES=1;ET0=1
SETBPS ;串口中断优先
SETBTR1 ;启动定时器1
MOV WDT_CONTR ,#27H;;;;;;看门狗设置使能
Q: MOV A,#0;FFH
MOVR2,#64D ;清数据区
MOV R0,#20H
QING: MOV@R0,A ;清数据区
INC R0
DJNZ R2,QING
Q1: SETB G1
SETBG2 ;G1,G2送数显示绿色
SETB R11
SETBR22 ;R11R22送数显示红色
MOV DPTR , #0000H ;取汉字长度
LCALL Byte_Read;
MOV ZS, A; #8 ;送一行8个汉字
T1: MOVR3,#00H ;行扫描R3控制行数从00000000到00010000,ABCD的变化给138译码0F扫描16行,当10时扫描结束
MOV DPTR , #0001H ;取数字
TZ: MOV A,ZS
MOV R2, A; #8 ;送一行8个汉字
SETBEN ;138片选,行输出使能
ZJ1: LCALL Byte_Read;16*16点阵,每行显示4个汉字,32条水平线,(1个汉字占16条水平线)2行显示8个汉字,所以先取第一行的一个字节,显示半个汉字(黑)
CPLA ;再跳过8个字节(4个汉字)取第二行1个字节数据(哈)
MOV R6,A
INC DPTR
LCALL Byte_Read;
CPL A
MOV R4,A
ACALLBIN ;BIN2显示绿色
INCDPTR
DJNZ R2,ZJ1
SETB STB
NOP;
CLR STB
MOVA,R3 ;送138地址ABCD
MOVP1,A ;P2.0-P2.3=ABCD
INC R3
MOV A,R3
XRLA,#10H ;00-08是前8行,08-10H是后8行;
JNZTZ ;送前16行
MOV WDT_CONTR ,#17H;喂狗CLR EN
JNB FLAG_1,T1
CALL FS1
AJMP T1
BIN: MOV R5, #08H ;往G1G2,或R11R22中写一个字节数据
BIN1: RLC A
; MOV R11, C ;写上半屏红色
MOV G1,C ;写上半屏绿色
MOV R4,A
MOV A,R6
RLC A
; MOV R22,C ;下半屏红色
MOV G2,C ;下半屏绿色
MOV R6,A
MOV A,R4
SETB SCK
NOP;
NOP
NOP
CLR SCK
DJNZ R5, BIN1
RET
;------------------------------------------------
;读一字节,调用前需打开IAP 功能,入口:DPTR= 字节地址,返回:A= 读出字节
Byte_Read:
MOV IAP_CONTR, #ENABLE_IAP ;打开 IAP功能,设置Flash 操作等待时间
MOV IAP_CMD, #ISP_IAP_BYTE_READ ;设置为IAP/ISP/EEPROM字节读模式命令
MOV IAP_ADDRH, DPH ;设置目标单元地址的高8位地址
MOV IAP_ADDRL, DPL ;设置目标单元地址的低8位地址
CLR EA
MOV IAP_TRIG, #5AH ;先送5Ah,再送A5h到ISP/IAP触发寄存器,每次都需如此
MOV IAP_TRIG, #0A5H ;送完A5h后,ISP/IAP命令立即被触发起动
NOP
MOV A, IAP_DATA ;读出的数据在IAP_DATA单元中,送入累加器A
SETB EA
ACALL IAP_Disable ;关闭 IAP功能,清相关的特殊功能寄存器,使CPU处于安全状态,
;一次连续的IAP操作完成之后建议关闭IAP功能,不需要每次都关
RET
;------------------------------------------------
;字节编程,调用前需打开IAP 功能,入口:DPTR= 字节地址,A=须编程字节的数据
Byte_Program:
MOV IAP_CONTR,#ENABLE_IAP ;打开 IAP功能,设置Flash 操作等待时间
MOV IAP_CMD,#ISP_IAP_BYTE_PROGRAM ;设置为IAP/ISP/EEPROM字节编程模式命令
MOV IAP_ADDRH,DPH ;设置目标单元地址的高8位地址
MOV IAP_ADDRL,DPL ;设置目标单元地址的低8位地址
MOV IAP_DATA,A ;要编程的数据先送进ISP_DATA寄存器
CLR EA
MOV IAP_TRIG,#5AH ;先送5Ah,再送A5h到ISP/IAP触发寄存器,每次都需如此
MOV IAP_TRIG,#0A5H ;送完A5h后,ISP/IAP命令立即被触发起动
NOP
SETB EA
ACALL IAP_Disable ;关闭 IAP功能,清相关的特殊功能寄存器,使CPU处于安全状态,
;一次连续的IAP操作完成之后建议关闭IAP功能,不需要每次都关
RET
;------------------------------------------------
;擦除扇区,入口:DPTR= 扇区地址
Sector_Erase:
MOV IAP_CONTR,#ENABLE_IAP ;打开 IAP功能,设置Flash 操作等待时间
MOV IAP_CMD,#03H ;设置为IAP/ISP/EEPROM扇区擦除模式命令
MOV IAP_ADDRH,DPH ;设置目标单元地址的高8位地址
MOV IAP_ADDRL,DPL ;设置目标单元地址的低8位地址
CLR EA
MOV IAP_TRIG,#5AH ;先送5Ah,再送A5h到ISP/IAP触发寄存器,每次都需如此
MOV IAP_TRIG,#0A5H ;送完A5h后,ISP/IAP命令立即被触发起动
NOP
SETB EA
ACALL IAP_Disable ;关闭 IAP功能,清相关的特殊功能寄存器,使CPU处于安全状态,
;一次连续的IAP操作完成之后建议关闭IAP功能,不需要每次都关
RET
;------------------------------------------------
IAP_Disable:
;关闭 IAP功能,清相关的特殊功能寄存器,使CPU处于安全状态,
;一次连续的IAP操作完成之后建议关闭IAP功能,不需要每次都关
MOV IAP_CONTR,#0 ;关闭 IAP功能
MOV IAP_CMD, #0 ;清命令寄存器,使命令寄存器无命令,此句可不用
MOV IAP_TRIG,#0 ;清命令触发寄存器,使命令触发寄存器无触发,此句可不用
MOV IAP_ADDRH,#0FFH ;送地址高字节单元为00,指向非EEPROM区
MOV IAP_ADDRL,#0FFH ;送地址低字节单元为00,防止误操作
RET
S: PUSH ACC
PUSH PSW
PUSH DPH
PUSH DPL
JS0: CLR ES
CLR EA
SETB REN ;允许接收
LCALLPDRI ;等待串口数据
MOV A, SBUF ;读输入缓冲区
CLR RI
MOV B,A
XRLA,#66H ;擦除EEPROM
JNZ JS
AJMP JS3
JS: MOV A,B
XRLA,#77H ;读EEPROM发送到PC
JZ FS6
MOV A,B
SUBBA,#28H ;30H="0" ,如果第一个字节是“01”表示16进制发送,如果是“30H”表示ASC码接收
JC JS1 ;8的asc码是38h-28h,c=0。(01h,10h先发送2个小于28的命令字符)-28h,c=1.转Js1十六进制接收,(36,37,38)-28h,c=0,ascii接收
LCALL PDRI;等待下一个串口数据
MOV A, SBUF ;读输入缓冲区
MOV R2,A
CLR RI
XRLA,#36H ;ASC码接收时命令改成66,77 ;擦除EEPROM
JNZ JSI
AJMP JS3
FS6: AJMP FS0
JSI: MOV A,B
XRLA,#37H ;读EEPROM发送到PC
JNZ JSA
AJMP FS0
JSA: MOVA,B ;分离出汉字长度8或16或24存EEPROM的0000单元
ANL A,#0FH
SWAP A
MOV B,A
MOV A,R2
ANL A,#0FH
ORL A,B
MOV DPTR,#0000H
LCALL Byte_Program
JSI1: MOVR2,#00h ;ascii码接收
MOV R5,#04H;02h
MOV DPTR,#0001H
SI8: SETBREN ;接收第一个字节时没有清除RI,所以还得从2CH开始接收
MOV R2,#00h
SI9: MOV R0,#2CH
LCALL PDRI ;PC发来的是ASCII码,要读入2个ASC码才能合成一个字节数据
MOVA, SBUF ;读输入缓冲区
CLR RI;软件清除串口中断标记
MOV @R0,A ;数据送RAM
INC R0 ;数据地址加1
SI10: LCALLPDRI
MOVA, SBUF ;读输入缓冲区
CLR RI;软件清除串口中断标记
MOV @R0,A ;数据送RAM
DEC R0 ;数据地址减1,回到第一个字节
LASC: LCALL ASC
SWAP A
MOV DBUF, A
INC R0 ;数据地址加1
LCALL ASC
ORL DBUF,A
MOVA,DBUF ;
LCALL Byte_Program ;字节编程写入A
CLR RI;软件清除串口中断标记
INC DPTR
DJNZ R2,SI9
DJNZ R5,SI8
AJMP SEND1
JS1: MOV DPTR,#0000H
MOV A,B
LCALL Byte_Program;MOV R2,#00H
JS2: MOV DPTR,#0001H
SETB REN ;允许接收
S2: LCALL PDRI;等待下一个串口数据
MOV A, SBUF ;读输入缓冲区
LCALL Byte_Program ;字节编程写入A
CLR RI;软件清除串口中断标记
INC DPTR
MOV A,DPH
CJNE A,#04H ,S2
AJMP SEND
FS0: ;MOV R2,#00H
MOV DPTR,#0000H ;将EEPROM测试起始地址送DPTR数据指针
FS: LCALL Byte_Read ;MOVX A,@DPTR;读芯片内部扩展的EXTRAM
MOV SBUF, A
JNB TI, $
CLR TI
INC DPTR
MOV A,DPH
CJNE A,#04H ,FS;DJNZ R2,FS
AJMP SEND
JS3: MOV DPTR,#0000H ;将EEPROM测试起始地址送DPTR数据指针
LCALL Sector_Erase ;擦除整个扇区
MOV DPTR,#0200H ;将EEPROM测试起始地址送DPTR数据指针
LCALL Sector_Erase ;擦除整个扇区
AJMP SEND
SEND1: SETBFLAG_1
SEND: POP DPL
POP DPH
POP PSW
POP ACC
SETB ES
SETB EA
SD: RETI
FS1: PUSH ACC
PUSH PSW
PUSH DPH
PUSH DPL
MOV R5,#04H;02H
MOV DPTR,#0000H ;将EEPROM测试起始地址送DPTR数据指针
CLR ES
MOV R0,#2CH
FS2: MOV R2,#00H
FS3: LCALL Byte_Read ;
MOV @R0,A
CALL FSD
INC DPTR
DJNZ R2,FS3
DJNZ R5,FS2
CLR FLAG_1
SETB ES
POP DPL
POP DPH
POP PSW
POP ACC
RET
ASC: MOV A, @R0
CLR C
SUBB A, #30H
MOV R6, A
SUBB A, #0AH ;0-9的数字不够减 30-39=0-9
JC ASCEND
XCH A, R6
SUBB A, #07H ;是A-F的数字再减,比如A=41H-30H-7=A, 41-47=A-F
MOV R6, A
ASCEND:MOV A, R6
RET
FSD: MOV DPTR,#0FD0H
MOV A, @R0
FSD1: ANL A, #0F0H
SWAP A
MOVC A,@A+DPTR
MOV SBUF, A
JNB TI, $
CLR TI
MOV A, @R0
ANL A, #0FH
MOVCA,@A+DPTR
MOV SBUF, A
JNB TI, $
CLR TI
;INC R0
RET
PDRI: SETB REN;占用R4/R5/R1
MOV R1,#100;20;300毫秒超时退出!
PBZ: MOV R4,#25;50;100;67
DY2: MOV R5,#2;4;8
DY1: JB RI,KKQ;检测到RI变1就退出
DJNZ R5,DY1;25微秒检测一次
JB RI,KKQ;检测到RI变1就退出
SETB C;程序正常时C=1
DJNZ R4,DY2;内循环50毫秒
DJNZ R1,PBZ;超时退出
CLR C;对串口接收超时退出C=0
CLRRI;清除有串口数据标志
KKQ: RET
END
LED显示屏显示时钟
首先在原电路基础上添加一个时钟模块DS20001,如下图:

然后把单片机显示程序改变如下:
T1: MOVR3,#00H ;行扫描 R3控制行数从00000000到00010000,ABCD的变化给138译码0F扫描16行,当10时扫描结束
MOV DPTR , #TABSZ ;取数字
MOV R2,#160
SETBEN ;138片选,行输出使能
ZJ1: ACALLMON ;取月数据首址
ACALL HOU ;取时数据首址 调显示
MOVA,MONTH ;取月数据首址+1,第二位
ANL A,#0FH
ACALL MON1
MOVA,HOUR ;取时数据首址
ANL A,#0FH
ACALLHOU1 ;2 调显示
MOV A,R2;#160
ACALLYUE ;取“月”字数据首址
MOVA,R2 ;取"-"字数据首址
ADD A,#64
ACALLSHI ;3 调显示
MOVA,R2 ;取“月”字数据首址+1
ADD A,#01H
ACALL YUE
MOVA,MINUTE ;取分数据首址
LCALLHOU0 ;4 调显示
MOVA,DAY ;取日数据首址
ACALLMON0 ;5
MOVA,MINUTE ;取"分"数据首址+1
ANL A,#0FH
ACALLHOU1 ;6 调显示
MOVA,DAY ;取日数据首址+1
ANL A,#0FH
ACALL MON1
MOVA,R2 ;取"-"字数据首址
ADD A,#64
ACALLSHI ;7 调显示
MOVA,#32 ;取日字的汉字点阵首址
ADD A,R2
ACALLYUE
MOVA,SECOND ;取秒数据首址
ACALLHOU0 ; 调显示
MOVA,#33 ;取日字的汉字点阵首址+1
ADD A,R2
ACALL YUE
MOVA,SECOND ;取秒数据首址+1
ANL A,#0FH
ACALLHOU1 ;8 调显示
INC R2
;DEC DPH
INC DPTR
SETB STB
NOP
CLR STB
MOVA,R3 ;送138地址ABCD
MOVP1,A ;P2.0-P2.3=ABCD
INC R3
MOV A,R3
XRLA,#10H ;00-08是前8行,08-10H是后8行;
JNZZJ1 ;送前16行
MOV WDT_CONTR ,#17H;喂狗CLR EN
JNB FLAG_1,TZ0
CALLFS1
TZ0: AJMP T1
MON: MOV A,MONTH
MON0: ANL A,#0F0H
SWAP A
MON1: MOV B,#10H
MULAB ;B放结果高8位,A放结果低8位
MOVC A, @A+DPTR ;16*16点阵,每行显示4个汉字,32条水平线,(1个汉字占16条水平线)2行显示8个汉字,所以先取第一行的一个字节,显示半个汉字(牡)
CPLA ;再跳过8个字节(4个汉字)取第二行1个字节数据(校)
MOV R6,A
RET
HOU: MOV A,HOUR
HOU0: ANL A,#0F0H
SWAP A
HOU1: MOV B,#10H
MUL AB
MOVC A, @A+DPTR ;16*16点阵,每行显示4个汉字,32条水平线,(1个汉字占16条水平线)2行显示8个汉字,所以先取第一行的一个字节,显示半个汉字(牡)
CPLA ;再跳过8个字节(4个汉字)取第二行1个字节数据(校)
MOV R4,A
ACALLBIN ;BIN2显示绿色
RET
YUE: ;MOV A,R2
MOVC A, @A+DPTR ;
CPL A
MOV R6,A
RET
SHI: MOVC A, @A+DPTR ;
CPL A
MOV R4,A
ACALLBIN ;BIN2显示绿色
RET
显示效果如下图:

显示程序改变如下:
T1: MOVR3,#00H ;行扫描 R3控制行数从00000000到00010000,ABCD的变化给138译码0F扫描16行,当10时扫描结束
MOV DPTR , #TABSZ ;取数字
MOV R2,#160
SETBEN ;138片选,行输出使能
ZJ1: ACALL MON
ACALLHOU ;1
MOV A,MONTH
ANL A,#0FH
ACALL MON1
MOV A,HOUR
ANL A,#0FH
ACALLHOU1 ;2
MOV A,R2;#160
ACALLYUE ;取“月”字数据首址
MOVA,R2 ;取"时"字数据首址
ADD A,#64
ACALLSHI ;3
MOVA,R2 ;取“月”字数据首址
ADD A,#01H
ACALL YUE
MOVA,R2 ;取"时"字数据首址
ADD A,#65
ACALL SHI ;4
MOV A,DAY
ACALLMON0 ;5
MOV A,MINUTE
ACALL HOU0
MOV A,DAY
ANL A,#0FH
ACALL MON1
MOV A,MINUTE
ANL A,#0FH
ACALLHOU1 ;6
MOVA,#32 ;取日字的汉字点阵首址
ADD A,R2
ACALL YUE
MOVA,R2 ;取"分"字数据首址
ADD A,#96
INC DPH
ACALL SHI
DECDPH ;7
MOVA,#33 ;取日字的汉字点阵首址+1
ADDA,R2
ACALL YUE
INC DPH
MOVA,R2 ;取"分"字数据首址+1
ADD A,#97
ACALLSHI ;8
INC R2
DEC DPH
INC DPTR
SETB STB
NOP
CLR STB
MOVA,R3 ;送138地址ABCD
MOVP1,A ;P2.0-P2.3=ABCD
INC R3
MOV A,R3
XRLA,#10H ;00-08是前8行,08-10H是后8行;
JNZZJ1 ;送前16行
MOV WDT_CONTR ,#17H;喂狗CLR EN
JNB FLAG_1,TZ0
CALL FS1
TZ0: AJMP T1
MON: MOV A,MONTH
MON0: ANL A,#0F0H
SWAP A
MON1: MOV B,#10H
MULAB ;B放结果高8位,A放结果低8位
MOVC A, @A+DPTR ;16*16点阵,每行显示4个汉字,32条水平线,(1个汉字占16条水平线)2行显示8个汉字,所以先取第一行的一个字节,显示半个汉字(牡)
CPLA ;再跳过8个字节(4个汉字)取第二行1个字节数据(校)
MOV R6,A
RET
HOU: MOV A,HOUR
HOU0: ANL A,#0F0H
SWAP A
HOU1: MOV B,#10H
MUL AB
MOVC A, @A+DPTR ;16*16点阵,每行显示4个汉字,32条水平线,(1个汉字占16条水平线)2行显示8个汉字,所以先取第一行的一个字节,显示半个汉字(牡)
CPLA ;再跳过8个字节(4个汉字)取第二行1个字节数据(校)
MOV R4,A
ACALLBIN ;BIN2显示绿色
RET
YUE: ;MOV A,R2
MOVC A, @A+DPTR ;
CPL A
MOV R6,A
RET
SHI: MOVC A, @A+DPTR ;
CPL A
MOV R4,A
ACALLBIN ;BIN2显示绿色
RET
显示效果如下图:

通过串口发送命令:“8816011801123045”可修改时间和日期,含义是16年一月18日星期一12点30分45秒。
还可以通过串口发送命令“99”,读取时钟模块的日期和时间。
完整程序请在我的网盘下载。
采用STC12C5A60S2单片机的LED显示屏驱动程序
一、原理图如下,由于LED显示屏上的驱动集成电路使用了74HC245集成电路(前面的例子是使用74HC244),使能端并取消了74LS04,所以驱动电路有所变化,相应的程序也有所改变。原来74LS138使能端经74LS04反相是低电平,现在取消了74LS04就变为高电平了 。 二、显示效果如下:2个画面交替显示。 三、STC12C5A60S2单片机简介
STC12C5A60S2是STC生产的单时钟/机器周期(1T)的单片机,是高速、低功耗、超强抗干扰的新一代8051单片机,指令代码完全兼容传统8051,但速度快8-12倍。内部集成MAX810专用复位电路,2路PWM,8路高速10位A/D转换,针对电机控制,强干扰场合。 1、增强型8051CPU,单时钟/机器周期,stc12c5a60s2的运行速度比at89s52要快12倍
2、工作电压 5.5-3.5V
3、60K字节ROM,1280字节数据RAM
4、通用I/O口,复位后为:准双向口/弱上拉
可设置成四种模式:准双向口/弱上拉,强推挽/强上拉,仅为输入/高阻,开漏
每个I/O口驱动能力均可达到20mA,但整个芯片最大不要超过120mA
5、有1K字节的EEPROM,擦写次数在10万次以上
6、看门狗
7、内部集成MAX810专用复位电路
8、外部掉电检测电路
9、时钟源:外部高精度晶体/时钟,内部R/C振荡器
常温下内部R/C振荡器频率为:5.0V单片机为:11~17MHz,3.3V单片机为:8~12MHz
10、4个16位定时器,两个与传统8051兼容的定时器/计数器,16位定时器T0和T1
11、3个时钟输出口,可由T0的溢出在P3.4/T0输出时钟,可由T1的溢出在P3.5/T1输出时钟,独立波特率发生器可以在P1.0口输出时钟
12、外部中断I/O口7路,传统的下降沿中断或电平触发中断,并新增支持上升沿中断的PCA模块,PowerDown模式可由外部中断唤醒,INT0/P3.2,INT1/P3.3,T0/P3.4,T1/P3.5,RxD/P3.0,CCP0/P1.3,CCP0/P1.3
13、2路PWM
14、A/D转换,10位精度ADC,共8路,转换速度可达250K/S
15、通用全双工异步串行口(UART)
16、双串口,RxD2/P1.2,TxD2/P1.3
17、工作范围:-40~85
18、封装:LQFP-48,LQFP-44,PDIP-40,PLCC
四、温度测量原理:采用NTC热敏电阻器与一个固定电阻分压,如下图随着温度的变化,分压值也会变化,用STC12C5A60S2单片机的A/D转换器采集这个分压值,在单片机中设置一个电压与温度的对应表(这个表通过实验获得),根据采集的电压值获取对应的温度值,显示出来并保存在单片机内存中。

五、显示程序
ORG 0000H
AJMPKS ;显示xx月xx日 室温xx度,11.0592MHZ,STC12C5A60S2单片机 ,带时钟,可交替显示温度。88命令修改时间日期,99命令查询日期时间2016-01-27 通过
ORG0003H ;XXXXXXXX-X
RETI
ORG 000BH
LJMP CT
RETI
ORG 001BH
RETI
ORG 0023H
AJMPS ;接收数据转S
A1 EQU P0.0 ;P1.0=A 接2针
B1 EQU P0.1 ;P1.1=B 接4针
C1 EQU P0.2 ;P1.2=C 接6针
D1 EQU P0.3 ;P1.3=D 接8针
G1 EQU P2.6 ;数据输出G1=B4
G2 EQU P2.7 ;数据输出 G2=B5
STB EQU P2.5 ;595数据锁存脉冲=L12脚
SCK EQU P2.4 ;595时钟输入=S 11脚
R11 EQU P2.3 ;改为81,R22改为80,上下显示颠倒
R22 EQU P2.2
EN EQU P2.1 ;138片选,行输出使NENG
ADC_Channel_1_Result EQU 2FH
DBUF EQU 60H
ZS EQU 61H
HM EQU 1EH ;定时器毫秒存储
WDT_CONTR EQU 0C1H
AUX1 EQU 0A2H ;AUXR1寄存器的ADRJ位是A/D转换结果寄存器(ADC_RES,ADC_RESL)的数据格式调整控制位.
;当ADRJ=0时,..............................................10位A/D转换结果的高8位存放在ADC_RES中,低2位存放在ADC_RESL的低2位中.
;AUR EQU 8EH; Internal/External RAM access 内部/外部RAM存取= 0:内部扩展的EXT_RAM可以存取.
FLAG_1 EQU 20H.1 ;
FLAG_2 EQU 20H.1 ;
FLAG_3 EQU 20H.1 ;
YEAR EQU 28H ;年
MONTH EQU 29H ;月
DAY EQU 2AH ;日
WEEK EQU 2BH ;星期
HOUR EQU 2CH ;小时
MINUTE EQU 2DH ;分钟
SECOND EQU 2EH ;秒
FLAG EQU 27H ;通用标志寄存器
;BIT0=1, ACK ERR
;BIT0=0,ACK OK
;BIT1=1,TEST MODE
;BIT1=0,NORMAL MODE
P1M0 DATA 92H
P1M1 DATA 91H
P0M0 DATA 94H
P0M1 DATA 93H
P2M0 DATA 96H
P2M1 DATA 95H
TIMETEMP EQU 27H ;时间数据缓存器
TIMETX EQU 59H ;时间数据发送寄存器
TIMERX EQU 5AH ;时间数据接收寄存器
SDA EQU 0b5h ;IIC的SDA口线 15脚
SCL EQU 0b7h ;IIC的SCL口线 13脚
LED EQU 0B6H
;声明与IAP/ISP/EEPROM有关的特殊功能寄存器的地址
IAP_DATA EQU 0C2H
IAP_ADDRH EQU 0C3H
IAP_ADDRL EQU 0C4H
IAP_CMD EQU 0C5H
IAP_TRIG EQU 0C6H
IAP_CONTR EQU 0C7H
;定义ISP/IAP命令
ISP_IAP_BYTE_READ EQU 1H ;字节读
ISP_IAP_BYTE_PROGRAM EQU 2H ;字节编程,可以将1写成0,要将1变成0,必须执行字节编程
ISP_IAP_SECTOR_ERASE EQU 3H ;扇区擦除,可以将0擦成1,要将0变成1,必须擦除整个扇区
;定义Flash 操作等待时间及允许IAP/ISP/EEPROM操作的常数
ENABLE_IAP EQU 84H ;系统工作时钟<6MHz时,对IAP_CONTR寄存器设置此值
;AD转换设置
ADC_CONTR EQU 0BCH ;ADC control register
; SFR name Address bit B7 B6 B5 B4 B3 B2 B1 B0
;ADC_CONTR BCH name ADC_POWER SPEED1 SPEED0 ADC_FLAG ADC_START CHS2CHS1 CHS0
ADC_RES EQU 0BDH ;ADC high 8-bit result register
ADC_LOW2 EQU 0BEH ;ADC low 8-bit result register
P1ASF EQU 09DH ;P1 secondary function control register
ADC_FLAG EQU 10H ;ADC complete flag
ADC_Power_On_Speed_Channel_1EQU 11100000B ;;B7=power,B6B5=speed,B4=flag,B3=start;B2B1B0=ch0-ch7,001是P1.1作为A/D输入,000是P1.0输入
KS: MOVSP,#65H ;设堆栈指针
MOV SCon,#50h; 方式1,REN=1.SM0,SM1,SM2,REN,TB8,RB8,TI,RI
MOV TMOD,#21H;波特率发生器T1工作在模式2上
MOVTH1,#0FDH;预置初值(按照波特率9600BPS预置初值)11.0592=9600=FD MOV TL1,#0FDH; MOV TH0,#0DCH;88H ;8800=12t,7000=stc1t
MOV TL0, #00H
ORL IE, #92H ;EA=1,ES=1;ET0=1
SETBPS ;串口中断优先
SETBTR1 ;启动定时器1
SETB EN
MOVP0M0,#00000000b ; P1M0=0 P1M1=0双向口 P1M0=1 P1M1=0输入口 P1M0=0 P1M1=1推挽输出20ma
MOV P0M1,#00000000b
MOVP2M0,#00000000b ; P1M0=0 P1M1=0双向口 P1M0=1 P1M1=0输入口 P1M0=0 P1M1=1推挽输出20ma
MOVP2M1,#00000000b
MOV ADC_CONTR,#ADC_Power_On_Speed_Channel_1;AD转换设置
;ANL AUX1,#11111011B ;ADRJ =0
LCALL INIT_ADC
MOV WDT_CONTR ,#27H;;;;;;看门狗设置使能
Q: MOV A,#0;FFH
MOVR2,#64D ;清数据区
MOV R0,#20H
QING: MOV@R0,A ;清数据区
INC R0
DJNZ R2,QING
LCALL TIMESTATUS_INT12 ;24小时制
LCALL READ_TIME ;
MOV WDT_CONTR ,#17H;喂狗CLR EN
SETBTR0 ;启动定时器0
Q1: SETB G1
SETBG2 ;G1,G2送数显示绿色
SETBR11
SETBR22 ;R11R22送数显示红色
CLR LED
T1: MOVR3,#00H ;行扫描R3控制行数从00000000到00010000,ABCD的变化给138译码0F扫描16行,当10时扫描结束
MOV DPTR , #TABSZ ;取数字
MOV R2,#160
CLREN ;138片选,行输出使能
MOV A,SECOND;根据秒数据交替显示
ANL A,#0FH
SUBB A,#5
JNC ZJ1
AJMP ZJ2
ZJ1: MOVA,R2 ;取“温“字数据首址+1
ADD A,#96
INC DPH
ACALL YUE
DEC DPH
ACALLHOU ;取时数据首址 1调显示
MOVA,R2 ;取“温“字数据首址+1
ADD A,#97
INC DPH
ACALL YUE
DEC DPH
MOVA,HOUR ;取时数据首址低字节
ANL A,#0FH
ACALLHOU1 ;2 调显示
MOVA,R2 ;取"度"字数据首址
ADD A,#128
INC DPH
ACALL YUE
DEC DPH
MOVA,MINUTE ;取分数据首址
ACALLHOU2 ;3调显示
MOVA,R2 ;取"度"字数据首址+1
ADD A,#129
INC DPH
ACALL YUE
DEC DPH
MOVA,MINUTE ;取"分"数据首址+1
ANL A,#0FH
ACALLHOU3 ;4调显示
MOV A,ADC_Channel_1_Result
MOVR5,A ;取A/D结果送R5
LCALL HEX2BCD ;影响单元:R0,R1,R6 ,R1存A/D结果转换成BCD的十位和个位
ACALL MON0
MOVA,SECOND ;取秒数据首址
ACALLHOU0 ; 5调显示
MOV A,ADC_Channel_1_Result
MOVR5,A ;取A/D结果送R5
LCALL HEX2BCD ;影响单元:R0,R1,R6 ,R1存A/D结果转换成BCD的十位和个位
ANL A,#0FH
ACALLMON1 ;
MOVA,SECOND ;取秒数据首址+1
ANL A,#0FH
ACALLHOU1 ;6 调显示
MOVA,R2 ;取"度"字数据首址+1
ADD A,#128
INC DPH
ACALL YUE
DEC DPH
MOVA,R2 ;取"-"字数据首址
ADD A,#64
ACALLSHI ;7 调显示
MOVA,R2 ;取"度"字数据首址+1
ADD A,#129
INC DPH
ACALL YUE
DEC DPH
MOVA,WEEK ;取星期数据首址+1
ANL A,#0FH
ACALLHOU3 ;8 调显示
INC R2
INC DPTR
SETB STB
NOP
CLR STB
MOV A,R3 ;送138地址ABCD
MOVP0,A ;P2.0-P2.3=ABCD
INC R3
MOV A,R3
XRLA,#10H ;00-08是前8行,08-10H是后8行;
JNZZJ1 ;送前16行
MOV WDT_CONTR ,#17H;喂狗CLR EN
JNB FLAG_1,TZ0
CALL FS1
TZ0: AJMP T1
ZJ2: ACALLMON ;取月数据首址
ACALLHOU ;取时数据首址 调显示
MOVA,MONTH ;取月数据首址+1,第二位
ANL A,#0FH
ACALL MON1
MOV A,HOUR ;取时数据首址+1
ANL A,#0FH
ACALLHOU1 ;2 调显示
MOV A,R2;#160
ACALLYUE ;取“月”字数据首址
MOVA,MINUTE ;取分数据首址
ACALLHOU2;0 ;调显示
MOVA,R2 ;取“月”字数据首址+1
ADD A,#01H
ACALL YUE
MOVA,MINUTE ;取"分"数据首址+1
ANL A,#0FH
ACALLHOU3;1 ;6 调显示
MOVA,DAY ;取日数据首址
ACALLMON0 ;5
MOVA,SECOND ;取秒数据首址
ACALLHOU0 ; 调显示
MOVA,DAY ;取日数据首址+1
ANL A,#0FH
ACALL MON1
MOVA,SECOND ;取秒数据首址+1
ANL A,#0FH
ACALLHOU1 ;8 调显示
MOVA,#32 ;取日字的汉字点阵首址
ADD A,R2
ACALL YUE
; MOVA,WEEK ;取星期数据首址
;ACALLHOU2;0 ; 调显示
MOVA,R2 ;取"-"字数据首址
ADD A,#64
ACALLSHI ;7 调显示
MOVA,#33 ;取日字的汉字点阵首址+1
ADD A,R2
ACALL YUE
MOVA,WEEK ;取星期数据首址+1
ANL A,#0FH
ACALL HOU3;1 ;8 调显示
INC R2
;DEC DPH
INC DPTR
SETB STB
NOP
CLR STB
MOVA,R3 ;送138地址ABCD
MOVP0,A ;P2.0-P2.3=ABCD
INC R3
MOV A,R3
XRLA,#10H ;00-08是前8行,08-10H是后8行;
JNZZJ2 ;送前16行
MOV WDT_CONTR ,#17H;喂狗CLR EN
JNB FLAG_1,TZ3
CALL FS1
TZ3: AJMP T1
MON: MOV A,MONTH
MON0: ANL A,#0F0H
SWAP A
MON1: MOV B,#10H
MULAB ;B放结果高8位,A放结果低8位
MOVC A, @A+DPTR ;16*16点阵,每行显示4个汉字,32条水平线,(1个汉字占16条水平线)2行显示8个汉字,所以先取第一行的一个字节,显示半个汉字(牡)
CPLA ;再跳过8个字节(4个汉字)取第二行1个字节数据(校)
MOV R6,A
RET
HOU: MOV A,HOUR
HOU0: ANL A,#0F0H
SWAP A
HOU1: MOV B,#10H
MUL AB
MOVC A, @A+DPTR ;16*16点阵,每行显示4个汉字,32条水平线,(1个汉字占16条水平线)2行显示8个汉字,所以先取第一行的一个字节,显示半个汉字(牡)
CPLA ;再跳过8个字节(4个汉字)取第二行1个字节数据(校)
MOV R4,A
ACALLBIN ;BIN2显示绿色
RET
HOU2: ANL A,#0F0H
SWAP A
HOU3: MOV B,#10H
MUL AB
SHI: MOVC A, @A+DPTR ;16*16点阵,每行显示4个汉字,32条水平线,(1个汉字占16条水平线)2行显示8个汉字,所以先取第一行的一个字节,显示半个汉字(牡)
CPLA ;再跳过8个字节(4个汉字)取第二行1个字节数据(校)
MOV R4,A
ACALLBIN2 ;BIN2显示绿色
RET
YUE: ;MOV A,R2
MOVC A, @A+DPTR ;
CPL A
MOV R6,A
RET
BIN: MOV R5, #08H ;往G1G2,或R11R22中写一个字节数据
BIN1: RLC A
; MOV R11, C ;写上半屏红色
MOV G1,C ;写上半屏红色
MOV R4,A
MOV A,R6
RLC A
; MOV R22,C ;下半屏红色
MOV R22,C ;下半屏绿色
MOV R6,A
MOV A,R4
SETB SCK
NOP;CALL SDELAY
NOP
NOP
CLR SCK
DJNZ R5, BIN1
RET
BIN2: MOV R5, #08H ;往G1G2,或R11R22中写一个字节数据
BIN3: RLC A
MOV G1,C ;G1
MOV R4,A
MOV A,R6
RLC A
MOV R22,C ;下半屏红色G1 R22 红色的日
MOV R6,A
MOV A,R4
SETB SCK
NOP
NOP
CLR SCK
DJNZ R5, BIN3
RET
|