星夜湖畔,寒风拂

星夜湖畔,寒风拂 查看完整档案

填写现居城市  |  填写毕业院校  |  填写所在公司/组织填写个人主网站
编辑
_ | |__ _ _ __ _ | '_ \| | | |/ _` | | |_) | |_| | (_| | |_.__/ \__,_|\__, | |___/ 个人简介什么都没有

个人动态

星夜湖畔,寒风拂 提出了问题 · 2020-10-22

c51 1602显示ds1302时间不正常?

定时器定时,每秒读取一次ds1302时间。
第一次能够成功读取预设时间,之后就不正常。
1.ds1302头文件

#ifndef _DS1302_H_
#define _DS1302_H_
#include <reg52.h>

sbit DS1302_IO = P3^4;            //ds1302串行数据引脚
sbit DS1302_CE = P3^5;            //ds1302使能引脚、复位引脚
sbit DS1302_CK = P3^6;            //ds1302串行时钟引脚

void DS1302BurstInit();                                //ds1302突发模式初始化
void ds1302BurstRead(unsigned char *dat);            //ds1302突发模式连续读

#endif

2.ds1302文件

#include "ds1302.h"

//ds1302写字节操作(低位->高位),上升沿写
void ds1302ByteWrite(unsigned char dat) {
    unsigned char i=0;
    
    for(i=0; i<8; i++) {
        DS1302_IO = dat & 0x01;
        dat >>= 1;
        DS1302_CK = 1;
        DS1302_CK = 0;
    }
}

//ds1302读字节操作(低位->高位),下降沿读
unsigned char ds1302ByteRead() {
    unsigned char i=0, dat=0;
    
    for(i=0; i<8; i++) {
        dat >>= 1;
        dat |= (unsigned char)DS1302_IO << 7;
        
        DS1302_CK = 1;
        DS1302_CK = 0;
    }
    
    return dat;
}

//ds1302单次写操作(向某一寄存器写入一个字节)
void ds1302SingleWrite(unsigned char addr, unsigned char dat) {
    DS1302_CE = 1;
    ds1302ByteWrite(addr);
    ds1302ByteWrite(dat);
    DS1302_CE = 0;
}

//ds1302单次读操作(从某一寄存器读出一个字节)
unsigned char ds1302SingleRead(unsigned char addr) {
    unsigned char dat = 0;
    
    DS1302_CE = 1;
    ds1302ByteWrite(addr);
    dat = ds1302ByteRead();
    DS1302_CE = 0;
    
    DS1302_CK = 1;
    DS1302_IO = 1;
    DS1302_IO = 0;
    
    return dat;
}

//ds1302突发模式写操作(连续写入8个字节)
void ds1302BurstWrite(unsigned char *dat) {
    unsigned char i=0;
    
    DS1302_CE = 1;
    ds1302ByteWrite(0xBE);                    //发送突发写寄存器指令
    //连续写入8个字节
    for(i=0; i<8; i++) {
        ds1302ByteWrite(dat[i]);
    }
    DS1302_CE = 0;
}

//ds1302突发模式读操作(连续读取8个字节)
void ds1302BurstRead(unsigned char *dat) {
    unsigned char i=0;
    
    DS1302_CE = 1;
    ds1302ByteWrite(0xBF);                    //发送突发读寄存器指令
    //连续读取8个字节
    for(i=0; i<8; i++) {
        *dat++ = ds1302ByteRead();
        
    }
    DS1302_CE = 0;
}

//ds1302突发模式初始化
void DS1302BurstInit() {
    unsigned char ch=0;                        //时钟停止标志位
    
    //初始化时间(秒、分、时、日、月、星期、年、写保护位)(2000年1月1日星期六 00:00:00)
    unsigned char code InitTime[] = {
        0x00, 0x00, 0x00, 0x01, 0x01, 0x06, 0x00, 0x00
    }; 
    
    //初始化ds1302通信引脚
    DS1302_CE = 0;
    DS1302_CK = 0;
    
    ch = ds1302SingleRead(0x81);            //读取秒寄存器
    //由秒寄存器最高位CH的值判断DS1302是否停止工作(已停止工作则初始化时钟)
    if((ch & 0x80) != 0) {
        ds1302SingleWrite(0x8E, 0x00);        //撤销写保护功能,允许写入数据
        ds1302BurstWrite(InitTime);
    }
    
    ds1302SingleWrite(0x8E, 0x80);            //打开写保护功能,禁止写入数据
}

