jianjun42 发表于 2009-10-16 11:09:10

分享我的M8+DS1302+LCD1602电子钟

初次尝试玩DS1302电子钟,经过几天的摸索和调试,终于获得了成功,现上传相关资料和代码,下面是实验板图片:http://cache.amobbs.com/bbs_upload782111/files_20/ourdev_492215.JPG
(原文件名:DSC00235.JPG)
下面是LCD1602的现实效果图片:
http://cache.amobbs.com/bbs_upload782111/files_20/ourdev_492216.JPG
(原文件名:DSC00236.JPG)
下面是源代码:
'这是一个M8+DS1302的数字钟程序
'portb.5接DS1302的RST,portb.4接sclk,portb.3接I/O?
'本机采用三键结构,其中pinc.2为选择调试键,pinc.4为数字加键,pinc.3为数字减键,相关数值调整后同步写入DS1302相应的寄存器。

$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 32                                             ' 设置堆栈大小
$swstack = 10
$framesize = 40
Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2
Config Lcd = 16 * 2
Cursor Off
Declare Sub Outbit(a As Byte)                               '发送字节
Declare Sub Inbit(indat As Byte)                            '接收字节
Declare Sub Finish                                          '结束操作
Declare Sub Begin                                           '开始写入
Dim A As Byte
Dim B As Byte
Dim C As Byte
Dim J As Byte
Dim Ax As Byte , Ad As Byte
Dim T(7) As Byte , Ts(7) As String * 2 , Tq As String * 2
Dim Tt As Byte

Call Begin                                                '充电设定
A = &H90                                                    '地址144
Call Outbit(a )                                             '写入地址
A = &B10101010                                              '允许充电。电阻4K,两个二极管
Call Outbit(a)                                              '写入充电设置
Call Finish                                                 '结束操作
Waitms 10
Cls
Ax = 126
Ad = 127
Tt = 0
B = 0
C = 0
Do
For J = 1 To 7
      Ad = Ad + 2
      A = Ad
      Call Begin
      Call Outbit(a)                                        '写入读取数据的地址
      Call Inbit(b)                                       '读取数据
      Call Finish                                           '结束操作
      B = Makedec(b)                                        '取数,bcd2dec转换
      Ts(j) = Str(b)
      Ts(j) = Format(ts(j) , "00")
   Next J
      Locate 2 , 9
      Lcd Ts(3) ; ":" ; Ts(2) ; ":" ; Ts(1)
      Locate 1 , 7
      Lcd "20" ; Ts(7) ; "-" ; Ts(5) ; "-" ; Ts(4)
      Ad = 127
   

If Pinc.2 = 0 Then                                        '选择调试
   Waitms 20
   If Pinc.2 = 0 Then
      Incr Tt
      If Tt > 8 Then Tt = 1
      Bitwait Pinc.2 , Set
   End If
End If

If Tt <> 0 Then
   Tq = Ts(tt)
   Ts(tt) = ""
   Locate 2 , 9
   Lcd Ts(3) ; ":" ; Ts(2) ; ":" ; Ts(1)
   Locate 1 , 7
   Lcd "20" ; Ts(7) ; "-" ; Ts(5) ; "-" ; Ts(4)
   Ts(tt) = Tq
   Waitms 500
   End If

If Pinc.4 = 0 Or Pinc.3 = 0 Then
   Waitms 20
   If Pinc.4 = 0 Then                                       '数字加
      B = Val(ts(tt))
      Incr B
      Bitwait Pinc.4 , Set
   Elseif Pinc.3 = 0 Then                                 '数字减
      B = Val(ts(tt))
      Decr B
      Bitwait Pinc.3 , Set
   End If
      T(tt) = Makebcd(b)
      C = Tt * 2
      Ax = Ax + C
      A = Ax
      Call Begin                                          '写入使能
      Call Outbit(a)                                        '首先写入地址
      A = T(tt)
      Call Outbit(a)                                        '然后写入数据
      Call Finish                                           '写入后结束本次写入
      Ax = 126
End If

Loop
End

Sub Outbit(a As Byte )                                    '发送数据子程序
   Local Temp As Byte , Tempi As Byte , I As Byte
   Ddrb.4 = 1
   Portb.4 = 0
   Ddrb.3 = 1
   Portb.3 = 0
   nop
   For I = 0 To 7
      Portb.4 = 0
      nop
      Temp = 2 ^ I
      Tempi = A And Temp
      If Tempi = 0 Then
         Portb.3 = 0
         Else
         Portb.3 = 1
      End If
      nop
      Portb.4 = 1
      nop
   Next I
   nop
