czwartek, 10 marca 2016

[9] STM32F4 - Discovery - USART, printf

W tym poście opiszę sposób włączenia oraz obsługi USART-u poprzez płytkę Discovery.

Opis


UART i USART można podłączyć w następującej konfiguracji do pinów:

W odróżnieniu od płytki Nucleo, Discovery nie ma wbudowanego konwertera, w związku z tym należy się posłużyć zewnętrznym.

Dostępne piny dla tej magistrali przedstawiłem poniżej:

USART1 - Zestaw pinów 1: TX PA9, RX PA10; 2: TX PB6, RX PB7;
USART2 - Zestaw pinów 1: TX PA2, RX PA3; 2: TX PD5, RX PD6;
USART3 - Zestaw pinów 1: TX PB10, RX PB11; 2: TX PC10, RX PC11; 3: TX PD8, RX PD9;
UART4 -  Zestaw pinów 1: TX PA0, RX PA1; 2: TX PC10, RX PC11;
UART5 - Zestaw pinów 1: TX PC12, RX PD2;
USART6 - Zestaw pinów 1: TX PC6, RX PC7; 2: TX PG14, RX PG9;
UART7 - Zestaw pinów 1: TX PE8, RX PE7; 2: TX PF7, RX PF6;
UART8 - Zestaw pinów 1: TX PE1, RX PE0;

USART1 i USART6 taktowane są poprzez APB 2, pozostałe natomiast przez APB 1. TX odpowiada za transmisję danych, RX natomiast jest odpowiedzialny za odbieranie.

Płytka Discovery niestety nie posiada wbudowanego konwertera, w związku z tym w celu uzyskania komunikacji należy posłużyć się zewnętrznym układem podłączonym do odpowiednich wyprowadzeń.

Program:


