[APLIKACJA] STM32 i monochromatyczny wyświetlacz OLED
Na rysunku 4 pokazano sekwencję zapisywania danych przez mastera do slave.

Rys. 4. Sekwencja zapisania danych na magistrali I2C
Z zadaniami wykonywanymi przez mastera na magistrali są związane zdarzenia (events, EV):
- EV5: SB1, zerowana po odczytaniu rejestru SR1 . Po tym jest zapisywany rejestr DR z bajtem adresu slave uzupełnionym o bit R/W=0
- EV6: ADDR=1, ustawiany w rejestrze SR1, zerowany przez odczytanie rejestru SR2
- EV8_1: TxE=1, rejestr przesuwny jest pusty, rejestr danych jest pusty, zapisanie danej do rejestru DR
- EV8: TxE=1, rejestr przesuwny nie jest pusty, rejestr danych jest pusty, zerowany przez zapis rejestru DR
- EV8_2:, TxE=1, BTF=1 – żądanie sekwencji STOP. TxE i BTF zerowany sprzętowo przez sekwencję STOP
Nota aplikacyjna zawiera procedurę wysyłania przez I2C zawartości bufora z danymi. Jej argumentami są: numer interfejsu (I2C1, lub I2C2) wskaźnik na bufor z danymi, ilość danych do wysłania, tryb pracy i adres slave. Możliwe są 3 tryby pracy: polling, interrupt i DMA, z których zweryfikowano dwa: polling i DMA.
Na listingu 3 pokazano procedurę wysyłania do sterownika wyświetlacza zawartości bufora w trybie polling. W pierwszej kolejności jest inicjowana sekwencja START. Zakończenie tej sekwencji jest sygnalizowane przez wyzerowanie bitu SB (zdarzenie EV5). Jeżeli sekwencja START nie zakończy się w określonym czasie, to procedura kończy działanie i zwraca kod błędu. Po sekwencji START jest wysyłany adres SLAVE przez zapisanie jego wartości do rejestru DR. Wysłanie adresu i odebranie bitu potwierdzenia A jest sygnalizowane ustawieniem bitu ADDR. Jeżeli wszystko przebiega poprawnie, to można zapisywać w pętli kolejne dane do rejestru DR. Wysłanie kompletnej danej jest sygnalizowane ustawieniem bitu TxE.
List. 3. Wysyłanie zawartości bufora do kontrolera wyświetlacza w trybie polling
else if (Mode == Polling) /* I2Cx Master Transmission using Polling */
{
Timeout = 0xFFFF;
/* Send START condition */
I2Cx->CR1 |= CR1_START_Set;
/* Wait until SB flag is set: EV5 */
while ((I2Cx->SR1&0x0001) != 0x0001)
{
if (Timeout-- == 0)
return Error;
}
/* Send slave address */
/* Reset the address bit0 for write*/
//SlaveAddress &= OAR1_ADD0_Reset;
Address = SlaveAddress;
/* Send the slave address */
I2Cx->DR = Address;
Timeout = 0xFFFF;
/* Wait until ADDR is set: EV6 */
while ((I2Cx->SR1 &0x0002) != 0x0002)
{
if (Timeout-- == 0)
return Error;
}
/* Clear ADDR flag by reading SR2 register */
temp = I2Cx->SR2;
/* Write the first data in DR register (EV8_1) */
I2Cx->DR = *pBuffer;
/* Increment */
pBuffer++;
/* Decrement the number of bytes to be written */
NumByteToWrite--;
/* While there is data to be written */
while (NumByteToWrite--)
{
/* Poll on BTF to receive data because in polling mode we can not guarantee the
EV8 software sequence is managed before the current byte transfer completes */
while ((I2Cx->SR1 & 0x00004) != 0x000004);
/* Send the current byte */
I2Cx->DR = *pBuffer;
/* Point to the next byte to be written */
pBuffer++;
}
/* EV8_2: Wait until BTF is set before programming the STOP */
while ((I2Cx->SR1 & 0x00004) != 0x000004);
/* Send STOP condition */
I2Cx->CR1 |= CR1_STOP_Set;
/* Make sure that the STOP bit is cleared by Hardware */
while ((I2Cx->CR1&0x200) == 0x200);
}
Na listingu 4 pokazano procedurę wysyłania zawartości bufora do kontrolera wyświetlacza z wykorzystaniem kanału DMA.
List. 4. Wysyłanie zawartości bufora do kontrolera wyświetlacza w trybie DMA
if (Mode == DMA) /* I2Cx Master Transmission using DMA */
{
Timeout = 0xFFFF;
/* Configure the DMA channel for I2Cx transmission */
I2C_DMAConfig (I2Cx, pBuffer, NumByteToWrite, I2C_DIRECTION_TX);
/* Enable the I2Cx DMA requests */
I2Cx->CR2 |= CR2_DMAEN_Set;
/* Send START condition */
I2Cx->CR1 |= CR1_START_Set;
/* Wait until SB flag is set: EV5 */
while ((I2Cx->SR1&0x0001) != 0x0001)
{
if (Timeout-- == 0)
return Error;
}
Timeout = 0xFFFF;
/* Send slave address */
/* Reset the address bit0 for write */
SlaveAddress &= OAR1_ADD0_Reset;
Address = SlaveAddress;
/* Send the slave address */
I2Cx->DR = Address;
/* Wait until ADDR is set: EV6 */
while ((I2Cx->SR1&0x0002) != 0x0002)
{
if (Timeout-- == 0)
return Error;
}
/* Clear ADDR flag by reading SR2 register */
temp = I2Cx->SR2;
if (I2Cx == I2C1)
{
/* Wait until DMA end of transfer */
while (!DMA_GetFlagStatus(DMA1_FLAG_TC6));
/* Disable the DMA1 Channel 6 */
DMA_Cmd(I2C1_DMA_CHANNEL_TX, DISABLE);
/* Clear the DMA Transfer complete flag */
DMA_ClearFlag(DMA1_FLAG_TC6);
}
else /* I2Cx = I2C2 */
{
/* Wait until DMA end of transfer */
while (!DMA_GetFlagStatus(DMA1_FLAG_TC4));
/* Disable the DMA1 Channel 4 */
DMA_Cmd(I2C2_DMA_CHANNEL_TX, DISABLE);
/* Clear the DMA Transfer complete flag */
DMA_ClearFlag(DMA1_FLAG_TC4);
}
/* EV8_2: Wait until BTF is set before programming the STOP */
while ((I2Cx->SR1 & 0x00004) != 0x000004);
/* Program the STOP */
I2Cx->CR1 |= CR1_STOP_Set;
/* Make sure that the STOP bit is cleared by Hardware */
while ((I2Cx->CR1&0x200) == 0x200);
}

Technologie End of Life i bezpieczeństwo sieci – wyzwania Europy związane z tzw. długiem technologicznym
Najczęstsze błędy firm przy wyborze dostawcy energii i jak ich uniknąć
Fotorezystor, czyli czujnik światła dwojakiego działania. Przykład innowacji w automatyce i elektronice możliwej dzięki technologii fotooporników 



