请教AVRMega128访问DS3231SN数据不正确原因

2019-03-24 20:21发布

最近搞个板子,使用Mega128访问DS3231SN,可是数据读取始终为0,不知何故,请大家帮忙看一下代码,看看哪有问题,谢谢。
上拉电阻为10K。
      #ifndef _ds3231_h
#define _ds3231_h
//====================================================================
#define RST_On CLR_BIT(PORTB,PB6)
#define RST_Off SET_BIT(PORTB,PB6)

#define GET_SDA GET_BIT(PINA,PA3)
#define SDA_High SET_BIT(PORTA,PA3)
#define SDA_Low CLR_BIT(PORTA,PA3)
#define SDA_In CLR_BIT(DDRA,PA3)
#define SDA_Out SET_BIT(DDRA,PA3)

#define SCL_High SET_BIT(PORTA,PA2)
#define SCL_Low CLR_BIT(PORTA,PA2)
#define SCL_Out SET_BIT(DDRA,PA2)
struct DS3231_DAT
{
    uchar year;
uchar month;
uchar day;
uchar hour;
uchar minute;
uchar second;
    float temperature;
}*ds3231;



void I2C_Start(void)
{
    SDA_Out;
SDA_High;
SCL_High;
delay_nus(5);
SDA_Low;
delay_nus(5);
SCL_Low;
delay_nus(5);
}

void I2C_Stop(void)
{
    SDA_Out;
SDA_Low;
SCL_High;
delay_nus(5);
SDA_High;
delay_nus(5);
}

uchar I2C_Write(uchar dat)
{   
    uchar i,ret;
SDA_Out;

for(i=0;i<8;i++)
{
    SCL_Low;
delay_nus(5);

    if(dat&0x80)
{
    SDA_High;
LED_ON();
}
else
{
    SDA_Low;
LED_OFF();
}
delay_nus(5);

SCL_High;
        delay_nus(5);

dat<<=1;
}

//read the ack bit
SDA_In;
SDA_High;
SCL_Low;
delay_nus(5);
SCL_High;
delay_nus(5);
ret=GET_SDA;
SCL_Low;
delay_nus(5);
return ret;
}

void I2C_Write_byte(uchar add,uchar data)
{
    //I2C_Start();
I2C_Write(0xd0);//Write mode
I2C_Write(add);
I2C_Write(data);
//I2C_Stop();
}

uchar I2C_Read(uchar ackBit)//ackBit: low for ACK, high for None ACK
{
    uchar i,dat=0x00;

    SDA_In;
    SCL_Low;
delay_nus(5);
for(i=0;i<8;i++)
{
    SCL_High;
        delay_nus(5);
dat|=GET_SDA;

dat<<=1;
SCL_Low;
        delay_nus(5);
}

//Send ACK
    SDA_Out;
if(ackBit==0)
{
    SDA_Low;
}
else
{
    SDA_High;
}

SCL_High;
delay_nus(5);
SCL_Low;
delay_nus(5);
SDA_In;
return dat;
}

uchar I2C_Read_byte(uchar addr,uchar ackBit)//ackBit: low for ACK, high for None ACK
{
    uchar dat;
//I2C_Start();
I2C_Write(0xd1);//read mode
I2C_Write(addr);
dat=I2C_Read(ackBit);
//I2C_Stop();
return dat;
}

void Ds3231_Set_Time(uchar year,uchar month,uchar day,uchar hour,uchar minute,uchar second)
{
    I2C_Start();
I2C_Write_byte(0x00,num2BCD(second,10));
I2C_Write_byte(0x01,num2BCD(minute,10));
I2C_Write_byte(0x02,num2BCD(hour,10));
I2C_Write_byte(0x04,num2BCD(day,10));
I2C_Write_byte(0x05,num2BCD(month,10));
    I2C_Write_byte(0x06,num2BCD(year,10));
I2C_Stop();
}

void DS3231_init(void)
{
    OE_On;
SDA_Out;
SCL_Out;
SCL_High;
SDA_High;

I2C_Start();
I2C_Write_byte(0x0e,0x00);//enable oscillator
I2C_Write_byte(0x0f,0x00);
I2C_Stop();

//2011-8-10 12:11:10
Ds3231_Set_Time(11,8,10,12,11,10);

}

void getDs3231Temp(void)
{
    uint hValue,lValue;
uchar sign;
float temp;

I2C_Start();
//check if bus is busy
while(I2C_Read_byte(0x0f,0)&0x04);
//write convert cmd
I2C_Write_byte(0x0E,0x20);
//wait until busy=0 and conv=0 
while((I2C_Read_byte(0x0f,0)&0x04)||(I2C_Read_byte(0x0E,0)&0x20));

//read high byte
hValue=I2C_Read_byte(0x11,0);
//get sign
sign=hValue&0x80;
//remove sign
hValue=hValue&0xef;

//read low byte
lValue=I2C_Read_byte(0x12,1)>>6;
//combine the temp code

I2C_Stop();
temp=hValue<<2|lValue; 
//add sign
if(sign>0)
{
    temp*=-1;
}

ds3231->temperature= 0.03125 *temp;//convert to degree
}

void getFullTimeNow(void)
{
    I2C_Start();
ds3231->year=I2C_Read_byte(0x06,0);
ds3231->month=I2C_Read_byte(0x05,0);
ds3231->day=I2C_Read_byte(0x04,0);
ds3231->hour=I2C_Read_byte(0x02,0);
ds3231->minute=I2C_Read_byte(0x01,0);
ds3231->second=I2C_Read_byte(0x00,1);
//getDs3231Temp();
I2C_Stop();
}

uchar getYear(uchar ackBit)//ackBit: low for ACK, high for None ACK)
{
    return I2C_Read_byte(0x06,ackBit);
}


uchar getMonth(uchar ackBit)
{
    return I2C_Read_byte(0x05,ackBit);
}


uchar getDay(uchar ackBit)
{
    return I2C_Read_byte(0x04,ackBit);
}


uchar getHour(uchar ackBit)
{
    return I2C_Read_byte(0x02,ackBit);;
}

uchar getMinute(uchar ackBit)
{
    return I2C_Read_byte(0x01,ackBit);
}

uchar getSecond(uchar ackBit)
{
    return I2C_Read_byte(0x00,ackBit);
}

void resetTime(void)
{
    RST_On;
delay_nms(250);
RST_Off;   
}


//====================================================================
#endif 此帖出自小平头技术问答
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。