czwartek, 12 listopada 2015

[4] STM32 M3 - Nucleo - F103RB - USART

Tym razem opisze sposób obsługi USART. Niewiele się będzie to różnić od przykładu opisanego prze zemnie dla mikrokontrolera F411RE.

Wstęp


Mikrokontroler znajdujący się na płytce Nucleo wyposażono w 3 interfejsy USART. Na płytce także znajduje się konwerter USART na USB. Dzięki temu nie trzeba wykorzystywać dodatkowego zewnętrznego urządzenia.

Obsługa USART2 - wbudowany konwerter


USART2 został podłączony do wcześniej wspominanego konwertera. Jego wyprowadzenia znajdują się na pinie PA2 oraz PA3. Odpowiednio są to piny TX oraz RX.

Linia PA2, po której będą wysyłane dane z mikrokontrolera musi zostać skonfigurowana w trybie funkcji alternatywnej, jako wyjście push pull. Natomiast linia PA3 z niej są odbierane dane przez układ. Musi ona zostać skonfigurowana w trybie wejścia o wysokiej impedancji.

#include "stm32f10x.h"
 
void GPIOInit(void);
void USARTInit(void);
void USART_Send(volatile char*);
void Delay(int);
 
int main(void)
{
 GPIOInit();
 USARTInit();
 
 USART_Send("Przed petla!\n");
 
 while (1) {
 }
}
 
void GPIOInit(void)
{
 GPIO_InitTypeDef GPIOInit;
 
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
 
 //PA2 Tx
 GPIO_StructInit(&GPIOInit);
 GPIOInit.GPIO_Pin = GPIO_Pin_2;
 GPIOInit.GPIO_Speed = GPIO_Speed_50MHz;
 GPIOInit.GPIO_Mode = GPIO_Mode_AF_PP;
 GPIO_Init(GPIOA, &GPIOInit);
 
 //PA3 Rx
 GPIOInit.GPIO_Pin = GPIO_Pin_3;
 GPIOInit.GPIO_Speed = GPIO_Speed_50MHz;
 GPIOInit.GPIO_Mode = GPIO_Mode_IN_FLOATING;
 GPIO_Init(GPIOA, &GPIOInit);
}
 
void USARTInit(void)
{
 USART_InitTypeDef USARTInit;
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
 
 //Ustawienie prędkości transmisji 9600bps
 USARTInit.USART_BaudRate = 9600;
 
 //Ustawienie dlugosci slowa
 USARTInit.USART_WordLength = 8;
 
 //Ustawienie bitu stopu
 USARTInit.USART_StopBits = USART_StopBits_1;
 
 //Brak kontroli parzystosci
 USARTInit.USART_Parity = USART_Parity_No;
 
 //Kontrola przepływu danych
 USARTInit.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
 
 //Tryb pracy TX i RX
 USARTInit.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
 
 USART_Init(USART2, &USARTInit);
 USART_Cmd(USART2, ENABLE);
}
 
void USART_Send(volatile char *c)
{
  //Pętla działa do czasu wyslania ostatniego znaku
  while(*c)
  {
    //Sprawdza czy rejestr danych został opróżniony
    while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
    //Prześlij dane,
    USART_SendData(USART2, *c);
    *c++;
  }
}
void Delay(int time)
{
    int i;
    for (i = 0; i < time * 5000; i++) {
    }
}
 

Obsługa zewnętrznego USARTU


Obsługa zewnetrznego USARTU polega właściwie dokładnie na tym samym. Jedynym wyjątkiem jest deklaracja innych pinów jako TX i RX oraz zmiana parametru USART na inny wykorzystywany. No i oczywiście należy podłączyć zewnętrzny konwerter UART na USB.

Do wyboru jest USART1, USART2 oraz USART3:

  • USART1 TX - PA9 RX - PA10
  • USART2 TX - PA2 RX - PA3
  • USART3 TX - PB10 RX - PB11


Możliwe jest także prze mapowanie pinów. Wtedy możliwe jest następujące ustawienie:

  • USART2 TX - PB6 RX - PB7
  • USART2 TX - PD5 RX - PD6 
  • USART3 TX - PC10  RX - PC11 
  • USART3 TX - PD8 RX - PD9

Wysyłanie danych


Do wysłania danych z komputera na mikrokontroler wykorzystywana jest funkcja USART_ReceiveData(USART2). 
USARTGetc pozwala na wyslanie odebranej danej w formacie char z mikrokontrolera na komputer.


#include "stdio.h"
#include "stm32f10x.h"
 
void GPIOInit(void);
void USARTInit(void);
void USARTSend(volatile char*);
void SendCharc(volatile char);
 
int main(void)
{
 GPIOInit();
 USARTInit();
 
 USARTSend("Przed petla!\n");
 
 while (1) {
  if (USART_GetFlagStatus(USART2, USART_FLAG_RXNE))
  {
      char c = USART_ReceiveData(USART2);
      SendCharc(c);
  }
 }
}
 
