/* p9_3: I2C burst read from DS1337 */ /* This program communicates with the DS1337 Real-time Clock via I2C. The time, day (of the week), date, month and year are read using burst read. DS1337 I2C parameters: fmax = 100 kHz, SCL PTE1, SDA PTE0 */ #include "MKL25Z4.h" #include #include "UART.h" #define SLAVE_ADDR 0x68 /* 1101 000. */ #define ERR_NONE 0 #define ERR_NO_ACK 0x01 #define ERR_ARB_LOST 0x02 #define ERR_BUS_BUSY 0x03 void I2C1_init(void); int I2C1_burstRead(unsigned char slaveAddr, unsigned char memAddr, int byteCount, unsigned char* data, int* cnt); void delayUs(int n); int main(void) { unsigned char timeDateReadback[7]; int count; int rv; I2C1_init(); rv = I2C1_burstRead(SLAVE_ADDR, 0, 7, timeDateReadback, &count); if (rv) for(;;) ; /* replace with error handling */ for (;;) { } } /* initialize I2C1 and the port pins */ void I2C1_init(void) { SIM->SCGC4 |= 0x80; /* turn on clock to I2C1 */ SIM->SCGC5 |= 0x2000; /* turn on clock to PortE */ PORTE->PCR[1] = 0x0600; /* PTE1 I2C1 SCL */ PORTE->PCR[0] = 0x0600; /* PTE0 I2C1 SDA */ I2C1->C1 = 0; /* stop I2C1 */ I2C1->S = 2; /* Clear interrupt flag */ I2C1->F = 0x1C; /* set clock to 97.09KHz @13.981MHz bus clock */ I2C1->C1 = 0x80; /* enable I2C1 */ } /* Use burst read to read multiple bytes from consecutive memory locations. Burst read: S-(saddr+w)-ACK-maddr-ACK-R-(saddr+r)-data-ACK-data-ACK-...-data-NACK-P */ int I2C1_burstRead(unsigned char slaveAddr, unsigned char memAddr, int byteCount, unsigned char* data, int* cnt) { int retry = 100; volatile unsigned char dummy; *cnt = 0; while (I2C1->S & 0x20) { /* wait until bus is available */ if (--retry <= 0) return ERR_BUS_BUSY; delayUs(100); } /* start */ I2C1->C1 |= 0x10; /* Tx on */ I2C1->C1 |= 0x20; /* become master */ /* send slave address and write flag */ I2C1->D = slaveAddr << 1; while(!(I2C1->S & 0x02)); /* wait for transfer complete */ I2C1->S |= 0x02; /* clear IF */ if (I2C1->S & 0x10) /* arbitration lost */ return ERR_ARB_LOST; if (I2C1->S & 0x01) /* got NACK from slave */ return ERR_NO_ACK; /* send address of target register in slave */ I2C1->D = memAddr; while(!(I2C1->S & 0x02)); /* wait for transfer complete */ I2C1->S |= 0x02; /* clear IF */ if (I2C1->S & 0x01) /* got NACK from slave */ return ERR_NO_ACK; /* restart */ I2C1->C1 |= 0x04; /* send Restart */ /* send slave address and read flag */ I2C1->D = (slaveAddr << 1) | 1; while(!(I2C1->S & 0x02)); /* wait for transfer complete */ I2C1->S |= 0x02; /* clear IF */ if (I2C1->S & 0x01) /* got NACK from slave */ return ERR_NO_ACK; /* change bus direction to read */ I2C1->C1 &= ~0x18; /* Tx off, prepare to give ACK */ if (byteCount == 1) I2C1->C1 |= 0x08; /* prepare to give NACK */ dummy = I2C1->D; /* dummy read to initiate bus read */ /* read data */ while (byteCount > 0) { if (byteCount == 1) I2C1->C1 |= 0x08; /* prepare to give NACK for last byte */ while(!(I2C1->S & 0x02)); /* wait for transfer complete */ I2C1->S |= 0x02; /* clear IF */ if (byteCount == 1) { I2C1->C1 &= ~0x20; /* stop the bus before reading last byte */ } *data++ = I2C1->D; /* read received data */ byteCount--; (*cnt)++; } return ERR_NONE; } /* delay n microseconds */ /* The CPU core clock is set to MCGFLLCLK at 41.94 MHz in SystemInit(). */ void delayUs(int n) { int i; int j; for(i = 0 ; i < n; i++) { for(j = 0; j < 7; j++) ; } }