/* P9_2.c - I2C byte read from a DS3231 * * This program initializes the I2C and continuously reads * the register 0 of the DS3231. * 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.23 with DFP v2.0.0 */ #include "stm32f0xx.h" #define SLAVE_ADDR 0x68 /* 1101 000. DS3231 */ void delayMs(int n); void I2C1_init(void); int I2C1_byteRead(char saddr, char maddr, char* data); void delayMs(int n); int Main(void) { char data; I2C1_init(); /* configure PA5 for the green LED (LD2) */ RCC->AHBENR |= RCC_AHBENR_GPIOAEN; /* enable GPIOA clock */ GPIOA->MODER &= ~0x00000C00; /* clear pin mode */ GPIOA->MODER |= 0x00000400; /* set pin to output mode */ while (1) { I2C1_byteRead(SLAVE_ADDR, 0, &data); if (data & 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 a byte 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_byteRead(char saddr, char maddr, 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 & 0x2)); /* wait until start flag is set */ I2C1->TXDR = maddr; /* send memory address */ while (!(I2C1->ISR & 0x40)); /* wait until transfer complete */ /* generate restart, send slave address, read 1 byte, set for auto end */ I2C1->CR2 = 0x02002400 | (1 << 16) | (saddr << 1); while (!(I2C1->ISR & 0x4)); /* 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++) ; }