End Sub


Sub Inbit(indat As Byte )                                 '接收数据的子程序
   Local Readtemp As Byte , Temp As Byte , I As Byte

   Ddrb.4 = 1
   Portb.4 = 1
   Indat = 0
   Readtemp = 0
   nop
   Ddrb.3 = 0
   Portb.3 = 1
   nop
   For I = 0 To 7
      Portb.4 = 1                                           '高电位换数据
      nop
      Portb.4 = 0
      nop
      If Pinb.3 = 1 Then
         Temp = 2 ^ I
         Readtemp = Readtemp + Temp
         Elseif Pinb.3 = 0 Then
         Temp = 0
      End If
      nop
   Next I
   Indat = Readtemp
   Portb.4 = 0
End Sub


Sub Finish                                                '结束操作子程序
   Ddrb.4 = 0
   Portb.4 = 0
   nop
   Ddrb.5 = 1
   Portb.5 = 0
   nop
End Sub

Sub Begin                                                   '开始操作子程序
   nop
   Ddrb.5 = 1
   Portb.5 = 1
   nop
   Ddrb.4 = 1
   Portb.4 = 0
   nop
End Sub

jianjun42 发表于 2009-10-16 18:22:10

下班回来发现此贴竟然没有人顶,没办法自己顶一下

ch2003_23 发表于 2009-10-16 21:13:42


汇编

xingcn 发表于 2009-10-16 22:41:28

楼上如何看出是汇编?

tyblly 发表于 2009-10-16 22:48:34

basic 的,非汇编

jianjun42 发表于 2009-10-19 14:54:54

我看了一些论坛内的相关帖子,提到很多DS1302的问题,比如走时精度、晶振还有起振难等问题,我竟然都没有碰到,我使用的DS1302就是花2元在电子商城买的,晶振也是普通的32768的,没有外接电容,电路也是采用标准电路,弄好了竟然工作非常好,走时很准确

jianjun42 发表于 2009-10-22 11:46:21

在本文的实验中,我再添加了LM35测温电路,利用M8的ADC1测试环境温度,有关LM35的具体参数我不在这里赘述,连接方式是LM35的一脚直接接+5V,3脚接地,2脚直接接M824脚(外接0.1uf电容),测量范围0-99.9度,相关程序如下:
For J = 1 To 30
      W1 = Getadc(1)
      W = W + W1
Next J
      W = W / 30
      W = W * 2560
      W = W / 1096
      W_adc = Str(w)
      W_adc = Format(w_adc , "00.0")
      Locate 2 , 1
      Lcd W_adc ; "C"
将以上程序添加到主程序DO......LOOP之间的合适位置即可。

jianjun42 发表于 2009-11-1 17:24:38

本实验再次更新,加入秒表功能,在正常走时中,按下S1键启动秒表,按下S2键停止秒表,再加上前面所述的测温功能,代码如下:
'这是一个M8+DS1302的数字钟程序
'portb.5接DS1302的RST,portb.4接sclk,portb.3接I/O?
'本机采用三键结构,其中pinc.2为选择调试键,pinc.4为数字加键,pinc.3为数字减键,相关数值调整后同步写入DS1302相应的寄存器。