3.主文件

#include <reg52.h>
#include "ds1302.h"
#include "lcd1602.h"

bit flag200ms;

void timeProcessDisplay(unsigned char *dat);
void ConfigInterrupt();
void Time0();

void main() {
    unsigned char time[8] = {0};
    
    ConfigInterrupt();    
    DS1302BurstInit();
    lcdInit();
    lcdFullclear();
    flag200ms = 1;
    while(1) {
        if(flag200ms) {
            flag200ms = 0;
            
            ds1302BurstRead(time);
            timeProcessDisplay(time);
        }
    }
}

//时间处理及显示
void timeProcessDisplay(unsigned char *dat) {
    static unsigned char secBackup = 0x60;    //秒备份值(判断是否需要刷新显示,确保首次刷新显示)
    unsigned char str[12] = {0};
     
    if(secBackup != dat[0]) {
        lcdFullclear();
        
        str[0]  = '2';
        str[1]  = '0';
        str[2]  = (dat[6] >> 4) + '0';
        str[3]  = (dat[6]&0x0f) + '0';
        str[4]  = '-';
        str[5]  = (dat[4] >> 4) + '0';
        str[6]  = (dat[4]&0x0f) + '0';
        str[7]  = '-';
        str[8]  = (dat[3] >> 4) + '0';
        str[9]  = (dat[3]&0x0f) + '0';
        str[10] = '\0';
        lcdShowStr(0, 2, str);
        
        str[0]  = (dat[5]&0x0f) + '0';
        str[1]  = '\0';
        lcdShowStr(0, 13, str);
        
        str[0]  = (dat[2] >> 4) + '0';
        str[1]  = (dat[2]&0x0f) + '0';
        str[2]  = ':';
        str[3]  = (dat[1] >> 4) + '0';
        str[4]  = (dat[1]&0x0f) + '0';
        str[5]  = ':';
        str[6]  = (dat[0] >> 4) + '0';
        str[7]  = (dat[0]&0x0f) + '0';
        str[8] = '\0';
        lcdShowStr(1, 4, str);
        
        secBackup = dat[0];
    }
}

//中断配置
void ConfigInterrupt() {
    TMOD &= 0xf0;
    TMOD |= 0x01;
    
    //1ms
    TH0 = 0xfc;
    TL0 = 0x82;
    
    ET0 = 1;
    EA  = 1;
    
    TR0 = 0;
}

//定时器0中断
void Time0() interrupt 1 {
    static unsigned char time200ms = 0;
    
    //1ms
    TH0 = 0xfc;
    TL0 = 0x82;
    
    time200ms++;
    if(time200ms >= 200) {
        time200ms = 0;
        flag200ms = 1;
    }
}

lcd1602程序文件应该没问题,就不贴出来占地方了。时间数据处理函数测试过应该也没问题。用的是普中的板子。
烦请网友帮忙看一下哪里出问题了,自己检查好久都没找出来问题。

关注 1 回答 0

星夜湖畔,寒风拂 提出了问题 · 2020-10-22

c51 1602显示ds1302时间不正常?

定时器定时,每秒读取一次ds1302时间。
第一次能够成功读取预设时间,之后就不正常。
1.ds1302头文件

#ifndef _DS1302_H_
#define _DS1302_H_
#include <reg52.h>

sbit DS1302_IO = P3^4;            //ds1302串行数据引脚
sbit DS1302_CE = P3^5;            //ds1302使能引脚、复位引脚
sbit DS1302_CK = P3^6;            //ds1302串行时钟引脚

void DS1302BurstInit();                                //ds1302突发模式初始化
void ds1302BurstRead(unsigned char *dat);            //ds1302突发模式连续读

#endif

2.ds1302文件

#include "ds1302.h"

