yealqin
2021-08-10 03:42
浏览 32

STC8G 控制DS3231通讯失败,DS3231无应答,网上程序和方法都尝试过,困扰一周,求解决!!(附代码)

如题,现在要通过STC8G读取DS3231的时间。我是通过串口观察读取数据,发现读取数据总是FF。出现问题之后参考并试过网络上的DS3231的驱动代码,还是不行。又怀疑DS3231问题,换了新的DS3231也不行。又检查接口,接口如下:DS3231“+”接STC8G“VCC" ,DS3231“-”接STC8G“GND" ,DS3231“NC”接STC8G“GND" ,DS3231“C”接STC8G“P34" ,DS3231“D”接STC8G“P35" ,电路我找不出问题。
已经连续快一周熬夜三四点了,找不到问题。
麻请大家看一下。
程序如下:

/***************头文件*******************/
#include "stc8.h"
#include "intrins.h"

/***************宏定义*******************/
#define uchar unsigned char     
#define uint unsigned int
#define FOSC 11059200UL  //用于串口
#define BRT (65536-FOSC/115200/4)  //用于串口
#define DS3231_WriteAddress 0xD0
#define DS3231_ReadAddress 0xD1
#define DS3231_add_second 0x00
#define DS3231_add_minute 0x01
#define DS3231_add_hour 0x02
#define DS3231_add_week 0x03
#define DS3231_add_day 0x04
#define DS3231_add_month 0x05
#define DS3231_add_year 0x06

/***************位定义*******************/
sbit DS3231_SCL=P3^4;  //DS3231引脚定义
sbit DS3231_SDA=P3^5;
bit busy;

/***************变量定义*******************/
uchar wptr;  //串口变量
uchar rptr;  //串口变量
uchar buffer[16];  //串口变量
uchar time_data[7];  //时间值: 0秒、1分、2时、3周、4日、5月、6年

/**************函数声明*******************/
void pin_init();
void UartInit();
void UartSend(char dat);
void UartSendStr(char *p);
void nop();
void Start_DS3231();
void Stop_DS3231(); 
void SendAck(); 
void SendNotAck(); 
void DS3231_writebyte();  
void DS3231_write(uchar address,uchar date);
void DS3231_read(uchar address);
uchar Ack_DS3231(void);
uchar DS3231_readbyte();

/************引脚初始化程序****************/
void pin_init()
{
  P3M0=0x00;//引脚配置为准双向口
  P3M1=0x00;
  P_SW2|=0x80; //上拉电阻
  P3PU|=0x30;                                
  P_SW2&=0x7f;
  DS3231_SCL=1;    //时钟线拉高
  _nop_();
  DS3231_SDA=1;    //数据线拉高
  _nop_();
}

/**********串口打印函数***********************************/
void UartIsr() interrupt 4
{
    if(TI)
    {
        TI = 0;
        busy = 0;
    }
    if(RI)
    {
        RI = 0;
        buffer[wptr++] = SBUF;
        wptr &= 0x0f;
    }
}

void UartInit()
{
    SCON = 0x50;
    TL2 = BRT;
    TH2 = BRT >> 8;
    AUXR = 0x15;
    wptr = 0x00;
    rptr = 0x00;
    busy = 0;
}
void UartSend(char dat)
{
    while (busy);
    busy = 1;
    SBUF = dat;
}

void UartSendStr(char *p)
{
    while (*p)
    {
            UartSend(*p++);
    }
}

/*************等待稳定延时函数***************/
void nop()
{
        _nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();
}

/***************DS3231启动函数**************/
void Start_DS3231()
{
    EA=0;    //在SCL高电平期间,SDA产生下降沿,关中断总允许    
    DS3231_SDA=1;
    _nop_();
    DS3231_SCL=1;
    nop();  
    DS3231_SDA=0; 
    nop();  
    DS3231_SCL=0; 
    nop();
}

/***************DS3231停止函数**************/
void Stop_DS3231()
{
    DS3231_SDA=0; //在SCL高电平期间,SDA产生上升沿,开中断总允许
    _nop_();
    DS3231_SCL=1; 
    nop();  
    DS3231_SDA=1;
    nop();   
    EA=1; 
}