$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 32                                             ' 设置堆栈大小
$swstack = 10
$framesize = 40
Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2
Config Lcd = 16 * 2
Config Adc = Single , Prescaler = Auto , Reference = Internal
Cursor Off
Declare Sub Outbit(a As Byte)                               '发送字节
Declare Sub Inbit(indat As Byte)                            '接收字节
Declare Sub Finish                                          '结束操作
Declare Sub Begin                                           '开始写入
Dim A As Byte
Dim B As Byte
Dim C As Byte
Dim D As Byte
Dim J As Byte
Dim Ax As Byte , Ad As Byte
Dim T(7) As Byte , Ts(7) As String * 2 , Tq As String * 2 , Ta As String * 2
Dim Tt As Byte
Dim W As Long , W1 As Word , W_adc As String * 4
Dim Shi As String * 2 , Fen As String * 2 , Miao As String * 2 , S As Bit , S1 As Byte , S2 As Byte , S3 As Byte , S4 As Byte
Start Adc
Call Begin                                                '充电设定
A = &H90                                                    '地址144
Call Outbit(a )                                             '写入地址
A = &B10101010                                              '允许充电。电阻4K,两个二极管
Call Outbit(a)                                              '写入充电设置
Call Finish                                                 '结束操作
Waitms 10
Cls
Ax = 126
Ad = 127
Tt = 0
B = 0
C = 0
W = 0
W1 = 0
S = 0
D = 0
Do

      If S = 0 Then
         For J = 1 To 7
             Ad = Ad + 2
             A = Ad
             Call Begin
             Call Outbit(a)                                 '写入读取数据的地址
             Call Inbit(b)                                  '读取数据
             Call Finish                                    '结束操作
             B = Makedec(b)                                 '取数,bcd2dec转换
             Ts(j) = Str(b)
             Ts(j) = Format(ts(j) , "00")
          Next J
          Locate 2 , 1
          Lcd "" ; Ts(3) ; ":" ; Ts(2) ; ":" ; Ts(1)
          Locate 1 , 1
          Lcd "20" ; Ts(7) ; "-" ; Ts(5) ; "-" ; Ts(4) ; " " ; Ts(6) ; "day"
          Ad = 127
      Elseif S = 1 Then
         Miao = Str(s3)
         Fen = Str(s2)
         Shi = Str(s1)
         Miao = Format(miao , "00")
         Fen = Format(fen , "00")
         Shi = Format(shi , "00")
         Locate 2 , 1
         Lcd Shi ; ":" ; Fen ; ":" ; Miao
         A = 129
         Call Begin
         Call Outbit(a)
         Call Inbit(d)
         Call Finish
         If D <> B Then
            S3 = S3 + 1
            If S3 > 59 Then
               S2 = S2 + 1
               S3 = 0
               If S2 > 59 Then
                  S1 = S1 + 1
                  S2 = 0
                  S3 = 0
               End If
            End If
         End If
            B = D
      End If

If Pinc.2 = 0 Then                                        '选择调试
   Waitms 20
   If Pinc.2 = 0 Then
      Incr Tt
      If Tt > 7 Then Tt = 0

   End If
End If

For J = 1 To 30
      W1 = Getadc(1)
      W = W + W1
Next J
      W = W / 30
      W = W * 2560
      W = W / 1094
      W_adc = Str(w)
      W_adc = Format(w_adc , "00.0")
      Locate 2 , 12
      Lcd W_adc ; "C"

If Tt <> 0 Then
   Tq = Ts(tt)
   Ts(tt) = ""
   Locate 2 , 3
   Lcd Ts(3) ; ":" ; Ts(2) ; ":" ; Ts(1)
   Locate 1 , 1
   Lcd "20" ; Ts(7) ; "-" ; Ts(5) ; "-" ; Ts(4) ; " " ; Ts(6) ; "day"
   Ts(tt) = Tq
   Waitms 800

If Pinc.4 = 0 Or Pinc.3 = 0 Then
   Waitms 20
   If Pinc.4 = 0 Then                                     '数字加
      B = Val(ts(tt))
      Incr B
   Elseif Pinc.3 = 0 Then                                 '数字减
      B = Val(ts(tt))
      Decr B
   End If
      T(tt) = Makebcd(b)
      C = Tt * 2
      Ax = Ax + C
      A = Ax
      Call Begin                                          '写入使能
      Call Outbit(a)                                    '首先写入地址
      A = T(tt)
      Call Outbit(a)                                    '然后写入数据
      Call Finish                                       '写入后结束本次写入
      Ax = 126
End If
End If

If Pinc.4 = 0 And Tt = 0 Then                           '启动秒表程序段
    Waitms 20
    If Pinc.4 = 0 Then
       Shi = "00"
       Fen = "00"
       Miao = "00"
       S1 = 0
       S2 = 0
       S3 = 0
       S = 1
       B = 0
       A = 129
       Bitwait Pinc.4 , Set
       Cls
       Call Begin
       Call Outbit(a)
       Call Inbit(b)
       Call Finish

    End If
End If

If Pinc.3 = 0 And S = 1 Then                              '停止秒表
   Waitms 20
   If Pinc.3 = 0 Then
   S = 0
   Cls
   Bitwait Pinc.3 , Set
   End If
End If
Loop
End

Sub Outbit(a As Byte )                                    '发送数据子程序
   Local Temp As Byte , Tempi As Byte , I As Byte
   Ddrb.4 = 1
   Portb.4 = 0
   Ddrb.3 = 1
   Portb.3 = 0
   For I = 0 To 7
      Portb.4 = 0
      Temp = 2 ^ I
      Tempi = A And Temp
      If Tempi = 0 Then
         Portb.3 = 0
         Else
         Portb.3 = 1
      End If
      Portb.4 = 1
   Next I
End Sub