//ds1302写字节操作(低位->高位),上升沿写
void ds1302ByteWrite(unsigned char dat) {
    unsigned char i=0;
    
    for(i=0; i<8; i++) {
        DS1302_IO = dat & 0x01;
        dat >>= 1;
        DS1302_CK = 1;
        DS1302_CK = 0;
    }
}

//ds1302读字节操作(低位->高位),下降沿读
unsigned char ds1302ByteRead() {
    unsigned char i=0, dat=0;
    
    for(i=0; i<8; i++) {
        dat >>= 1;
        dat |= (unsigned char)DS1302_IO << 7;
        
        DS1302_CK = 1;
        DS1302_CK = 0;
    }
    
    return dat;
}

//ds1302单次写操作(向某一寄存器写入一个字节)
void ds1302SingleWrite(unsigned char addr, unsigned char dat) {
    DS1302_CE = 1;
    ds1302ByteWrite(addr);
    ds1302ByteWrite(dat);
    DS1302_CE = 0;
}

//ds1302单次读操作(从某一寄存器读出一个字节)
unsigned char ds1302SingleRead(unsigned char addr) {
    unsigned char dat = 0;
    
    DS1302_CE = 1;
    ds1302ByteWrite(addr);
    dat = ds1302ByteRead();
    DS1302_CE = 0;
    
    DS1302_CK = 1;
    DS1302_IO = 1;
    DS1302_IO = 0;
    
    return dat;
}

//ds1302突发模式写操作(连续写入8个字节)
void ds1302BurstWrite(unsigned char *dat) {
    unsigned char i=0;
    
    DS1302_CE = 1;
    ds1302ByteWrite(0xBE);                    //发送突发写寄存器指令
    //连续写入8个字节
    for(i=0; i<8; i++) {
        ds1302ByteWrite(dat[i]);
    }
    DS1302_CE = 0;
}

//ds1302突发模式读操作(连续读取8个字节)
void ds1302BurstRead(unsigned char *dat) {
    unsigned char i=0;
    
    DS1302_CE = 1;
    ds1302ByteWrite(0xBF);                    //发送突发读寄存器指令
    //连续读取8个字节
    for(i=0; i<8; i++) {
        *dat++ = ds1302ByteRead();
        
    }
    DS1302_CE = 0;
}

//ds1302突发模式初始化
void DS1302BurstInit() {
    unsigned char ch=0;                        //时钟停止标志位
    
    //初始化时间(秒、分、时、日、月、星期、年、写保护位)(2000年1月1日星期六 00:00:00)
    unsigned char code InitTime[] = {
        0x00, 0x00, 0x00, 0x01, 0x01, 0x06, 0x00, 0x00
    }; 
    
    //初始化ds1302通信引脚
    DS1302_CE = 0;
    DS1302_CK = 0;
    
    ch = ds1302SingleRead(0x81);            //读取秒寄存器
    //由秒寄存器最高位CH的值判断DS1302是否停止工作(已停止工作则初始化时钟)
    if((ch & 0x80) != 0) {
        ds1302SingleWrite(0x8E, 0x00);        //撤销写保护功能,允许写入数据
        ds1302BurstWrite(InitTime);
    }
    
    ds1302SingleWrite(0x8E, 0x80);            //打开写保护功能,禁止写入数据
}

3.主文件

#include <reg52.h>
#include "ds1302.h"
#include "lcd1602.h"

bit flag200ms;

void timeProcessDisplay(unsigned char *dat);
void ConfigInterrupt();
void Time0();

void main() {
    unsigned char time[8] = {0};
    
    ConfigInterrupt();    
    DS1302BurstInit();
    lcdInit();
    lcdFullclear();
    flag200ms = 1;
    while(1) {
        if(flag200ms) {
            flag200ms = 0;
            
            ds1302BurstRead(time);
            timeProcessDisplay(time);
        }
    }
}

