[问答] 求助,ds1302和lcd1602汇编程序能帮忙看下吗
2017-12-18 15:06:46  947 ds1302 lcd1602
收藏 0 收藏 推荐 0 推荐
分享
我根据网上查找的资料,写了ds1302和lcd1602的汇编程序,lcd1602的程序单独测试过了,能够显示出我想要的字符,但是1302的程序怎么也用不了,我再查资料看了感觉也没有什么问题,编的程序都是没有错误,没有警告的,但是就是用不了,已经调试差不多一周了,实在找不出来,希望大家能帮忙看看

/***主函数先设置定时器,定时时间一到就显示
程序先初始化ds1302,初始化1602,然后调用键盘程序判断是不是有按键按下了,有的话就执行相应的功能,然后
最初F0应该是0的,如果没有按DS_STR,F0也是0,这样回到主程序,然后把时间分成高低位,去显示。
如果按了DS_ZT,就是暂停,F0=0,这样暂停时钟。如果按了DS_STR,F0=1,使得DS1302开始走时,主程序就跳到
都时间的程序,然后显示。再从访问按键的程序开始循环。
**/////
E BIT P2.7
WRT BIT P2.5
RS BIT P2.6
CE BIT P3.5
//////****************1602定义
DSADDR EQU 30H
DSDATA EQU 31H
SCLK BIT P3.6
RST  BIT P3.5
IO1302 BIT P3.4

SEC EQU 32H
MIN EQU 33H
HOUR EQU 34H
DATE EQU 35H
MONTH EQU 36H
WEEK EQU 37H
YEAR EQU 38H

SECL EQU 39H
SECH EQU 40H
MINL EQU 41H
MINH EQU 42H
HOURL EQU 43H
HOURH EQU 44H
DATEL EQU 45H
DATEH EQU 46H
MONTHL EQU 47H
MONTHH EQU 48H
WEEKL EQU 49H
WEEKH EQU 50H
YEARL EQU 51H
YEARH EQU 52H

//////**********1302内存定义
LIE EQU 53H
HANG EQU 54H
ANJIAN EQU 55H
///////////*************矩阵键盘定义
ORG 00H
LJMP MAIN
ORG 0BH
LJMP T0INT
ORG 70H
MAIN:
MOV SP,#60H                                 
MOV TMOD,#01H                          //设置定时器的参数
MOV TH0,#3CH
MOV TL0,#0B0H
MOV R0,#10H
SETB EA                                        //打开中断
SETB ET0
SETB TR0
LCALL INIT_1302
LCALL LCD1602_INIT

MAIN1:
LCALL KEY
JB F0,MAIN2                                 ///F0为1的时候就读1302的时间然后显示出来
LCALL WT_1302
MOV DSDATA,SEC
LCALL GDW_1302
MOV DSDATA,MIN
LCALL GDW_1302
MOV DSDATA,HOUR
LCALL GDW_1302
MOV DSDATA,DATE
LCALL GDW_1302
MOV DSDATA,MONTH
LCALL GDW_1302
MOV DSDATA,WEEK
LCALL GDW_1302
MOV DSDATA,YEAR
LCALL GDW_1302
LJMP MAIN3                         ///F0为0的时候就写时间,把时间的值分为高低位,读出来,然后显示
MAIN2:
LCALL RT_1302
MAIN3:
JNB 7CH,MAIN1
CLR 7CH
LCALL DISPT_1602
LJMP MAIN1


////////****************判断按键程序4*4矩阵键盘 用p1口
KEY:
MOV P1,#0F0H
LCALL DELAY10MS
MOV HANG,#00H
MOV A,P1                                        //key程序判断矩阵键盘到底是哪一个按键按下的
ANL A,#0F0H                                        //比如用#23记住为第三行第四列的按键
CJNE A,#0F0H,L

L:
LCALL DELAY10MS
MOV A,P1
JB ACC.4,L1
MOV LIE,#00H
LJMP Q

L1:
JB ACC.5,L2
MOV LIE,#01H
LJMP Q

L2:
JB ACC.6,L3
MOV LIE,#02H
LJMP Q

L3:
MOV LIE,#03H
LJMP Q

Q:
MOV P1,#0FH
LCALL DELAY10MS
MOV A,P1
ANL A,#0FH
JB ACC.0,Q1
MOV HANG,#00H
LJMP PANDUAN

Q1:
JB ACC.1,Q2
MOV HANG,#10H
LJMP PANDUAN