void GPIOInit(void)
{
 GPIO_InitTypeDef GPIOInit;
 
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
 
 //PA2 Tx
 GPIO_StructInit(&GPIOInit);
 GPIOInit.GPIO_Pin = GPIO_Pin_2;
 GPIOInit.GPIO_Speed = GPIO_Speed_50MHz;
 GPIOInit.GPIO_Mode = GPIO_Mode_AF_PP;
 GPIO_Init(GPIOA, &GPIOInit);
 
 //PA3 Rx
 GPIOInit.GPIO_Pin = GPIO_Pin_3;
 GPIOInit.GPIO_Speed = GPIO_Speed_50MHz;
 GPIOInit.GPIO_Mode = GPIO_Mode_IN_FLOATING;
 GPIO_Init(GPIOA, &GPIOInit);
}
 
void USARTInit(void)
{
 USART_InitTypeDef USARTInit;
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
 
 //Ustawienie prędkości transmisji 9600bps
 USARTInit.USART_BaudRate = 9600;
 
 //Ustawienie dlugosci slowa
 USARTInit.USART_WordLength = 8;
 
 //Ustawienie bitu stopu
 USARTInit.USART_StopBits = USART_StopBits_1;
 
 //Brak kontroli parzystosci
 USARTInit.USART_Parity = USART_Parity_No;
 
 //Kontrola przepływu danych
 USARTInit.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
 
 //Tryb pracy TX i RX
 USARTInit.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
 
 USART_Init(USART2, &USARTInit);
 USART_Cmd(USART2, ENABLE);
}
 
void SendCharc(volatile char c)
{
 while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
 USART_SendData(USART2, c);
}
 
void USARTSend(volatile char *c)
{
  //Pętla działa do puki będzie jakiś znak do wysłania
 while(*c)
 {
    //Sprawdza czy rejestr danych został opróżniony
    while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
    //Prześlij dane,
    USART_SendData(USART2, *c);
    *c++;
  }
}

Funckja printf


Tym razem zastosuje funkcję printf do przesyłania danych. Nie będę się tu za bardzo rozpisywał, ponieważ zostało to prze zemnie opisane przy mikrokontrolerze F411RE. 

W związku z tym wrzucam od razu program. Ważniejsze rzeczy zostały opisałem w komentarzach w programie.

#include "stdio.h"
#include "stm32f10x.h"
 
void GPIOInit(void);
void USARTInit(void);
void USARTSend(volatile char*);
void SendCharc(volatile char);
int __io_putchar(int c);
 
int main(void)
{
 GPIOInit();
 USARTInit();
 
 USARTSend("Przed petla!\n");
 printf("Funckja Printf!\n");
 
 while (1) {
 
 }
}
 
void GPIOInit(void)
{
 GPIO_InitTypeDef GPIOInit;
 
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
 
 //PA2 Tx
 GPIO_StructInit(&GPIOInit);
 GPIOInit.GPIO_Pin = GPIO_Pin_2;
 GPIOInit.GPIO_Speed = GPIO_Speed_50MHz;
 GPIOInit.GPIO_Mode = GPIO_Mode_AF_PP;
 GPIO_Init(GPIOA, &GPIOInit);
 
 //PA3 Rx
 GPIOInit.GPIO_Pin = GPIO_Pin_3;
 GPIOInit.GPIO_Speed = GPIO_Speed_50MHz;
 GPIOInit.GPIO_Mode = GPIO_Mode_IN_FLOATING;
 GPIO_Init(GPIOA, &GPIOInit);
}
 
void USARTInit(void)
{
 USART_InitTypeDef USARTInit;
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
 
 //Ustawienie prędkości transmisji 9600bps
 USARTInit.USART_BaudRate = 9600;
 
 //Ustawienie dlugosci slowa
 USARTInit.USART_WordLength = 8;
 
 //Ustawienie bitu stopu
 USARTInit.USART_StopBits = USART_StopBits_1;
 
 //Brak kontroli parzystosci
 USARTInit.USART_Parity = USART_Parity_No;
 
 //Kontrola przepływu danych
 USARTInit.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
 
 //Tryb pracy TX i RX
 USARTInit.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
 
 USART_Init(USART2, &USARTInit);
 USART_Cmd(USART2, ENABLE);
}
 
void SendCharc(volatile char c)
{
 while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
 USART_SendData(USART2, c);
}
 
int __io_putchar(int c)
{
 SendCharc(c);
 return c;
}
 
void USARTSend(volatile char *c)
{
  //Pętla działa do puki będzie jakiś znak do wysłania
 while(*c)
 {
    //Sprawdza czy rejestr danych został opróżniony
    while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
    //Prześlij dane,
    USART_SendData(USART2, *c);
    *c++;
  }
}