Sub Inbit(indat As Byte )                                 '接收数据的子程序
   Local Readtemp As Byte , Temp As Byte , I As Byte
   Ddrb.4 = 1
   Portb.4 = 1
   Indat = 0
   Readtemp = 0
   Ddrb.3 = 0
   Portb.3 = 1
   For I = 0 To 7
      Portb.4 = 1                                           '高电位换数据
      Portb.4 = 0
      If Pinb.3 = 1 Then
         Temp = 2 ^ I
         Readtemp = Readtemp + Temp
         Elseif Pinb.3 = 0 Then
         Temp = 0
      End If
   Next I
   Indat = Readtemp
   Portb.4 = 0
End Sub

Sub Finish                                                '结束操作子程序
   Ddrb.4 = 0
   Portb.4 = 0
   Ddrb.5 = 1
   Portb.5 = 0
End Sub

Sub Begin                                                   '开始操作子程序
   Ddrb.5 = 1
   Portb.5 = 1
   Ddrb.4 = 1
   Portb.4 = 0
End Sub

jianjun42 发表于 2009-11-1 17:24:48

本实验再次更新,加入秒表功能,在正常走时中,按下S1键启动秒表,按下S2键停止秒表,再加上前面所述的测温功能,代码如下:
'这是一个M8+DS1302的数字钟程序
'portb.5接DS1302的RST,portb.4接sclk,portb.3接I/O?
'本机采用三键结构,其中pinc.2为选择调试键,pinc.4为数字加键,pinc.3为数字减键,相关数值调整后同步写入DS1302相应的寄存器。

$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 32                                             ' 设置堆栈大小
$swstack = 10
$framesize = 40
Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2
Config Lcd = 16 * 2
Config Adc = Single , Prescaler = Auto , Reference = Internal
Cursor Off
Declare Sub Outbit(a As Byte)                               '发送字节
Declare Sub Inbit(indat As Byte)                            '接收字节
Declare Sub Finish                                          '结束操作
Declare Sub Begin                                           '开始写入
Dim A As Byte
Dim B As Byte
Dim C As Byte
Dim D As Byte
Dim J As Byte
Dim Ax As Byte , Ad As Byte
Dim T(7) As Byte , Ts(7) As String * 2 , Tq As String * 2 , Ta As String * 2
Dim Tt As Byte
Dim W As Long , W1 As Word , W_adc As String * 4
Dim Shi As String * 2 , Fen As String * 2 , Miao As String * 2 , S As Bit , S1 As Byte , S2 As Byte , S3 As Byte , S4 As Byte
Start Adc
Call Begin                                                '充电设定
A = &H90                                                    '地址144
Call Outbit(a )                                             '写入地址
A = &B10101010                                              '允许充电。电阻4K,两个二极管
Call Outbit(a)                                              '写入充电设置
Call Finish                                                 '结束操作
Waitms 10
Cls
Ax = 126
Ad = 127
Tt = 0
B = 0
C = 0
W = 0
W1 = 0
S = 0
D = 0
Do

      If S = 0 Then
         For J = 1 To 7
             Ad = Ad + 2
             A = Ad
             Call Begin
             Call Outbit(a)                                 '写入读取数据的地址
             Call Inbit(b)                                  '读取数据
             Call Finish                                    '结束操作
             B = Makedec(b)                                 '取数,bcd2dec转换
             Ts(j) = Str(b)
             Ts(j) = Format(ts(j) , "00")
          Next J
          Locate 2 , 1
          Lcd "" ; Ts(3) ; ":" ; Ts(2) ; ":" ; Ts(1)
          Locate 1 , 1
          Lcd "20" ; Ts(7) ; "-" ; Ts(5) ; "-" ; Ts(4) ; " " ; Ts(6) ; "day"
          Ad = 127
      Elseif S = 1 Then
         Miao = Str(s3)
         Fen = Str(s2)
         Shi = Str(s1)
         Miao = Format(miao , "00")
         Fen = Format(fen , "00")
         Shi = Format(shi , "00")
         Locate 2 , 1
         Lcd Shi ; ":" ; Fen ; ":" ; Miao
         A = 129
         Call Begin
         Call Outbit(a)
         Call Inbit(d)
         Call Finish
         If D <> B Then
            S3 = S3 + 1
            If S3 > 59 Then
               S2 = S2 + 1
               S3 = 0
               If S2 > 59 Then
                  S1 = S1 + 1
                  S2 = 0
                  S3 = 0
               End If
            End If
         End If
            B = D
      End If

If Pinc.2 = 0 Then                                        '选择调试
   Waitms 20
   If Pinc.2 = 0 Then
      Incr Tt
      If Tt > 7 Then Tt = 0

   End If
End If

