/* * This program reads the second register of a DS3231 RTC and displays * the least significant digit on the four LEDs of the EduBase board. * The DS3231 Real Time Clock chip is not included in the Edubase board but * a connector is provided for a DS3231 module. * * The DS3231 is connected via I2C. The I2C connections are: * I2C1_SCL - PB08 * I2C1_SDA - PB09 * * The four LEDs are: * LED3 - PB7 * LED2 - PB6 * LED1 - PB5 * LED0 - PB4 */ #include "stm32f4xx.h" void delayMs(int n); void delayMs(int n); void I2C1_init(void); char I2C1_byteRead(char saddr, char maddr, char* data); void display(int data); #define SLAVE_ADDR 0x68 // 1101 000. int main(void) { char readback; char error; RCC->AHB1ENR |= 2; /* enable GPIOB clock */ /* configure LED pins */ GPIOB->MODER &= ~0x0000ff00; /* clear pin mode */ GPIOB->MODER |= 0x00005500; /* set pins to output mode */ I2C1_init(); for (;;) { // use second count to turn LEDs on or off error = I2C1_byteRead(SLAVE_ADDR, 0, &readback); if (error) for(;;) ; // replace with error handling display(readback); delayMs(200); } } /* configure UCB1 as I2C */ void I2C1_init(void) { RCC->AHB1ENR |= 2; /* Enable GPIOB clock */ RCC->APB1ENR |= 0x00200000; /* Enable I2C1 clock */ /* configure PB8, PB9 pins for I2C1 */ GPIOB->AFR[1] &= ~0x000000FF; /* PB8, PB9 I2C1 SCL, SDA */ GPIOB->AFR[1] |= 0x00000044; GPIOB->MODER &= ~0x000F0000; /* PB8, PB9 use alternate function */ GPIOB->MODER |= 0x000A0000; GPIOB->OTYPER |= 0x00000300; /* output open-drain */ GPIOB->PUPDR &= ~0x000F0000; /* with pull-ups */ GPIOB->PUPDR |= 0x00050000; I2C1->CR1 = 0x8000; /* software reset I2C1 */ I2C1->CR1 &= ~0x8000; /* out of reset */ I2C1->CR2 = 0x0010; /* peripheral clock is 16 MHz */ I2C1->CCR = 80; /* standard mode, 100kHz clock */ I2C1->TRISE = 17; /* maximum rise time */ I2C1->CR1 |= 0x0001; /* 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. */ char I2C1_byteRead(char saddr, char maddr, char* data) { volatile int tmp; while (I2C1->SR2 & 2); /* wait until bus not busy */ I2C1->CR1 |= 0x100; /* generate start */ while (!(I2C1->SR1 & 1)); /* wait until start flag is set */ I2C1->DR = saddr << 1; /* transmit slave address + Write */ while (!(I2C1->SR1 & 2)); /* wait until addr flag is set */ tmp = I2C1->SR2; /* clear addr flag */ while (!(I2C1->SR1 & 0x80)); /* wait until data register empty */ I2C1->DR = maddr; /* send memory address */ while (!(I2C1->SR1 & 0x80)); /* wait until data register empty */ I2C1->CR1 |= 0x100; /* generate restart */ while (!(I2C1->SR1 & 1)); /* wait until start flag is set */ I2C1->DR = saddr << 1 | 1; /* transmit slave address + Read */ while (!(I2C1->SR1 & 2)); /* wait until addr flag is set */ I2C1->CR1 &= ~0x400; /* Disable Acknowledge */ tmp = I2C1->SR2; /* clear addr flag */ I2C1->CR1 |= 0x200; /* generate stop after data received */ while (!(I2C1->SR1 & 0x40)); /* Wait until RXNE flag is set */ *data++ = I2C1->DR; /* Read data from DR */ return 0; } void display(int data) { GPIOB->BSRR = 0x00F00000; GPIOB->BSRR = data << 4; } /* 16 MHz SYSCLK */ void delayMs(int n) { int i; for (; n > 0; n--) for (i = 0; i < 3195; i++) ; }