Q2:
JB ACC.2,Q3
MOV HANG,#20H
LJMP PANDUAN

Q3:
MOV HANG,#30H
LJMP PANDUAN

PANDUAN:
MOV A,LIE                                        //记下的按键,然后分别给每个按键定义功能
ADD A,HANG
MOV ANJIAN,A
MOV R2,A
CJNE R2,#00H,AJ1                        //年的加的功能
LJMP YEAR_ADD

AJ1:
CJNE R2,#01H,AJ2                         //年的减的功能
LJMP YEAR_SUB

AJ2:
CJNE R2,#02H,AJ3                          //周的加的功能
LJMP WEEK_ADD

AJ3:
CJNE R2,#03H,AJ4                        //周的减的功能
LJMP WEEK_SUB

AJ4:
CJNE R2,#10H,AJ5                        //月的加的功能
LJMP MONTH_ADD

AJ5:
CJNE R2,#11H,AJ6
LJMP MONTH_SUB                         //月的减的功能

AJ6:
CJNE R2,#12H,AJ7                   //日期加的功能
LJMP DATE_ADD

AJ7:
CJNE R2,#13H,AJ8                 //日期减的功能
LJMP DATE_SUB

AJ8:
CJNE R2,#20H,AJ9
LJMP HOUR_ADD                         //小时加的功能

AJ9:
CJNE R2,#21H,AJ10                //小时减的功能
LJMP HOUR_SUB

AJ10:
CJNE R2,#22H,AJ11                   //分钟加的功能
LJMP MIN_ADD

AJ11:
CJNE R2,#23H,AJ12                  //分钟减的功能
LJMP MIN_SUB

AJ12:
CJNE R2,#30H,AJ13                   //秒加的功能
LJMP SEC_ADD

AJ13:
CJNE R2,#31H,AJ14                  //秒减的功能
LJMP SEC_SUB

AJ14:
CJNE R2,#32H,AJ15
LJMP DS_STR                                   //设定F0等于1,ds1302开始走时

AJ15:
LJMP DS_ZT                                   //设定F0等于0,ds1302暂停走时

YEAR_ADD:
MOV A,YEAR
ADD A,#01H
DA A                                                  //按下一次年加一,如果超过99,变成0,再给年到寄存器
CJNE A,#99H,YA
MOV A,#00H
YA:
MOV YEAR,A
LJMP FANHUI

YEAR_SUB:
MOV A,YEAR                                           //按下一次年减一,如果到0,变成99,再给年到寄存器
SUBB A,#01H
DA A
CJNE A,#00H,YS
MOV A,#99H                                           //以下同理
YS:
MOV YEAR,A
LJMP FANHUI

WEEK_ADD:
MOV A,WEEK
ADD A,#01H
DA A
CJNE A,#07H,WA
MOV A,#01H
WA:
MOV WEEK,A
LJMP FANHUI

WEEK_SUB:
MOV A,WEEK
SUBB A,#01H
DA A
CJNE A,#00H,WS
MOV A,#07H
WS:
MOV WEEK,A
LJMP FANHUI

MONTH_ADD:
MOV A,MONTH
ADD A,#01H
DA A
CJNE A,#12H,MA
MOV A,#01H
MA:
MOV MONTH,A
LJMP FANHUI

MONTH_SUB:
MOV A,MONTH
SUBB A,#01H
DA A
CJNE A,#00H,MS
MOV A,#12H
MS:
MOV MONTH,A
LJMP FANHUI

DATE_ADD:
MOV A,DATE
ADD A,#01H
DA A
CJNE A,#32H,DA1
MOV A,#01H
DA1:
MOV DATE,A
LJMP FANHUI

DATE_SUB:
MOV A,DATE
SUBB A,#01H
DA A
CJNE A,#00H,DS1
MOV A,#32H
DS1:
MOV DATE,A
LJMP FANHUI

HOUR_ADD:
MOV A,HOUR
ADD A,#01H
DA A
CJNE A,#24H,HA
MOV A,#00H
HA:
MOV HOUR,A
LJMP FANHUI

HOUR_SUB:
MOV A,HOUR
SUBB A,#01H
DA A
CJNE A,#00H,HS
MOV A,#24H
HS:
MOV HOUR,A
LJMP FANHUI

MIN_ADD:
MOV A,MIN
ADD A,#01H
DA A
CJNE A,#60H,MINA
MOV A,#00H
MINA:
MOV MIN,A
LJMP FANHUI