For J = 1 To 30
      W1 = Getadc(1)
      W = W + W1
Next J
      W = W / 30
      W = W * 2560
      W = W / 1094
      W_adc = Str(w)
      W_adc = Format(w_adc , "00.0")
      Locate 2 , 12
      Lcd W_adc ; "C"

If Tt <> 0 Then
   Tq = Ts(tt)
   Ts(tt) = ""
   Locate 2 , 3
   Lcd Ts(3) ; ":" ; Ts(2) ; ":" ; Ts(1)
   Locate 1 , 1
   Lcd "20" ; Ts(7) ; "-" ; Ts(5) ; "-" ; Ts(4) ; " " ; Ts(6) ; "day"
   Ts(tt) = Tq
   Waitms 800

If Pinc.4 = 0 Or Pinc.3 = 0 Then
   Waitms 20
   If Pinc.4 = 0 Then                                     '数字加
      B = Val(ts(tt))
      Incr B
   Elseif Pinc.3 = 0 Then                                 '数字减
      B = Val(ts(tt))
      Decr B
   End If
      T(tt) = Makebcd(b)
      C = Tt * 2
      Ax = Ax + C
      A = Ax
      Call Begin                                          '写入使能
      Call Outbit(a)                                    '首先写入地址
      A = T(tt)
      Call Outbit(a)                                    '然后写入数据
      Call Finish                                       '写入后结束本次写入
      Ax = 126
End If
End If

If Pinc.4 = 0 And Tt = 0 Then                           '启动秒表程序段
    Waitms 20
    If Pinc.4 = 0 Then
       Shi = "00"
       Fen = "00"
       Miao = "00"
       S1 = 0
       S2 = 0
       S3 = 0
       S = 1
       B = 0
       A = 129
       Bitwait Pinc.4 , Set
       Cls
       Call Begin
       Call Outbit(a)
       Call Inbit(b)
       Call Finish

    End If
End If

If Pinc.3 = 0 And S = 1 Then                              '停止秒表
   Waitms 20
   If Pinc.3 = 0 Then
   S = 0
   Cls
   Bitwait Pinc.3 , Set
   End If
End If
Loop
End

Sub Outbit(a As Byte )                                    '发送数据子程序
   Local Temp As Byte , Tempi As Byte , I As Byte
   Ddrb.4 = 1
   Portb.4 = 0
   Ddrb.3 = 1
   Portb.3 = 0
   For I = 0 To 7
      Portb.4 = 0
      Temp = 2 ^ I
      Tempi = A And Temp
      If Tempi = 0 Then
         Portb.3 = 0
         Else
         Portb.3 = 1
      End If
      Portb.4 = 1
   Next I
End Sub

Sub Inbit(indat As Byte )                                 '接收数据的子程序
   Local Readtemp As Byte , Temp As Byte , I As Byte
   Ddrb.4 = 1
   Portb.4 = 1
   Indat = 0
   Readtemp = 0
   Ddrb.3 = 0
   Portb.3 = 1
   For I = 0 To 7
      Portb.4 = 1                                           '高电位换数据
      Portb.4 = 0
      If Pinb.3 = 1 Then
         Temp = 2 ^ I
         Readtemp = Readtemp + Temp
         Elseif Pinb.3 = 0 Then
         Temp = 0
      End If
   Next I
   Indat = Readtemp
   Portb.4 = 0
End Sub

Sub Finish                                                '结束操作子程序
   Ddrb.4 = 0
   Portb.4 = 0
   Ddrb.5 = 1
   Portb.5 = 0
End Sub

Sub Begin                                                   '开始操作子程序
   Ddrb.5 = 1
   Portb.5 = 1
   Ddrb.4 = 1
   Portb.4 = 0
End Sub

jtfj 发表于 2009-11-2 18:48:38

DS1302一天相差1s能不能修正

jianjun42 发表于 2009-11-3 10:35:07

选择精度较高的32768KHZ的晶振和通过调整晶振外接电容容量可以微调定时精度

wang_xm 发表于 2010-5-1 23:29:23

有营养

wexm2005 发表于 2010-7-7 10:09:05

有没有用ICC编的?

gpzdc986 发表于 2010-7-7 14:27:57

mark

pingguo2012 发表于 2010-10-31 01:21:30

强人

wzr200408 发表于 2010-10-31 09:20:22

支持,我看不懂

LQH2010 发表于 2010-11-21 13:35:08

强!

fsj5098@hotmail 发表于 2015-3-9 15:06:17

支持,我看不懂
页: [1]
查看完整版本: 分享我的M8+DS1302+LCD1602电子钟