W tym programie przedstawię sposób wykorzystania USARTU na przerwaniach. Do tego celu wykorzystac układ 1 z podłączeniem TX do PA9 oraz RX do PA10.

  1. #include "stm32f4xx.h"
  2. #include "stm32f4xx_gpio.h"
  3. #include "stm32f4xx_rcc.h"
  4. #include "stm32f4xx_usart.h"
  5. #include "misc.h"
  6. void SendChar(char);
  7. void USART_Initialize(void);
  8. void GPIO_Initialize(void);
  9. void USART_Send(volatile char *s);
  10. int main(void)
  11. {
  12.      //Inicjalizacja pinów
  13.      GPIO_Initialize();
  14.      //Inicjalizacja USARTU
  15.      USART_Initialize();
  16.      //Wyslanie danych
  17.      USART_Send("1234");
  18.      SendChar('1');
  19.      while (1)
  20.      {
  21.      }
  22. }
  23. void USART_Initialize(void)
  24. {
  25.      //Inicjalizacja kontrolera przerwan
  26.      NVIC_InitTypeDef NVIC_InitStruct;
  27.    
  28.      //konfiguracja ukladu USART
  29.      USART_InitTypeDef USART_InitStructure;
  30.      
  31.      //Ustawienie kanalu IRQ
  32.      NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
  33.    
  34.      //Wlaczenie zegara dla USART1
  35.      RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
  36.      
  37.      //Ustawienie predkosci transmisji 9600bps
  38.      USART_InitStructure.USART_BaudRate = 9600;
  39.      //Dlugosc wysylanego slowa
  40.      USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  41.      //Ustawienie jednego bitu stopu
  42.      USART_InitStructure.USART_StopBits = USART_StopBits_1;
  43.      //Kontrola parzystosci wylaczona
  44.      USART_InitStructure.USART_Parity = USART_Parity_No;
  45.      //Wylaczenie kontroli przeplywu danych
  46.      USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  47.      //Tryb pracy linii odpowiednio odbior i nadawanie
  48.      USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  49.      
  50.      //Konfiguracja ukladu
  51.      USART_Init(USART1, &USART_InitStructure);
  52.      //Wlaczenie USART1
  53.      USART_Cmd(USART1, ENABLE);
  54.      
  55.      //Wlaczenie przerwania na RX1
  56.      USART1->CR1 |= USART_CR1_RXNEIE;
  57.    
  58.      //Wprowadzenie ustawien do przerwan
  59.      NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
  60.      NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
  61.      NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
  62.      NVIC_Init(&NVIC_InitStruct);
  63. }
  64. void GPIO_Initialize(void)
  65. {
  66.      //konfigurowanie portow GPIO
  67.      GPIO_InitTypeDef  GPIO_In;
  68.      RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
  69.      
  70.      //TX dla pinu PB6
  71.      GPIO_In.GPIO_Pin = GPIO_Pin_6;
  72.      GPIO_In.GPIO_PuPd = GPIO_PuPd_UP;
  73.      GPIO_In.GPIO_OType = GPIO_OType_PP;
  74.      GPIO_In.GPIO_Mode = GPIO_Mode_AF;
  75.      GPIO_In.GPIO_Speed = GPIO_Speed_100MHz;
  76.      GPIO_Init(GPIOB, &GPIO_In);
  77.      
  78.      //RX dla pinu PB7
  79.      GPIO_In.GPIO_Pin = GPIO_Pin_7;
  80.      GPIO_In.GPIO_Mode = GPIO_Mode_AF;
  81.      GPIO_In.GPIO_PuPd = GPIO_PuPd_UP;
  82.      GPIO_In.GPIO_OType = GPIO_OType_PP;
  83.      GPIO_In.GPIO_Speed = GPIO_Speed_100MHz;
  84.      GPIO_Init(GPIOB, &GPIO_In);
  85.      
  86.      //Wlaczenie transmisji na podanych pinach
  87.      GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_USART1);
  88.      GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_USART1);
  89. }
  90. void USART_Send(volatile char *c)
  91. {
  92.      //Petla dziala do puki bedzie jakis znak do wyslania
  93.      while(*c)
  94.      {
  95.         //Sprawdza czy rejestr danych zostal oprózniony
  96.         while( !(USART1->SR & 0x00000040) );
  97.         //Przeslij dane,
  98.         USART_SendData(USART1, *c);
  99.         *c++;
  100.      }
  101. }
  102. void SendChar(char c)
  103. {
  104.      //Sprawdza czy bufor nadawczy jest pusty
  105.      while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
  106.      USART_SendData(USART1, c);
  107. }

