STM32F030:USART

Z kiwiki
Prejsť na: navigácia, hľadanie

Obsah

Universal Synchronous Asynchronous Receiver Transmitter

V mikrokontroléri STM32F030C4 je k dizpozícii 1 USART port. Je možné konfigurovať piny, na ktorých bude pripojený.

  1. kofigurácia: PA9 (Tx), PA10 (Rx)
  2. kofigurácia: PA2 (Tx), PA3 (Rx)
  3. kofigurácia: PA14 (Tx), PA15 (Rx)

Ako pracovať s USART

  1. Je potrebné povoliť hodinový signál pre perifériu USART nasledovne: RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE)
  2. Pre GPIO piny použité pre USART je potrebné taktiež povoliť časovanie: RCC_AHBPeriphClockCmd(...)
  3. Alternatívne funkcie:
    • Pomocou funkcie GPIO_PinAFConfig() prepojiť pin s požadovanou alternatívnou funkciou.
    • Nastaviť požadovaný GPIO pin ako alternatívnu funkciou pomocou zápisu: GPIO_InitStruct->GPIO_Mode = GPIO_Mode_AF.
    • Zavolať inicializačnú funkciu GPIO_Init().
  4. Nastaviť baudovú rýchlosť, dĺžku slova, stop bit, prioritu, hardvérovú kontrolu prenosu a režim (prijímač/vysielač) komunikácie pomocou funkcie USART_Init()
  5. Pre sybchrónny režim, povoliť časovanie, nastaviť polaritu, fázu a nastavenie posledného bitu pomocou funkcie USART_ClockInit().
  6. Pre povolenie prerušenia od USART je potrebné nastaviť vektor prerušenia pomocou funkcie NVIC_Init(...) a zaregistrovať oblsluhu prerušenia pomocou USART_ITConfig(...)
  7. Ak je potrebé DMA
    • Nastaviť DMA prenos pomocou funkcie DMA_Init().
    • Aktivovať požadovaný kanál pomocou funkcie USART_DMACmd().
  8. Povoliť rozhranie USART pomocou funkcie USART_Cmd().
  9. Ak sa použije režim DMA, povoliť DMA pomocou funkcie DMA_Cmd().

Často používané štruktúry a funkcie

USART_InitTypeDef
štruktúra pre nastavenie USART.
typedef struct
{
  // Nastavuje baudovú rýchlosť. Hodnota môže byť: 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, ...
  uint32_t USART_BaudRate;
  // definuje počet bitov v prijatom/odoslanom slove. Možné hodnoty: USART_WordLength_7b, USART_WordLength_8b, USART_WordLength_9b 
  uint32_t USART_WordLength;
  // definuje počet stop bitov. Táto hodnota sa započítava do dĺžky slova. Možné hodnoty: USART_StopBits_1, USART_StopBits_2, USART_StopBits_1%5 
  uint32_t USART_StopBits;
  // definuje typ paritu v prenášanom slove. Možné hodnoty: USART_Parity_No, USART_Parity_Even, USART_Parity_Odd
  uint32_t USART_Parity;
  // definuje smer komunikácie (príjem/vysielanie). Možné hodnoty: USART_Mode_Rx, USART_Mode_Tx 
  uint32_t USART_Mode; 
  // nastavuje/zakazuje hardvérové riadenie komunikácie. Hodnoty: USART_HardwareFlowControl_None, ..._RTS, ..._CTS, ..._RTS_CTS
  uint32_t USART_HardwareFlowControl;
} USART_InitTypeDef;

Poznámka: Hodnota USART_StopBits je súčasťou hodnoty USART_WordLength. To znamená, ža ak chceme slovo dlhé 8bit a jeden stop bit, potom treba nastaviť parameter USART_WordLength na hodnotu 9 (USART_WordLength_9b)

void USART_Init
inicializuje rozhranie USART
/**
  *         Nastaví rozhranie USART na hodnoty určené štruktúrou USART_InitTypeDef.
  * @param  USARTx: Rozhranie USART, ktoré sa bude nastavovať. Pre STM32F0 je iba USART1
  * @param  USART_InitStruct: ukazateľ na štruktúru USART_InitTypeDef obsahujúcu nastavenie rozhrania USART
  */
void USART_Init(USART_TypeDef *USARTx,USART_InitTypeDef *USART_InitStruct);
void USART_Cmd
Aktivácia rozhrania USART
/**
  *         Povolí alebo zakáže rozhranie USART
  * @param  USARTx: Rozhranie USART, ktoré sa bude nastavovať. Pre STM32F0 je iba USART1
  * @param  NewState: nový stav rozhrania USART
  *         hodnota môže byť: ENABLE alebo DISABLE.
  * @retval None
  */
void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState)
void USART_SendData
na rozhranie USART odošle dáta
/**
  *         Odošle jeden bajt cez rozhranie USART
  * @param  USARTx: Rozhranie USART, ktoré sa bude nastavovať. Pre STM32F0 je iba USART1
  * @param  Data: hodnota, ktorá sa odošle
  * @retval None
  */
