This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Problems interfacing (M41T0)SERIAL REAL-TIME CLOCK

hi
I want to interface a SERIAL REAL-TIME CLOCK (M41T0). The problem comes reading from the build-in registers, that's what I think. The code looks like this. The master device in this case is P89C51RC2BA chip. I think I have to work on BCD values as well
thanks.

// Routine: i2c_start
void i2c_start(void)
{ SDA = HIGH; // Set data line high SCL = HIGH; // Set clock line high SDA = LOW; // Set data line low (START SIGNAL) SCL = LOW; // Set clock line low
} // Routine: i2c_stop
void i2c_stop (void)
{ unsigned char input_var;

SCL = LOW; // Set clock line low SDA = LOW; // Set data line low SCL = HIGH; // Set clock line high SDA = HIGH; // Set data line high (STOP SIGNAL) input_var = SDA; // Put port pin into HiZ
}

//------------------------------------------------------------------------------
// Routine: i2c_write
//------------------------------------------------------------------------------
void i2c_write (unsigned char output_data)
{ unsigned char index;

for(index = 0; index < 8; index++) // Send 8 bits to the I2C Bus { // Output the data bit to the I2C Bus SDA = ((output_data & 0x80) ? 1 : 0); output_data <<= 1; // Shift the byte by one bit SCL = HIGH; // Clock the data into the I2C Bus SCL = LOW; }

index = SDA; // Put data pin into read mode SCL = HIGH; // Clock the ACK from the I2C Bus SCL = LOW;
} //------------------------------------------------------------------------------
// Routine: i2c_read
//------------------------------------------------------------------------------

unsigned char i2c_read (void)
{ unsigned char index, input_data;

index = SDA; // Put data pin into read mode

input_data = 0x00; for(index = 0; index < 8; index++) // Send 8 bits to the I2C Bus { input_data <<= 1; // Shift the byte by one bit SCL = HIGH; // Clock the data into the I2C Bus input_data |= SDA; // Input the data from the I2C Bus SCL = LOW; }

return input_data;
}

void main()
{ //After Initializing CPU, set default values to the //registers
......

i2c_start();
i2c_write (0xD0); //start condition followed by the //correct slave address(D0h). //////////////////////////////////////////
//The 8 bytes contained in the device can then be
///accessed sequentially in the following order:
//1. Seconds Register
//2. Minutes Register
//3. Century/Hours Register
//4. Day Register
//5. Date Register
//6. Month Register
//7. Years Register
//8. Control Register
//////////////////////////////////////////
i2c_write(0x00); // Write 00 to seconds word
i2c_write(0x59); // Write 59 to minutes word
i2c_write(0x23); // Write 23 to century/hours word
i2c_write(0x05); // Write 05 to day word
i2c_write(0x10); // Write 10 to date word
i2c_write(0x11); // Write 11 to month word
i2c_write(0x05); // Write 05 to year word
i2c_write(0x00); // Write 00 to control word
i2c_stop(); // Issue stop signal
i2c_start(); // Issue start signal
i2c_write(0xD0); // Address M41T0 To Write
i2c_write(0x00); // Start address 0 (Seconds)
i2c_start(); // Issue start signal
i2c_write(0xD1); // Address M41T0 To Read
cksec = i2c_read(); // Read Seconds from RTC
ckmin = i2c_read(); // Read Minutes from RTC
ckhrs = i2c_read(); // Read Hours from RTC
ckday = i2c_read(); // Read Days from RTC
ckdat = i2c_read(); // Read Seconds from RTC
ckmth = i2c_read(); // Read Minutes from RTC
ckyer = i2c_read(); // Read Hours from RTC
ckctl = i2c_read(); // Read Days from RTC
i2c_stop(); // Issue stop signal
arr[0] = (char)cksec;//type cast BCD value to char
arr[1] = (char)ckmin;
arr[2] = (char)ckhrs;
arr[3] = '\0';
Printf(0xB4,0x10,arr); //prints value on LCD

Parents
  • I was of course drunk when I wrote the above post.

    All assignments in the last code snippet should of course be (missing ASCII offset of '0'):

    arr[0] = '0' + (ckhrs >> 4);
    arr[1] = '0' + (ckhrs & 0x0f);
    arr[2] = '0' + (ckmin >> 4);
    arr[3] = '0' + (ckmin & 0x0f);
    arr[4] = '0' + (cksec >> 4);
    arr[5] = '0' + (cksec & 0x0f);
    arr[6] = '\0';
    


    The above should work even if ckhrs, ckmin and cksec are signed, since they don't make use of the full BCD range, and will not set the sign bit.

    When converting a year byte, you must make sure to use unsigned data, or write

    '0' + (ckyer >> 4) & 0x0f;
    


    or years 2080 and foward would look very funny.

    By the way: Be careful with copy/paste. The following line in your code (it's not alone) gives a confused impression:

    ckyer = i2c_read(); // Read Hours from RTC
    

Reply
  • I was of course drunk when I wrote the above post.

    All assignments in the last code snippet should of course be (missing ASCII offset of '0'):

    arr[0] = '0' + (ckhrs >> 4);
    arr[1] = '0' + (ckhrs & 0x0f);
    arr[2] = '0' + (ckmin >> 4);
    arr[3] = '0' + (ckmin & 0x0f);
    arr[4] = '0' + (cksec >> 4);
    arr[5] = '0' + (cksec & 0x0f);
    arr[6] = '\0';
    


    The above should work even if ckhrs, ckmin and cksec are signed, since they don't make use of the full BCD range, and will not set the sign bit.

    When converting a year byte, you must make sure to use unsigned data, or write

    '0' + (ckyer >> 4) & 0x0f;
    


    or years 2080 and foward would look very funny.

    By the way: Be careful with copy/paste. The following line in your code (it's not alone) gives a confused impression:

    ckyer = i2c_read(); // Read Hours from RTC
    

Children
No data