MIN_SUB:
MOV A,MIN
SUBB A,#01H
DA A
CJNE A,#00H,MINS
MOV A,#60H
MINS:
MOV MIN,A
LJMP FANHUI

SEC_ADD:
MOV A,SEC
ADD A,#01H
DA A
CJNE A,#60H,SA
MOV A,#00H
SA:
MOV SEC,A
LJMP FANHUI

SEC_SUB:
MOV A,SEC
SUBB A,#01H
DA A
CJNE A,#00H,SS
MOV A,#60H
SS:
MOV SEC,A
LJMP FANHUI

DS_STR:
MOV DSADDR,#80H                                          //按下按键,把秒写入,ds1302走时
MOV DSDATA,SEC
LCALL XIE1302
MOV DSADDR,#8EH                                          //打开写保护,F0置1
MOV DSDATA,#80H
LCALL XIE1302
SETB F0
LJMP FANHUI

DS_ZT:
MOV DSADDR,#8EH
MOV DSDATA,#00H                                          //关闭写保护
LCALL XIE1302
MOV A,SEC
ADD A,#80H                                                  //把秒的最高为置1,写入ds1302,让它暂停,F0=0
DA A
MOV SEC,A
MOV DSADDR,#80H
MOV DSDATA,SEC
LCALL XIE1302
CLR F0
LJMP FANHUI


FANHUI:                                                           //返回
RET

DELAY10MS:   ;误差 0us                          //用来消抖
    MOV R7,#01H
DL4:
    MOV R6,#26H
DL3:
    MOV R5,#82H
    DJNZ R5,$
    DJNZ R6,DL3
    DJNZ R7,DL4
    RET


//////****************1302写命令函数
XIE1302:
CLR SCLK
NOP
SETB RST
NOP                                                                           //用DSADDR记住地址,DSDATA记住值,写入
MOV A,DSADDR
MOV R1,#08H
XIE1:   
RRC A
NOP
MOV IO1302,C
NOP
SETB SCLK
NOP
CLR SCLK
DJNZ  R1,XIE1
MOV A,DSDATA
MOV R1,#08H
XIE2:   
RRC A
NOP
MOV IO1302,C
NOP
SETB SCLK
NOP
CLR SCLK
DJNZ R1,XIE2
CLR RST
RET

//////****************1302读数据函数
DU1302:      
CLR SCLK
NOP
NOP
SETB RST
NOP                                                                   //用DSADDR记住地址,DSDATA记住值,读出来
NOP                                                                  
MOV A,DSADDR
MOV R1,#08H
DU1:     
CLR SCLK
NOP
NOP
RRC A
NOP
NOP
MOV IO1302,C
NOP
NOP
SETB SCLK
DJNZ R1,DU1
MOV R1,#08H
CLR A
NOP
CLR C
NOP
DU2:     
CLR SCLK
NOP
NOP
MOV C,IO1302
NOP
NOP
RRC A
NOP
NOP
SETB SCLK
NOP
NOP
DJNZ R1,DU2
NOP
MOV DSDATA,A
NOP
RET

////////******************1302初始化函数
INIT_1302:   
MOV  DSADDR,#8EH   ;允许写1302,关闭写保护
MOV  DSDATA,#00H
LCALL XIE1302

MOV DSADDR,#80H   ;1302停止振荡
MOV DSDATA,#80H
LCALL XIE1302

MOV DSDATA,#00H
MOV DSADDR,#8CH   ;年
LCALL XIE1302

MOV DSDATA,#00H        ;月
MOV DSADDR,#88H
LCALL XIE1302

MOV DSDATA,#00H
MOV DSADDR,#86H       ;日
LCALL XIE1302

MOV DSDATA,#23H
MOV DSADDR,#84H     ;时
LCALL XIE1302

MOV DSDATA,#05H
MOV DSADDR,#82H      ;分
LCALL XIE1302

MOV DSDATA,#00H        ;周
MOV DSADDR,#8AH
LCALL XIE1302

MOV DSDATA,#00H
MOV DSADDR,#80H   ;1302开始振荡
LCALL XIE1302

MOV DSADDR,#8EH   ;禁止写入1302
MOV DSDATA,#80H
LCALL XIE1302
RET

