/* P9_4.c - I2C burst read from a DS3231 * * This program initializes the I2C and continuously * reads all the time registers of the DS3231 using burst reads. * Register 0 contains the second count. The clock is powered-up * enabled and the second count is incrementing. The bit 0 is * used to turn on and off the LED of the Nucleo board. The LED * should blink every second. * No errors or acknowledgment are checked. * * The connections * I2C1_SCL - PB8 * I2C1_SDA – PB9 * This program was tested with Keil uVision v5.24a with DFP v2.11.0 */ #include "stm32f0xx.h" #define SLAVE_ADDR 0x68 /* 1101 000. DS3231*/ void delayMs(int n); void I2C1_init(void); int I2C1_burstRead(char saddr, char maddr, int n, char* data); void delayMs(int n); int Main(void) { char timeDateReadback[15]; I2C1_init(); /* configure PA5 for the green LED (LD2) */ RCC->AHBENR |= 0x20000; /* enable GPIOA clock */ GPIOA->MODER &= ~0x00000C00; /* clear pin mode */ GPIOA->MODER |= 0x00000400; /* set pin to output mode */ while (1) { I2C1_burstRead(SLAVE_ADDR, 0, 7, timeDateReadback); if (timeDateReadback[0] & 1) GPIOA->ODR |= 0x00000020; /* turn on LED */ else GPIOA->ODR &= ~0x00000020; /* turn off LED */ delayMs(10); } } void I2C1_init(void) { RCC->AHBENR |= 0x00040000; /* Enable GPIOB clock */ RCC->APB1ENR |= 0x00200000; /* Enable I2C1 clock */ /* configure PB8, PB9 pins for I2C1 */ GPIOB->MODER &= ~0x000F0000; /* PB8, PB9 use alternate function */ GPIOB->MODER |= 0x000A0000; GPIOB->AFR[1] &= ~0x000000FF; /* PB8, PB9 I2C1 SCL, SDA */ GPIOB->AFR[1] |= 0x00000011; GPIOB->OTYPER |= 0x00000300; /* output open-drain */ GPIOB->PUPDR &= ~0x000F0000; /* with pull-ups */ GPIOB->PUPDR |= 0x00050000; I2C1->CR1 = 0; /* software reset I2C1 */ I2C1->TIMINGR = 0x10420F13; /* 100 KHz, peripheral clock is 8 MHz */ I2C1->CR1 = 0x00000001; /* enable I2C1 module */ } /* this funtion reads multiple bytes of data from the memory location * maddr of a device with I2C slave device address saddr. * For simplicity, no error checking or error report is done. */ int I2C1_burstRead(char saddr, char maddr, int n, char* data) { while (I2C1->ISR & 0x8000); /* wait until bus not busy */ I2C1->CR2 = 0x00012000 | (saddr << 1); /* generate start and send slave address */ while (!(I2C1->ISR & 0x02)); /* wait until transmitter is ready */ I2C1->TXDR = maddr; /* send memory address */ while (!(I2C1->ISR & 0x40)); /* wait until transfer complete */ /* generate restart, send slave address, repeat read n bytes, set for auto end */ I2C1->CR2 = 0x02002400 | ((n & 0xFF) << 16) | (saddr << 1); for (; n > 0; n--) { while (!(I2C1->ISR & 0x04)); /* Wait until RXNE flag is set */ *data++ = I2C1->RXDR; /* Read data from DR */ } while (!(I2C1->ISR & 0x20)); /* wait until stop flag is set */ I2C1->ICR = 0x20; /* clear stop flag */ I2C1->CR2 = 0x02000000; /* clear configuration register 2 */ return 0; } /* 8 MHz SYSCLK */ void delayMs(int n) { int i; for (; n > 0; n--) for (i = 0; i < 1142; i++) ; }