找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1861|回复: 0
打印 上一主题 下一主题
收起左侧

用DS1302的burst模式读写,但会显示错误

[复制链接]
跳转到指定楼层
楼主
ID:474005 发表于 2019-2-17 18:28 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/***************************DS1302.c**************************************************/
#include "DS1302.h"
#define uc unsigned char

sbit CE = P1^3;
sbit SCK = P1^7;
sbit SDA = P2^3;

void DS_write(uc dat);                 //单字节写入DS1302
uc DS_read(void);                         //单字节读DS1302
void DS_register_write(uc addr,uc dat);   //向DS1302的寄存器中写入一个字节
uc DS_register_read(uc addr);                                 //读取指定寄存器中的一个字节并返回那个字节
void init_DS(void);                                                 //初始化DS1302
void DS_BURST_WRITE(uc *dat);    //连续写8个字节
void DS_BURST_READ(uc *dat);      //连续读8个字节      

void DS_write(uc dat)                 //DS1302在SCK上升沿时读取单片机发送的数据,单片机在SCK下降沿发送数据相当于SPI中MOSI变化
{
        uc mask;
        for (mask=0x01; mask!=0; mask<<=1)            
        {
                if ((dat & mask) != 0)                   //如果是==1,只显示秒钟
                        SDA = 1;
                else
                        SDA =0;
                SCK = 1;
                SCK = 0;

        }
        //SDA = 1;                                //释放数据引脚
}

uc DS_read()                                //单片机在SCK上升沿读取DS1302发送的数据,DS1302在SCK下降沿发送数据相当于SPI中MISO变化
{
        uc dat=0,mask;
        for (mask=0x01; mask!=0; mask<<=1)
        {
                if (SDA !=0 )
                {
                        dat |= mask;   //读取到的数据是1
                }
                SCK = 1;
                SCK = 0;
        }
        SDA = 0;                          //加了这个后就不会出现两个竖杆跳动地情况
        return dat;
}

void DS_register_write(uc addr,uc dat)
{
        CE = 0;
        SCK = 0;
       
        CE = 1;
        addr &= 0xFE;
        DS_write(addr);
        DS_write(dat);
        CE = 0;
}

uc DS_register_read(uc addr)
{
        uc dat;
        CE = 0;
        SCK = 0;

        CE = 1;
        addr |= 0x01;
        DS_write(addr);
        dat = DS_read();
        CE = 0;
        return dat;
}

void init_DS(void)                                                //无错
{
        /*用数组实现初始化*/
//        uc code init_time[] = {0x00,0x40,0x15,0x14,0x02,0x2019};       
//        uc i;                       
        CE = 0;                                   //初始化通信引脚
        SCK = 0;

//        i = DS_register_read(0); //读取秒寄存器          CT107D没有备用电源,可以不判断这一位
//        if ((i & 0x80) != 0) //由秒寄存器最高位 CH 的值判断 DS1302 是否已停止
//        {
//                DS_register_write(7, 0x00); //撤销写保护以允许写入数据
//                for (i=0; i<7; i++) //设置 DS1302 为默认的初始时间
//                {
//                        DS1302SingleWrite(i, init_time[i]);
//                }
//        }
       
        DS_register_write(0x8E,0x00);  //撤销写保护
        /*初始化年份2019*/
        //DS_register_write(0x8C,0x19);
        /*初始化月份2*/
        //DS_register_write(0x88,0x02);
        /*初始化日14*/
        //DS_register_write(0x86,0x14);
        /*初始化时15*/
        DS_register_write(0x84,0x23);
        /*初始化分40*/
        DS_register_write(0x82,0x59);
        /*初始化秒00*/
        DS_register_write(0x80,0x55);

        DS_register_write(0x8E,0x80);
}
void set_sfm(unsigned char shi,unsigned char  fen,unsigned char  miao)
{
DS_register_write(0x8e,0);
DS_register_write(0x80,(miao/10)*16+miao%10);
DS_register_write(0x82,(fen/10)*16+fen%10);
DS_register_write(0x84,(shi/10)*16+shi%10);
DS_register_write(0x8e,0x80);
}