//////*********1302取时间高低位函数
GDW_1302:
MOV R3,#00H
MOV R4,#00H
MOV A,DSDATA
ANL A,#0FH                                   //高低位分别与0FH,取出各自的高低位保存
MOV R3,A
MOV A,DSDATA
SWAP A
ANL A,#0FH
MOV R4,A
RET


//////*********1302读时间函数
RT_1302:
MOV DSADDR,#8DH                                 //读时间,然后分别保存它们的高低位,应该不用关闭写保护了吧
MOV DSDATA,#00H
LCALL DU1302
LCALL GDW_1302
MOV YEARL,R3
MOV YEARH,R4

MOV DSADDR,#8BH
MOV DSDATA,#00H
LCALL DU1302
LCALL GDW_1302
MOV WEEKL,R3
MOV WEEKH,R4

MOV DSADDR,#89H
MOV DSDATA,#00H
LCALL DU1302
LCALL GDW_1302
MOV MONTHL,R3
MOV MONTHH,R4

MOV DSADDR,#87H
MOV DSDATA,#00H
LCALL DU1302
LCALL GDW_1302
MOV DATEL,R3
MOV DATEH,R4

MOV DSADDR,#85H
MOV DSDATA,#00H
LCALL DU1302
LCALL GDW_1302
MOV HOURL,R3
MOV HOURH,R4

MOV DSADDR,#83H
MOV DSDATA,#00H
LCALL DU1302
LCALL GDW_1302
MOV MINL,R3
MOV MINH,R4

MOV DSADDR,#81H
MOV DSDATA,#00H
LCALL DU1302
LCALL GDW_1302
MOV SECL,R3
MOV SECH,R4

RET

/////////////*************1302写时间函数
WT_1302:
MOV DSADDR,#8EH
MOV DSDATA,#00H                                  //把现在的时间全部写入1302
LCALL XIE1302

MOV DSADDR,#80H
MOV DSDATA,#80H
LCALL XIE1302

MOV DSADDR,#8CH
MOV DSDATA,YEAR
LCALL XIE1302

MOV DSADDR,#8AH
MOV DSDATA,WEEK
LCALL XIE1302

MOV DSADDR,#88H
MOV DSDATA,MONTH
LCALL XIE1302

MOV DSADDR,#86H
MOV DSDATA,DATE
LCALL XIE1302

MOV DSADDR,#84H
MOV DSDATA,HOUR
LCALL XIE1302

MOV DSADDR,#82H
MOV DSDATA,MIN
LCALL XIE1302

MOV DSADDR,#80H
MOV DSDATA,SEC
LCALL XIE1302

RET
/////////////************1602显示时间函数
DISPT_1602:
MOV A,#30H
ORL YEARL,A
ORL YEARH,A
ORL WEEKL,A                                         //因为1602里面有记住的字符,把时间转换成ASCII码可以减少麻烦,不用再用DPTR
ORL WEEKH,A
ORL MONTHL,A
ORL MONTHH,A
ORL DATEL,A
ORL DATEH,A
ORL HOURL,A
ORL HOURH,A                                   //加30转换成ASCII码
ORL MINL,A
ORL MINH,A
ORL SECL,A
ORL SECH,A

LCALL LCD1602_INIT
MOV A,#80H
LCALL LCD1602_CMD
MOV A,#'2'
LCALL LCD1602_DATA

MOV A,#'0'
LCALL LCD1602_DATA
MOV A,YEARH
LCALL LCD1602_DATA
MOV A,YEARL
LCALL LCD1602_DATA
MOV A,#'.'
LCALL LCD1602_DATA

MOV A,MONTHH
LCALL LCD1602_DATA
MOV A,MONTHL
LCALL LCD1602_DATA
MOV A,#'.'
LCALL LCD1602_DATA

MOV A,DATEH
LCALL LCD1602_DATA
MOV A,DATEL
LCALL LCD1602_DATA
MOV A,#' '
LCALL LCD1602_DATA

MOV A,#'W'
LCALL LCD1602_DATA
MOV A,#'E'
LCALL LCD1602_DATA
MOV A,#'E'
LCALL LCD1602_DATA
MOV A,#'K'
LCALL LCD1602_DATA
MOV A,':'
LCALL LCD1602_DATA
MOV A,WEEKL
LCALL LCD1602_DATA

MOV A,HOURH
LCALL LCD1602_DATA
MOV A,HOURL
LCALL LCD1602_DATA
MOV A,#':'
LCALL LCD1602_DATA

