Actions

EmSys

DS1307 Programming

From EdWiki

RTC DS1307 on EduARM4 Trainer Board

Ds1307 tm4c connections.png
Figure:DS1307 Connectons

Note

Source Code

  1. /*
  2. * I2C to DS1307 single byte writes
  3.  
  4. * This program communicates with the DS1307 Real-time Clock via I2C.
  5. *
  6. * The DS1307 has a total of 64 bytes of RAM space with addresses 00–3FH.
  7. * The first seven locations, 00–06, are set aside for RTC values of Time and Date.
  8. * The next byte is used for the control register. It is located at address 0x07.
  9. * That leaves 56 bytes, from addresses 0x08 to 0x3F, available for general-purpose data storage.
  10. * That means the entire 64 bytes of RAM are accessible directly for read or write
  11. *
  12. */
  13.  
  14. /* DS1307 parameters:  fmax = 100 kHz
  15.  *                     I2C1SCL PA6
  16.  *                     I2C1SDA PA7
  17.  *
  18. */
  19.  
  20. #include <stdint.h>
  21. #include "inc/tm4c123gh6pm.h"
  22.  
  23. #define MAX_BUF_SIZE                56
  24.  
  25. #define SLAVE_ADDR 0x68             /* 1100 1000 */
  26. #define I2C_START_ADDR              0x08
  27.  
  28. void I2C1_init(void);
  29. char I2C1_byteWrite(int slaveAddr, char memAddr, char data);
  30. char I2C1_read(int slaveAddr, char memAddr, int byteCount, char* data);
  31.  
  32. char readBuf[MAX_BUF_SIZE];
  33.  
  34. int main(void)
  35. {
  36.     char err, i;
  37.  
  38.     char writeBuf;
  39.  
  40.     writeBuf = I2C_START_ADDR;
  41.     I2C1_init();
  42.  
  43.     /* write 56 bytes with single byte writes */
  44.     for( i = 0; i < MAX_BUF_SIZE; i++) {
  45.         err = I2C1_byteWrite(SLAVE_ADDR, writeBuf++, i);
  46.         if(err) break;
  47.     }
  48.  
  49.     if( err ) {
  50.         ;                       /* Handle error condition */
  51.     } else {
  52.         /* uses burst read to read 56 bytes of data */
  53.         err = I2C1_read(SLAVE_ADDR, I2C_START_ADDR, MAX_BUF_SIZE, readBuf);
  54.     }
  55.  
  56.     for(;;) {
  57.         ;
  58.     }
  59. }
  60.  
  61. /* initialize I2C1 as master and the port pins */
  62. void I2C1_init(void)
  63. {
  64.     SYSCTL_RCGCI2C_R |= 0x02;       /* enable clock to I2C1 */
  65.     SYSCTL_RCGCGPIO_R |= 0x01;      /* enable clock to GPIOA */
  66.  
  67.     /* PORTA 7, 6 for I2C1 */
  68.     GPIO_PORTA_AFSEL_R |= 0xC0;     /* PORTA 7, 6 for I2C1 */
  69.     GPIO_PORTA_PCTL_R &= ~0xFF000000; /* PORTA 7, 6 for I2C1 */
  70.     GPIO_PORTA_PCTL_R |= 0x33000000;
  71.     GPIO_PORTA_DEN_R |= 0xC0;       /* PORTA 7, 6 as digital pins */
  72.     GPIO_PORTA_ODR_R |= 0x80;       /* PORTA 7 as open drain */
  73.  
  74.     I2C1_MCR_R = 0x10;              /* master mode */
  75.     I2C1_MTPR_R = 7;                /* 100 kHz @ 16 MHz */
  76. }
  77.  
  78.  
  79. /* Wait until I2C master is not busy and return error code */
  80. /* If there is no error, return 0 */
  81. static int I2C_wait_till_done(void)
  82. {
  83.     while(I2C1_MCS_R & 1)
  84.         ;                           /* wait until I2C master is not busy */
  85.     return I2C1_MCS_R & 0xE;        /* return I2C error code */
  86. }
  87.  
  88. /* Write one byte only */
  89. /* byte write: S-(saddr+w)-ACK-maddr-ACK-data-ACK-P */
  90. char I2C1_byteWrite(int slaveAddr, char memAddr, char data)
  91. {
  92.     char error;
  93.  
  94.     /* send slave address and starting address */
  95.     I2C1_MSA_R = slaveAddr << 1;
  96.     I2C1_MDR_R = memAddr;
  97.     I2C1_MCS_R = 3;                 /* S-(saddr+w)-ACK-maddr-ACK */
  98.  
  99.     error = I2C_wait_till_done();   /* wait until write is complete */
  100.     if(error) return error;
  101.  
  102.     /* send data */
  103.     I2C1_MDR_R = data;
  104.     I2C1_MCS_R = 5;                 /* -data-ACK-P */
  105.     error = I2C_wait_till_done();   /* wait until write is complete */
  106.     while( I2C1_MCS_R & 0x40 )
  107.         ;                           /* wait until bus is not busy */
  108.     error = I2C1_MCS_R & 0xE;
  109.     if(error) return error;
  110.  
  111.     return 0;                       /* no error */
  112. }
  113.  
  114. /* Read memory */
  115. /* read: S-(saddr+w)-ACK-maddr-ACK-R-(saddr+r)-ACK-data-ACK-data-ACK-...-data-NACK-P */
  116. char I2C1_read(int slaveAddr, char memAddr, int byteCount, char* data)
  117. {
  118.     char error;
  119.  
  120.     if (byteCount <= 0)
  121.         return -1;                  /* no read was performed */
  122.  
  123.     /* send slave address and starting address */
  124.     I2C1_MSA_R = slaveAddr << 1;
  125.     I2C1_MDR_R = memAddr;
  126.     I2C1_MCS_R = 3;                 /* S-(saddr+w)-ACK-maddr-ACK */
  127.     error = I2C_wait_till_done();
  128.     if(error)
  129.         return error;
  130.  
  131.     /* to change bus from write to read, send restart with slave addr */
  132.     I2C1_MSA_R = (slaveAddr << 1) + 1;   /* restart: -R-(saddr+r)-ACK */
  133.  
  134.     if( byteCount == 1 )            /* if last byte, don't ack */
  135.         I2C1_MCS_R = 7;             /* -data-NACK-P */
  136.     else                            /* else ack */
  137.         I2C1_MCS_R = 0xB;           /* -data-ACK- */
  138.     error = I2C_wait_till_done();
  139.     if(error) return error;
  140.  
  141.     *data++ = I2C1_MDR_R;           /* store the data received */
  142.  
  143.     if( --byteCount == 0 ) {        /* if single byte read, done */
  144.         while( I2C1_MCS_R & 0x40 )
  145.             ;                       /* wait until bus is not busy */
  146.         return 0;                   /* no error */
  147.     }
  148.  
  149.     /* read the rest of the bytes */
  150.     while( byteCount > 1 ) {
  151.         I2C1_MCS_R = 9;              /* -data-ACK- */
  152.         error = I2C_wait_till_done();
  153.         if(error) return error;
  154.         byteCount--;
  155.         *data++ = I2C1_MDR_R;        /* store data received */
  156.     }
  157.  
  158.     I2C1_MCS_R = 5;                 /* -data-NACK-P */
  159.     error = I2C_wait_till_done();
  160.     *data = I2C1_MDR_R;             /* store data received */
  161.     while( I2C1_MCS_R & 0x40 )
  162.         ;                           /* wait until bus is not busy */
  163.  
  164.     return 0;                       /* no error */
  165. }