11.1. JEDNOSMĚRNÁ KOMUNIKACE MASTER->SLAVE A MASTER<-SLAVE
11.1.1.2
I2C3
Nastavení I2C3 se trochu liší. První rozdíl je, že u pinů již není třeba aktivovat pull-up rezistory. To stačí pouze u jedné dvojice pinů komunikace. Další změny vychází z toho, že I2C3 pracuje v našem příkladu jako obvod Slave. Proto u něj aktivujeme registr držící Slave adresu, a tu pak do něj nahrajeme ze vstupního parametru funkce. Poslední změnou je povolení přerušení při shodě přijaté adresy s právě uloženou Slave adresou. Bez aktivace a obsluhy tohoto přerušení nebude periferie reagovat na přijetí shodné adresy potvrzovacím ACK signálem, takže komunikace nebude možná. V závěru opět povolíme linku přerušení pro ARM a zapneme periferii. void I2C3_init(uint8_t AdresaSlave) { // zapne hodinovy signal pro port C RCC->IOPENR |= RCC_IOPENR_GPIOCEN; // vynuluje nastaveni pinu PC0 a PC1 (vstupni rezim) GPIOC->MODER &= ~(GPIO_MODER_MODE0 | GPIO_MODER_MODE1); // nastavi piny PC0 a PC1 do alternativniho rezimu GPIOC->MODER |= (GPIO_MODER_MODE0_1 | GPIO_MODER_MODE1_1); // nastavi alternativni rezim 7 pro piny PC0 a PC1 GPIOC->AFR[0] |= ((7U << GPIO_AFRL_AFSEL0_Pos) | (7 << GPIO_AFRL_AFSEL1_Pos)); // nastavi piny PC0 a PC1 do rezimu open-drain GPIOC->OTYPER |= (GPIO_OTYPER_OT_0 | GPIO_OTYPER_OT_1); // zapne hodinovy signal pro I2C3 RCC->APB1ENR |= RCC_APB1ENR_I2C3EN; // povoli a nastavi adresu Slave obvodu I2C3->OAR1 |= ((AdresaSlave << I2C_OAR1_OA1_Pos) | I2C_OAR1_OA1EN); // povoli preruesni pri shode Slave adresy I2C3->CR1 |= I2C_CR1_ADDRIE; // povoli preruseni I2C3 ARM jadra NVIC->ISER[0] |= (1U << I2C3_IRQn);
}
// zapne I2C3 I2C3->CR1 |= I2C_CR1_PE;
89 Ukázka elektronické knihy, UID: KOS505583
KAPITOLA 11. I2C
11.1.2 11.1.2.1
Funkce periferií I2C1 - vysílání
Všechny následující funkce budou velmi podobné jak funkcím z příkladu komunikací UART a SPI , tak sobě navzájem. Tato funkce je volána programem, když je nutné začít odesílat data, nebo v přerušení, jestliže je třeba poslat další data. Tělo první podmínky není třeba popisovat. Funguje stejně jako u příkladů jiných komunikací. Program druhé podmínky je zajímavější. Je to dáno tím, že I2C1 bude v komunikaci fungovat jako obvod Master. V předposledním řádku je totiž do řídícího registru I2C1 vložena adresa Slave obvodu, se kterým má být navázána komunikace. Dále se do registru zapisuje počet bytů, které budeme chtít v rámci komunikace poslat. Jelikož jsme v inicializaci I2C1 nastavili automatické vytvoření ukončovacího signálu komunikace, bude po odeslání daného počtu bytů komunikace automaticky ukončena. Posledním zápisem do tohoto registru na pozici bitu START se vytvoří startovací signál komunikace, po kterém je okamžitě odeslána adresa Slave obvodu. Poslední příkaz povoluje přerušení při prázdném vysílacím registru.
90 Ukázka elektronické knihy, UID: KOS505583
11.1. JEDNOSMĚRNÁ KOMUNIKACE MASTER->SLAVE A MASTER<-SLAVE
void I2C1_TX(uint8_t* dataOdeslani, uint8_t delka, uint8_t AdresaSlave) { static uint8_t dataKOdeslani[MAX_DELKA_DAT]; static uint8_t delkaDat = 0U; static uint8_t delkaDatZaloha = 0U; // Volani prerusenim if (delkaDat != 0U) { // odesle dalsi znak dat I2C1->TXDR = dataKOdeslani[delkaDatZaloha - delkaDat]; delkaDat--; if (delkaDat == 0U) { // zakaze preruseni pri prazdnem vysilacim registru I2C1->CR1 &= ~I2C_CR1_TXIE; } return; } // Volani programem - zkopiruj data if(delka != 0U) { // nastavi delku dat delkaDatZaloha = delkaDat = delka; // zkopiruje data k odeslani for (uint8_t index = 0U; index < delkaDat; index++) { dataKOdeslani[index] = dataOdeslani[index]; } // nastavi adresu Slave obvodu, pocet bajtu k odeslani a zacne komunikaci I2C1->CR2 |= ((AdresaSlave << I2C_CR2_SADD_Pos) | (delka << I2C_CR2_NBYTES_Pos) | I2C_CR2_START);
}
}
// povoli preruseni pri prazdnem vysilacim registru I2C1->CR1 |= I2C_CR1_TXIE;
91 Ukázka elektronické knihy