DS1307 Programming
From EdWiki
RTC DS1307 on EduARM4 Trainer Board
Figure:DS1307 Connectons
Note
- Short 1 & 2 and 3 & 4 of J6 on the EduARM4 Trainer Board
Source Code
/*
* I2C to DS1307 single byte writes
* This program communicates with the DS1307 Real-time Clock via I2C.
*
* The DS1307 has a total of 64 bytes of RAM space with addresses 00–3FH.
* The first seven locations, 00–06, are set aside for RTC values of Time and Date.
* The next byte is used for the control register. It is located at address 0x07.
* That leaves 56 bytes, from addresses 0x08 to 0x3F, available for general-purpose data storage.
* That means the entire 64 bytes of RAM are accessible directly for read or write
*
*/
/* DS1307 parameters: fmax = 100 kHz
* I2C1SCL PA6
* I2C1SDA PA7
*
*/
#include <stdint.h>
#include "inc/tm4c123gh6pm.h"
#define MAX_BUF_SIZE 56
#define SLAVE_ADDR 0x68 /* 1100 1000 */
#define I2C_START_ADDR 0x08
void I2C1_init(void);
char I2C1_byteWrite(int slaveAddr, char memAddr, char data);
char I2C1_read(int slaveAddr, char memAddr, int byteCount, char* data);
char readBuf[MAX_BUF_SIZE];
int main(void)
{
char err, i;
char writeBuf;
writeBuf = I2C_START_ADDR;
I2C1_init();
/* write 56 bytes with single byte writes */
for( i = 0; i < MAX_BUF_SIZE; i++) {
err = I2C1_byteWrite(SLAVE_ADDR, writeBuf++, i);
if(err) break;
}
if( err ) {
; /* Handle error condition */
} else {
/* uses burst read to read 56 bytes of data */
err = I2C1_read(SLAVE_ADDR, I2C_START_ADDR, MAX_BUF_SIZE, readBuf);
}
for(;;) {
;
}
}
/* initialize I2C1 as master and the port pins */
void I2C1_init(void)
{
SYSCTL_RCGCI2C_R |= 0x02; /* enable clock to I2C1 */
SYSCTL_RCGCGPIO_R |= 0x01; /* enable clock to GPIOA */
/* PORTA 7, 6 for I2C1 */
GPIO_PORTA_AFSEL_R |= 0xC0; /* PORTA 7, 6 for I2C1 */
GPIO_PORTA_PCTL_R &= ~0xFF000000; /* PORTA 7, 6 for I2C1 */
GPIO_PORTA_PCTL_R |= 0x33000000;
GPIO_PORTA_DEN_R |= 0xC0; /* PORTA 7, 6 as digital pins */
GPIO_PORTA_ODR_R |= 0x80; /* PORTA 7 as open drain */
I2C1_MCR_R = 0x10; /* master mode */
I2C1_MTPR_R = 7; /* 100 kHz @ 16 MHz */
}
/* Wait until I2C master is not busy and return error code */
/* If there is no error, return 0 */
static int I2C_wait_till_done(void)
{
while(I2C1_MCS_R & 1)
; /* wait until I2C master is not busy */
return I2C1_MCS_R & 0xE; /* return I2C error code */
}
/* Write one byte only */
/* byte write: S-(saddr+w)-ACK-maddr-ACK-data-ACK-P */
char I2C1_byteWrite(int slaveAddr, char memAddr, char data)
{
char error;
/* send slave address and starting address */
I2C1_MSA_R = slaveAddr << 1;
I2C1_MDR_R = memAddr;
I2C1_MCS_R = 3; /* S-(saddr+w)-ACK-maddr-ACK */
error = I2C_wait_till_done(); /* wait until write is complete */
if(error) return error;
/* send data */
I2C1_MDR_R = data;
I2C1_MCS_R = 5; /* -data-ACK-P */
error = I2C_wait_till_done(); /* wait until write is complete */
while( I2C1_MCS_R & 0x40 )
; /* wait until bus is not busy */
error = I2C1_MCS_R & 0xE;
if(error) return error;
return 0; /* no error */
}
/* Read memory */
/* read: S-(saddr+w)-ACK-maddr-ACK-R-(saddr+r)-ACK-data-ACK-data-ACK-...-data-NACK-P */
char I2C1_read(int slaveAddr, char memAddr, int byteCount, char* data)
{
char error;
if (byteCount <= 0)
return -1; /* no read was performed */
/* send slave address and starting address */
I2C1_MSA_R = slaveAddr << 1;
I2C1_MDR_R = memAddr;
I2C1_MCS_R = 3; /* S-(saddr+w)-ACK-maddr-ACK */
error = I2C_wait_till_done();
if(error)
return error;
/* to change bus from write to read, send restart with slave addr */
I2C1_MSA_R = (slaveAddr << 1) + 1; /* restart: -R-(saddr+r)-ACK */
if( byteCount == 1 ) /* if last byte, don't ack */
I2C1_MCS_R = 7; /* -data-NACK-P */
else /* else ack */
I2C1_MCS_R = 0xB; /* -data-ACK- */
error = I2C_wait_till_done();
if(error) return error;
*data++ = I2C1_MDR_R; /* store the data received */
if( --byteCount == 0 ) { /* if single byte read, done */
while( I2C1_MCS_R & 0x40 )
; /* wait until bus is not busy */
return 0; /* no error */
}
/* read the rest of the bytes */
while( byteCount > 1 ) {
I2C1_MCS_R = 9; /* -data-ACK- */
error = I2C_wait_till_done();
if(error) return error;
byteCount--;
*data++ = I2C1_MDR_R; /* store data received */
}
I2C1_MCS_R = 5; /* -data-NACK-P */
error = I2C_wait_till_done();
*data = I2C1_MDR_R; /* store data received */
while( I2C1_MCS_R & 0x40 )
; /* wait until bus is not busy */
return 0; /* no error */
}