void DS_BURST_WRITE(uc *dat)        //给要写入的时分秒数组
{
        uc i;
        CE = 1;
        DS_register_write(0x8E,0x00);           //撤销写保护
        DS_write(0xBE);
        for (i=0; i<8; i++)
        {
                DS_write(dat[i]);       
        }
        CE = 0;
}

void DS_BURST_READ(uc *dat)   //给数组
{
        uc i;
        CE = 1;
        DS_register_write(0x8E,0x00);
        DS_write(0xBF);
        for (i=0; i<8; i++)
        {
                dat[i] = DS_read();
        }
        CE = 0;
}


/**************************************************DS1302.h***********************************/
#include <reg52.h>
#include <intrins.h>
#include "DS1302.h"

unsigned char time[8];
unsigned char code T_display[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00};         //段选
unsigned char code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};                                                 //位选


#define FOSC 11059200L

#define T1MS (65536-FOSC/12/1000)   //1ms timer calculation method in 12T mode

void configureT0(unsigned int ms);

bit flag200ms;
unsigned char shi,fen,miao;
unsigned char count = 0;
unsigned char T0RH = 0;
unsigned char T0RL = 0;

void interruptTime0(void) interrupt 1
{
        static unsigned char i;
        static unsigned char tmr200ms;
        TH0 = T0RH;
        TL0 = T0RL;
        tmr200ms++;
        if (count-- == 0)
        {                  
                count = 1;
                P2 = 0xE0;                             //数码管段选,位选显示1ms扫描
                P0 = ~T_display[time[i]];
                P2 = 0x00;
                P2=0xc0;P0=T_COM[i];P2=0;
                i++;   
                if(i == 8)
                        i = 0;
        }
        if (tmr200ms >= 200)
        {
                flag200ms = 1;
                tmr200ms = 0;
        }
}

void configureT0(unsigned int ms)           //T0RL,T0RH有错
{
        unsigned long tmp;

        tmp = 11059200 / 12;
        tmp = (tmp * ms) / 1000;                  //只保留了整数
        tmp = 65536 - tmp;
       
        T0RH = (unsigned char)(tmp >> 8); //优先级问题,当tmp>>8不加括号就会闪烁.用仿真这个表达式和打括号的表达式一样.但是显示的效果是跑马灯一样的.
        T0RL = (unsigned char)tmp;
        TMOD &= 0xF0;
        TMOD = 0x01;
        TH0 = T0RH;
        TL0 = T0RL;
        ET0 = 1;
        TR0 = 1;         
}



void main()                                        //burst模式
{
        unsigned char dat[8] = {0x23,0x55,0x55,0x23,0x23,0x23,0x23,0x23};
        EA = 1;
        configureT0(1);
        DS_BURST_WRITE(dat);
        while (1)
        {
                if (flag200ms)
                        DS_BURST_READ(dat);
                time[0] = dat[0]>>4;
                time[1] = dat[0]&0x0F;
                time[2] = 10;
                time[3] = dat[1]>>4;
                time[4] = dat[1]&0x0f;
                time[5] = 10;
                time[6] = dat[2]/16;
                time[7] = dat[2]%16;       
        }
}

/*******************************************DS1302.h************************************/
#ifndef  _DS1302_h_
#define  _DS1302_h_

#include<reg52.h>
#include<intrins.h>

#define uc unsigned char

void DS_write(uc dat);                 //单字节写入DS1302
unsigned char DS_read(void);                         //单字节读DS1302
void DS_register_write(uc addr,uc dat);   //向DS1302的寄存器中写入一个字节
uc DS_register_read(uc addr);                                 //读取指定寄存器中的一个字节并返回那个字节
void init_DS(void);                                                 //初始化DS1302
void DS_BURST_WRITE(uc *dat);    //连续写8个字节
void DS_BURST_READ(uc *dat);      //连续读8个字节
void set_sfm(unsigned char shi,unsigned char  fen,unsigned char  miao);

#endif



QQ3401224322,欢迎一起讨论工程

DS1302.zip

42.62 KB, 下载次数: 2

上电那一刻会显示初始值,但立马会跳变

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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