void USART_SendData(USART_TypeDef* USARTx, uint16_t Data)
uint16_t USART_ReceiveData
príjem dát
/**
  *         Vráti naposledy prijaté dáta
  * @param  USARTx: Rozhranie USART, ktoré sa bude nastavovať. Pre STM32F0 je iba USART1
  * @retval Prijaté dáta (1Byte)
  */
uint16_t USART_ReceiveData(USART_TypeDef* USARTx)

Príznaky prenosu

Stav rozhrania USART je možné monitorovať pomocou hodnôt nasledujúcich príznakov. Hodnoty príznakov sa dajú vyčítať funkciou USART_GetFlagStatus.

  • USART_FLAG_RXNE - príznak neprázdneho prijímacieho registra
  • USART_FLAG_IDLE - príznak nečinnosti linky
  • USART_FLAG_ORE - príznak OverRun
  • USART_FLAG_NE - príznak chyby spôsobenej zašumením dát (Noise Error).
  • USART_FLAG_FE - príznak chyby prijatého rámca (Framming Error)
  • USART_FLAG_PE - príznak chyby parity (Parity Error)
  • USART_FLAG_TC - príznak ukončenia prenosu (Transmission Complete)
  • USART_FLAG_TXE - príznak prázdneho vysielacieho registra
  • USART_FLAG_CTS - príznak zmeny bitu CTS
  • USART_FLAG_RTO - príznak dosiahnutia max. času pre príjem (Receive TimeOut)
  • USART_FLAG_BUSY - príznak zaneprázdnenia

Príklady

Jednoduché posielanie znakov

Zadanie: Na rozhranie USART1 sa budú postupne posielať všetky čitateľné znaky tabuľky ASCII.

Riešenie: Rozhranie USART nastavíme nasledovne:

  • rýchlosť 19200 baud/s
  • dĺžka slova = 8 bit + 1 stop bit
  • parita = párna

Čitateľné znaky sú v tabuľke ASCII od 32 po 127

void GPIO_Configuration(void)
{
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
 
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
 
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1); // USART1 TX
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);
}
 
void USART_Configuration(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
 
    USART_InitTypeDef USART_InitStructur;
    USART_InitStructur.USART_BaudRate = 19200;
    USART_InitStructur.USART_WordLength = USART_WordLength_9b;
    USART_InitStructur.USART_StopBits = USART_StopBits_1;
    USART_InitStructur.USART_Parity = USART_Parity_Even;
    USART_InitStructur.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructur.USART_Mode = USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructur);
    USART_Cmd(USART1,ENABLE);
}
 
void delay (int a);
 
int main(void)
{
    GPIO_Configuration();
    USART_Configuration();
    uint8_t ascii_znak=0;
    while(1)
    {
        USART_SendData(USART1, ascii_znak+32); 
        //pokiaľ sa znak neodoslal, tak čakám
        while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
        ascii_znak++;
        // znaky budem cykliť o 0 (+32) do 95 (+32), teda od 32 po 127
        ascii_znak %= 95;
        //len kvoli spomaleniu programu
        delay(2000);
    }
}
 
void delay (int a)
{   volatile int r,s=0;
    for (r=0 ; r < a ; r++){
        s++;
    }
    return;
}

Posielanie a príjem znaku

Zadanie: Program bude na rozhraní USART1 očakávať jednotlivé znaky. Po prijatí znaku, tento znak odošle naspäť.

Riešenie:

  • Rozhranie USART nastavíme ako v predchádzajúcom príklade
  • Rozhranie USART bude teraz vstupno/výstupné
void GPIO_Configuration(void)
{
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
 
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
 
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1); // USART1 TX
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);
}
 
void USART_Configuration(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
 
    USART_InitTypeDef USART_InitStructur;
    USART_InitStructur.USART_BaudRate = 19200;
    USART_InitStructur.USART_WordLength = USART_WordLength_9b;
    USART_InitStructur.USART_StopBits = USART_StopBits_1;
    USART_InitStructur.USART_Parity = USART_Parity_Even;
    USART_InitStructur.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    // zmena je tu: rozhranie je obojsmerné
    USART_InitStructur.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructur);
    USART_Cmd(USART1,ENABLE);
}
 
int main(void)
{
    GPIO_Configuration();
    USART_Configuration();
    uint8_t ascii_znak=0;
    while(1)
    {
        // čakanie ja príjem znaku - čakáme pokiaľ je prázdny prijímací register
        while(1){
            if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE) == SET){
                // načítanie 1 znaku
                ascii_znak = USART_ReceiveData(USART1);
                break;
            }
        }
        // odoslanie znaku
        USART_SendData(USART1, ascii_znak);
        while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
    }
}

Vylepšená komunikácia

