STM32Butterfly2: obsługa zewnętrznego RTC z I2C
Poniżej przedstawiono listing programu głównego.
int main(void) { //Initialize system timer time_init(); //Initialize nokia display nlcd_init(); //Initialize the i2c module i2cm_init(I2C_SPEED); //Print welcome string nlcd_put_string( "www.boff.pl", 0, 0 ); //Register configuration static const uint8_t pgm_regs[] = { 0x00, //Start Addr 0x00, //Sec 0x30, //Min 0x20, //Hour 0x04, //Day num 0x05, //day 0x06, //Month 0x07, //Year 0x00 //Config }; static const uint8_t sw_addr = 0; uint8_t buf[RTC_REGS_SIZE]; int code = i2cm_transfer_7bit(I2C_RTC_ADDR,pgm_regs,sizeof(pgm_regs),NULL,0); if(code<0) { print_i2cerr(code); for(;;); //Fail never end loop } for( ;;) { //Send configuration registgers code = i2cm_transfer_7bit( I2C_RTC_ADDR,&sw_addr,sizeof(sw_addr),buf, sizeof(buf) ); if(code==0) { print_date(buf); } else { print_i2cerr(code); for(;;); //Fail never end loop } wait_ms(MEASURE_DELAY_TIME); } return 0; }
Pierwszym działaniem w programie głównym jest skonfigurowanie licznika SysTick, realizuje to funkcja time_init(). Jej działanie sprowadza się do określenia częstotliwości występowania przerwania od licznika SysTick, ustawienia priorytetu przerwania oraz włączenia licznika.
Drugim działaniem jest wywołanie funkcji nlcd_init(), która opowiada za konfigurację wyświetlacza pochodzącego z telefonu Nokia 3310. Jej działanie polega na włączeniu zegarów dla wykorzystywanych portów GPIO i kontrolera SPI i skonfigurowaniu linii używanych w transmisji przez magistralę SPI oraz dodatkowych sterujących wyświetlaczem. Funkcja konfigurująca wyświetlacz po przeprowadzeniu konfiguracji linii wysyła cykl komend do wyświetlacza, które go inicjalizują.
Następnym działaniem jest konfiguracja kontrolera I2C. Odpowiada za to funkcja i2cm_init, która jako parametr przyjmuje częstotliwość z jaką transmitowane są dane. Poniżej przedstawiono listing funkcji.
errno_t i2cm_init( unsigned clk_speed) { //GPIO configuration RCC->APB2ENR |= I2C1_GPIO_ENR; io_config(I2C1_PORT,I2C1_SDA_PIN,GPIO_MODE_50MHZ,GPIO_CNF_ALT_OD); io_config(I2C1_PORT,I2C1_SCL_PIN,GPIO_MODE_50MHZ,GPIO_CNF_ALT_OD); io_set(I2C1_PORT,I2C1_SCL_PIN); io_set(I2C1_PORT,I2C1_SDA_PIN); //I2C module configuration RCC->APB1ENR |= I2C1_ENR; /* Enable I2C module*/ i2c->CR1 |= CR1_PE_SET; /* Reset the i2c device */ i2c->CR1 |= CR1_SWRST; nop(); i2c->CR1 &= ~CR1_SWRST; uint16_t tmpreg = i2c->CR2; /* Clear frequency FREQ[5:0] bits */ tmpreg &= CR2_FREQ_RESET; tmpreg |= (uint16_t)(CONFIG_PCLK1_HZ/1000000); i2c->CR2 = tmpreg; //Set speed i2cm_set_speed(clk_speed); /* CR1 configuration */ /* Get the I2Cx CR1 value */ tmpreg = i2c->CR1; /* Clear ACK, SMBTYPE and SMBUS bits */ tmpreg &= CR1_CLEAR_MASK; /* Configure I2Cx: mode and acknowledgement */ /* Set SMBTYPE and SMBUS bits according to I2C_Mode value */ /* Set ACK bit according to I2C_Ack value */ tmpreg |= I2C_MODE_I2C | I2C_ACK_ENABLE; /* Write to I2Cx CR1 */ i2c->CR1 = tmpreg; /* Set I2Cx Own Address1 and acknowledged address */ i2c->OAR1 = I2C_AcknowledgedAddress_7bit; i2c->SR1 = 0; i2c->SR2 = 0; /* Enable interrupt controller */ nvic_set_priority( I2C1_EV_IRQn, IRQ_PRIO, IRQ_SUB); nvic_set_priority( I2C1_ER_IRQn, IRQ_PRIO, IRQ_SUB); nvic_irq_enable(I2C1_EV_IRQn,true); nvic_irq_enable(I2C1_ER_IRQn,true); return ERR_OK; }