MOV A,MINH
LCALL LCD1602_DATA
MOV A,MINL
LCALL LCD1602_DATA
MOV A,#':'
LCALL LCD1602_DATA

MOV A,SECH
LCALL LCD1602_DATA
MOV A,SECL
LCALL LCD1602_DATA

RET



//////****************1602写数据函数
LCD1602_DATA:
LCALL CHECK_BUSY1602
CLR E
SETB RS
CLR WRT
MOV P0,A
NOP
SETB E
NOP
CLR E
RET

//////****************1602写命令函数
LCD1602_CMD:
LCALL CHECK_BUSY1602
CLR E
CLR RS
CLR WRT                                                         //直接把A写入1602
MOV P0,A
NOP
SETB E
NOP
CLR E
RET

//////****************1602初始化函数
LCD1602_INIT:
LCALL DELAY5MS
MOV A,#38H
LCALL LCD1602_CMD
MOV A,#0CH
LCALL LCD1602_CMD                                  //初始化1602,延迟是好像原来不加不对
LCALL DELAY5MS
LCALL DELAY5MS
MOV A,#06H
LCALL LCD1602_CMD
MOV A,#01H
LCALL LCD1602_CMD
MOV A,#80H
LCALL LCD1602_CMD
RET

////////****************1602查忙程序
CHECK_BUSY1602:
PUSH  ACC
MOV   P0, #255
CLR   RS                                           //PUSH和POP原来单独测试1602的时候不加就用不了,初始化失败,不知道为什么
SETB  WRT
BUSYLOOP:
SETB  E
NOP
MOV   A,P0
CLR   E
JB    ACC.7, BUSYLOOP
POP   ACC
RET

DELAY5MS:
    MOV   R6, #10
DL1:DJNZ  R7, $
    DJNZ  R6, DL1
    RET

////*************
T0INT:
MOV TH0,#3CH
MOV TL0,#0B0H                                          //T0定时器中断,就是隔一段时间读1302的时间用
DJNZ R0,RTT0
MOV R0,#10
SETB 7CH
RTT0:
RET


END


2017-12-18 15:06:46   评论 邀请回答
7个回答
我自己认为可能错误出现在ds1302上面,但是我再对照资料看过了,感觉编的程序是没有问题的啊,修改了也还是没有反应
2017-12-18 15:16:52 评论

举报

有人帮忙看看吗 或者能够帮忙给一个ds1302的汇编例子吗 我找到的都用不了
2017-12-18 21:11:34 评论

举报

你的程序最好分开调试,1602正常了,就调1302的显示,也就是把1302的时间读出来显示,你现在的程序增加了按键,以及
MAIN3:
JNB 7CH,MAIN1
CLR 7CH
LCALL DISPT_1602这里有一个对7CH的判断,如果这个7CH判断不成立,也就不会显示时间了。
不论是汇编还是C语言,最好是每个功能模块的单独调试,都调试好了,再进行合并调试。
1302除了读取和写入的正确外,还要注意硬件是否有故障,比如1302的晶振,如果坏了,时间就不走了
2017-12-19 10:21:13 评论

举报

编写程序要使用制表符,要把标号和代码语句错开,这样查看起来方便,你现在贴出来的程序,找标号都不好找,好的程序编写格式有助于编写,查看以及纠错。
2017-12-19 10:27:37 评论

举报

T0INT:
MOV TH0,#3CH
MOV TL0,#0B0H                                          //T0定时器中断,就是隔一段时间读1302的时间用
DJNZ R0,RTT0
MOV R0,#10
SETB 7CH
RTT0:
RET
汇编里不适合在中断里直接使用R0这类的寄存器,最好使用全局变量,如果一定要使用的话,就需要进行压栈,出栈处理,因为当程序大了以后,很难确定在中断里使用的R0类寄存器是否在外部也使用了,这样会造成不可预料的错误,也不好查找
2017-12-19 10:33:53 评论

举报

人中狼 发表于 2017-12-19 10:33
T0INT:
MOV TH0,#3CH
MOV TL0,#0B0H                                          //T0定时器中断,就是隔一段时间读1302的时间用

谢谢提醒
2017-12-19 15:20:43 评论

举报


根据您的建议,我分开调试已经解决了,谢谢您
2017-12-21 12:36:53 评论

举报

撰写答案

你正在撰写答案

如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。

高级模式
您需要登录后才可以回帖 登录 | 注册

提问题
关闭

站长推荐 上一条 /9 下一条

快速回复 返回顶部 返回列表