Zadanie: Program bude na rozhraní USART1 očakávať jednotlivé znaky - malé písmená abecedy. Po prijatí znaku odošle naspäť toto písmeno ako veľké. Iné ako malé písmená budeme ignotrovať. Príjem znakov sa bude riešiť v samostatnom prerušení.

Riešenie:

  • V tabuľke ASCII:
    • malé písmená: 97 - 122
    • veľké písmená: 65 - 90
  • Pre príjem znaku je potrebné zaregistrovať obsluhu rozhrania USART v prerušení.
    • Prerušenie sa vyvolá, ak sa na rozhraní USART objaví znak

Poznámky ku kódu

  • konfigurácia vektora prerušenia - NVIC_Configuration
  • Obsluha prerušenia rozhrania USART - USART1_IRQHandler
    • vykonávame akciu, len ak sú v prijímacom registri nejaké dáta
    • flag_received - príznak, že bol prijatý znak
uint8_t ascii_znak=0;
 
void GPIO_Configuration(void)
{   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1); // USART1 TX
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);
}
 
void USART_Configuration(void)
{   RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
    USART_InitTypeDef USART_InitStructur;
    USART_InitStructur.USART_BaudRate = 19200;
    USART_InitStructur.USART_WordLength = USART_WordLength_9b;
    USART_InitStructur.USART_StopBits = USART_StopBits_1;
    USART_InitStructur.USART_Parity = USART_Parity_Even;
    USART_InitStructur.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructur.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructur);
    USART_Cmd(USART1,ENABLE);
    // ZMENA: povolíme prerušenie pri udalosti "prázdny prijímací register"
    // obsluha tejto udalosti bude vo funkcii USART1_IRQHandler
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
}
 
void NVIC_Configuration()
{   NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}
 
// automaticky sa sputí pri príznaku USART_IT_RXNE
void USART1_IRQHandler(void)
{
    if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
    {   // nacitanieznaku
        ascii_znak = USART_ReceiveData(USART1);
        // info, že sme načítali znak
        flag_received = 1;
    }
}
 
/**         Skonvertuje malé písmeno na veľké. Písmeno je uložené v globálnej premennej ascii_znak
  *         Ak nie je ascii_znak malé písmeno, nič sa nerobí.
  * @return 1 - ak bol ascii_znak malé písmeno, inak 0
 */
uint8_t kontrola_znaku(){
    if(ascii_znak>=97 && ascii_znak<=122){
        ascii_znak -= 32;
        return 1;
    }
    return 0;
}
 
int main(void)
{
    GPIO_Configuration();
    USART_Configuration();
    NVIC_Configuration();
 
    while(1)
    {   // ak boli prijaté dáta
        if(flag_received)
        {
            // bude sa odosialať odpoveď, iba ak vráti funkcia kontrola_znaku hodnotu 1
            if(kontrola_znaku()==1){
                USART_SendData(USART1, ascii_znak);
                while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
                // po odoslaní vynulujeme príznak
                flag_received = 0;
            }
        }
    }
}


Vylepšená komunikácia 2

Zadanie: Zadanie rovnaké ako "Vylepšená komunikácia". Odosielanie bude prebiehať v prerušení rozhrania USART

Poznámky ku kódu

  • Zmeny sa týkajú obsluhy prerušenia rozhrania USART:
    • spracovanie príznaku USART_IT_RXNE je rovnaké
    • spracovanie príznaku USART_IT_TXE:
      • príznak sa vyvolá manuálne z hlavnej slučky main
      • odošle sa jeden znak
      • zakáže sa prerušenie s príznakom USART_IT_TXE, pretože už nie je čo odosielať
uint8_t ascii_znak=0;
 
void GPIO_Configuration(void)
{   
/*
 *  rovnaké ako v predchádzajúcom príklade
 */
}
 
void USART_Configuration(void)
{   
/*
 *  rovnaké ako v predchádzajúcom príklade
 */
}
 
void NVIC_Configuration()
{  
/*
 *  rovnaké ako v predchádzajúcom príklade
 */
}
 
void USART1_IRQHandler(void)
{
    if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
    {   ascii_znak = USART_ReceiveData(USART1);
        flag_received = 1;
    }
    // Vyvolá sa okamžite po povolení príznaku USART_IT_TXE v hlavnej slučke
    // pretože vysielací register je prázdny - môžeme teda vysielať
    if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
    {   USART_SendData(USART1, ascii_znak);
        while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
        flag_received = 0;
        USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
    }
}
 
uint8_t kontrola_znaku(){
/*
 *  rovnaké ako v predchádzajúcom príklade
 */
}
 
int main(void)
{
    GPIO_Configuration();
    USART_Configuration();
    NVIC_Configuration();
 
    while(1)
    {   
        if(flag_received)
        {
            if(kontrola_znaku()==1)
            {
                USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
            }
        }
    }
}
Osobné nástroje
Menné priestory

Varianty
Operácie
Navigácia
Rýchle linky
Nástroje
Tlačiť/exportovať