Drugi program będzie zawierał przykład, który będzie odbierał dane z komputera.

  1. //Program wykorzystujacy funckje printf
  2. #include "stm32f4xx.h"
  3. #include "stm32f4xx_gpio.h"
  4. #include "stm32f4xx_rcc.h"
  5. #include "stm32f4xx_usart.h"
  6. #include "stdio.h"
  7. #include "misc.h"
  8. //struktura FILE zawierajca jeden parametr
  9. struct __FILE {
  10.     int parametr;
  11. };
  12. //Stworzenie zmiennej z struktury FILE
  13. //Parametr musi miec taka nazwe
  14. FILE __stdout;
  15. void send_char(char);
  16. void USART_Initialize(void);
  17. void GPIO_Initialize(void);
  18. void USART_Send(volatile char *s);
  19. int PutFile(int ch, FILE *f);
  20. void Send_Charc(volatile char c);
  21. int main(void)
  22. {
  23.       float Wartosc2 = 1.85456;
  24.       //Inicjalizacja pinów
  25.       GPIO_Initialize();
  26.       //Inicjalizacja USARTU
  27.       USART_Initialize();
  28.       //Wyslanie danych
  29.       USART_Send("\n1234 \n");
  30.       printf("\nFunkcja printf \r\n");
  31.       printf("Zmiennoprzecinkowa - %.3f \r\n", Wartosc2);
  32.       while (1)
  33.       {
  34.        }
  35. }
  36. void USART_Initialize(void)
  37. {
  38.      //Inicjalizacja kontrolera przerwan
  39.      NVIC_InitTypeDef NVIC_InitStruct;
  40.    
  41.      //konfiguracja ukladu USART
  42.      USART_InitTypeDef USART_InitStructure;
  43.      
  44.      //Ustawienie kanalu IRQ
  45.      NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
  46.    
  47.      //Wlaczenie zegara dla USART1
  48.      RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
  49.      
  50.      //Ustawienie predkosci transmisji 9600bps
  51.      USART_InitStructure.USART_BaudRate = 9600;
  52.      //Dlugosc wysylanego slowa
  53.      USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  54.      //Ustawienie jednego bitu stopu
  55.      USART_InitStructure.USART_StopBits = USART_StopBits_1;
  56.      //Kontrola parzystosci wylaczona
  57.      USART_InitStructure.USART_Parity = USART_Parity_No;
  58.      //Wylaczenie kontroli przeplywu danych
  59.      USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  60.      //Tryb pracy linii odpowiednio odbior i nadawanie
  61.      USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  62.      
  63.      //Konfiguracja ukladu
  64.      USART_Init(USART1, &USART_InitStructure);
  65.      //Wlaczenie USART1
  66.      USART_Cmd(USART1, ENABLE);
  67.      
  68.      //Wlaczenie przerwania na RX1
  69.      USART1->CR1 |= USART_CR1_RXNEIE;
  70.    
  71.      //Wprowadzenie ustawien do przerwan
  72.      NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
  73.      NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
  74.      NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
  75.      NVIC_Init(&NVIC_InitStruct);
  76. }
  77. void GPIO_Initialize(void)
  78. {
  79.      //konfigurowanie portow GPIO
  80.      GPIO_InitTypeDef  GPIO_In;
  81.      RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
  82.      
  83.      //TX dla pinu PB6
  84.      GPIO_In.GPIO_Pin = GPIO_Pin_6;
  85.      GPIO_In.GPIO_PuPd = GPIO_PuPd_UP;
  86.      GPIO_In.GPIO_OType = GPIO_OType_PP;
  87.      GPIO_In.GPIO_Mode = GPIO_Mode_AF;
  88.      GPIO_In.GPIO_Speed = GPIO_Speed_100MHz;
  89.      GPIO_Init(GPIOB, &GPIO_In);
  90.      
  91.      //RX dla pinu PB7
  92.      GPIO_In.GPIO_Pin = GPIO_Pin_7;
  93.      GPIO_In.GPIO_Mode = GPIO_Mode_AF;
  94.      GPIO_In.GPIO_PuPd = GPIO_PuPd_UP;
  95.      GPIO_In.GPIO_OType = GPIO_OType_PP;
  96.      GPIO_In.GPIO_Speed = GPIO_Speed_100MHz;
  97.      GPIO_Init(GPIOB, &GPIO_In);
  98.      
  99.      //Wlaczenie transmisji na podanych pinach
  100.      GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_USART1);
  101.      GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_USART1);
  102. }
  103. void USART_Send(volatile char *c)
  104. {
  105.      //Petla dziala do puki bedzie jakis znak do wyslania
  106.      while(*c)
  107.      {
  108.         //Sprawdza czy rejestr danych zostal oprózniony
  109.         while( !(USART1->SR & 0x00000040) );
  110.         //Przeslij dane,
  111.         USART_SendData(USART1, *c);
  112.         *c++;
  113.      }
  114. }
  115. //Funkcja wysylajaca dane do strumienia
  116. //Jej nazwy nie mozna zmieniac
  117. int fputc(int ch, FILE *f)
  118. {
  119.     volatile char c = ch;
  120.    
  121.       //Wyslanie danych
  122.         USART1->DR = (uint16_t)(& 0x01FF);
  123.         //Odczekanie az bufor zostanie oprozniony
  124.       while (!((USART1)->SR & USART_FLAG_TXE))
  125.         {}
  126.        
  127.     return ch;
  128. }
  129. void Send_Charc(volatile char c)
  130. {
  131.  while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
  132.  USART_SendData(USART1, c);
  133. }