//时间处理及显示
void timeProcessDisplay(unsigned char *dat) {
    static unsigned char secBackup = 0x60;    //秒备份值(判断是否需要刷新显示,确保首次刷新显示)
    unsigned char str[12] = {0};
     
    if(secBackup != dat[0]) {
        lcdFullclear();
        
        str[0]  = '2';
        str[1]  = '0';
        str[2]  = (dat[6] >> 4) + '0';
        str[3]  = (dat[6]&0x0f) + '0';
        str[4]  = '-';
        str[5]  = (dat[4] >> 4) + '0';
        str[6]  = (dat[4]&0x0f) + '0';
        str[7]  = '-';
        str[8]  = (dat[3] >> 4) + '0';
        str[9]  = (dat[3]&0x0f) + '0';
        str[10] = '\0';
        lcdShowStr(0, 2, str);
        
        str[0]  = (dat[5]&0x0f) + '0';
        str[1]  = '\0';
        lcdShowStr(0, 13, str);
        
        str[0]  = (dat[2] >> 4) + '0';
        str[1]  = (dat[2]&0x0f) + '0';
        str[2]  = ':';
        str[3]  = (dat[1] >> 4) + '0';
        str[4]  = (dat[1]&0x0f) + '0';
        str[5]  = ':';
        str[6]  = (dat[0] >> 4) + '0';
        str[7]  = (dat[0]&0x0f) + '0';
        str[8] = '\0';
        lcdShowStr(1, 4, str);
        
        secBackup = dat[0];
    }
}

//中断配置
void ConfigInterrupt() {
    TMOD &= 0xf0;
    TMOD |= 0x01;
    
    //1ms
    TH0 = 0xfc;
    TL0 = 0x82;
    
    ET0 = 1;
    EA  = 1;
    
    TR0 = 0;
}

//定时器0中断
void Time0() interrupt 1 {
    static unsigned char time200ms = 0;
    
    //1ms
    TH0 = 0xfc;
    TL0 = 0x82;
    
    time200ms++;
    if(time200ms >= 200) {
        time200ms = 0;
        flag200ms = 1;
    }
}

lcd1602程序文件应该没问题,就不贴出来占地方了。时间数据处理函数测试过应该也没问题。用的是普中的板子。
烦请网友帮忙看一下哪里出问题了,自己检查好久都没找出来问题。

关注 1 回答 0

星夜湖畔,寒风拂 关注了用户 · 2020-10-22

小齐本齐 @xiaoqibenqi

公众号:码农田小齐
回复【666】查看往期文章分类。
回复【进群】有技术交流群/自习打卡群/好文分享群。
回复【01-05】可以获取计算机精选书籍、个人刷题笔记、大厂面经、面试资料等资源~

愿我们一起成为更好的人,期待与你相遇️️

关注 3385

星夜湖畔,寒风拂 关注了专栏 · 2020-10-22

Python数据科学

微信公众号:Python数据科学

关注 7690

星夜湖畔,寒风拂 关注了专栏 · 2020-10-22

进击的大前端

前端工程师,底层技术人。 思否2020年度“Top Writer”! 掘金“优秀作者”! 开源中国2020年度“优秀源创作者” 分享各种大前端进阶知识! 关注公众号【进击的大前端】第一时间获取高质量原创。 更多文章和示例源码请看:https://github.com/dennis-jiang/Front-End-Knowledges

关注 10000

星夜湖畔,寒风拂 关注了专栏 · 2020-10-22

Java进阶路线

java技术分享,从小白到巨人的成长过程

关注 4387

星夜湖畔,寒风拂 关注了专栏 · 2020-10-22

我们一起进大厂

微信搜索:三太子敖丙

关注 6455

星夜湖畔,寒风拂 关注了专栏 · 2020-10-22

cxuan的技术园地

Java后端开发,欢迎关注个人微信公众号 Java建设者 及时关注最新技术文章。

关注 8394

星夜湖畔,寒风拂 关注了专栏 · 2020-10-22

前端食堂

个人公众号:前端食堂 你的前端食堂,记得按时吃饭~

关注 2823

星夜湖畔,寒风拂 关注了标签 · 2020-10-22

关注 88584

认证与成就

  • 获得 0 次点赞
  • 获得 1 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 1 枚铜徽章

擅长技能
编辑

(゚∀゚ )
暂时没有

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2020-10-22
个人主页被 169 人浏览