/**************等待应答函数*****************/
uchar Ack_DS3231(void)
{
    uchar errtime=255;  //SDA低电平有应答,高电平无应答
    uchar ack=1;
    DS3231_SDA=1; 
    _nop_();
    DS3231_SCL=1; 
    nop();
  while((ack)&&(errtime>5))     //判断从机是不是低电平低电平,如果不是,过时不候。
    {
        ack=DS3231_SDA;        //从机发送低电平立马退出
        errtime--;
    }
    DS3231_SCL=0;
    return ack;  //1无应答,0有应答
}

/*************传送响应函数******************/
void SendAck()
{
    DS3231_SDA=0; //SDA发送一个低电平应答信号
    nop();
    DS3231_SCL=1;
    nop(); 
    DS3231_SCL=0;
    nop();
    DS3231_SDA=1;
    nop();
}

/*************传送不响应函数*****************/
void SendNotAck()
{
    DS3231_SDA=1; //SDA发送一个高电平不应答信号
    nop();
    DS3231_SCL=1;
    nop(); 
    DS3231_SCL=0;
    nop();
    DS3231_SDA=1;
    nop();
}

/*********DS3231写字节函数****************/
void DS3231_writebyte (uchar ch)
{
    uchar im;    //发送八位二进制数
    DS3231_SCL=0;
    _nop_();
    DS3231_SDA=1;
    for (im=0;im<8;im++) 
    {
        if(ch&0x80==0x80) DS3231_SDA=1;
        else DS3231_SDA=0;
        ch<<=1;
        _nop_();
        DS3231_SCL=1; 
        nop(); 
        DS3231_SCL=0; 
        nop();
    } 
    DS3231_SDA=1;
}

/***********DS3231读字节函数*************/
uchar DS3231_readbyte()
{
    uchar in;    //接受8位二进制数
    uchar DS3231_tem_recedata=0;
    DS3231_SCL=0;
    _nop_();
    DS3231_SDA=1;
    for (in=0;in<8;in++) 
    {
        DS3231_tem_recedata<<=1;
        DS3231_tem_recedata|=DS3231_SDA;
        _nop_();_nop_();
        DS3231_SCL=1;
        nop();
        DS3231_SCL=0;
        nop();
    }
    return (DS3231_tem_recedata); 
}

/*************DS3231写入函数****************/
void DS3231_write(uchar add,uchar date)
{
    date=((date/10)<<4)+(date%10); //十进制转BCD码
    Start_DS3231();   //address和date分别是地址和数据
    DS3231_writebyte(DS3231_WriteAddress);
    Ack_DS3231();
    DS3231_writebyte(add); 
  Ack_DS3231();
    DS3231_writebyte(date); 
  Ack_DS3231();
    Stop_DS3231(); 
}

/*************DS3231读取函数******************/
void DS3231_read(uchar addr)
{
    uchar data_tem;  //读取时间数据
    Start_DS3231();  
    DS3231_writebyte(DS3231_WriteAddress); 
    Ack_DS3231(); 
    DS3231_writebyte(addr); 
    Ack_DS3231(); 
    Start_DS3231(); 
    DS3231_writebyte(DS3231_ReadAddress);
    Ack_DS3231();
    data_tem=DS3231_readbyte(); 
    SendNotAck();
    Stop_DS3231();
    time_data[addr]=(data_tem>>4)*10+(data_tem&0x0F);//BCD码转十进制
}

/***************主程序(用于测试DS3231模块)****************/
void main()
{
    pin_init(); //引脚定义及初始化
    UartInit();  //串口初始化
    ES=1;
    DS3231_write(0x0E,0x04);  
  DS3231_write(0x0F,0x00);
    
    DS3231_write(DS3231_add_second,0x01);     //尝试在秒的位置写入01并读取秒的数据
    DS3231_read(DS3231_add_second);
    UartSend(time_data[DS3231_add_second]);  
    while(1);
}
//最终串口打印结果为A5,而且无论怎么改都是A5。
//A5因为我把读取的数据进行了BCD码到十进制转换,实际读取的总是FF
    


  • 好问题 提建议
  • 收藏

相关推荐 更多相似问题