LinkedIn YouTube Facebook
Szukaj

Wstecz
Artykuły

[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);
  }
Absolwent Wydziału Elektroniki Politechniki Wrocławskiej, współpracownik miesięcznika Elektronika Praktyczna, autor książek o mikrokontrolerach Microchip i wyświetlaczach graficznych, wydanych nakładem Wydawnictwa BTC. Zawodowo zajmuje się projektowaniem zaawansowanych systemów mikroprocesorowych.