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.
- #include "stm32f4xx.h"
- #include "stm32f4xx_gpio.h"
- #include "stm32f4xx_rcc.h"
- #include "stm32f4xx_usart.h"
- #include "misc.h"
- void SendChar(char);
- void USART_Initialize(void);
- void GPIO_Initialize(void);
- void USART_Send(volatile char *s);
- int main(void)
- {
- //Inicjalizacja pinów
- GPIO_Initialize();
- //Inicjalizacja USARTU
- USART_Initialize();
- //Wyslanie danych
- USART_Send("1234");
- SendChar('1');
- while (1)
- {
- }
- }
- void USART_Initialize(void)
- {
- //Inicjalizacja kontrolera przerwan
- NVIC_InitTypeDef NVIC_InitStruct;
- //konfiguracja ukladu USART
- USART_InitTypeDef USART_InitStructure;
- //Ustawienie kanalu IRQ
- NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
- //Wlaczenie zegara dla USART1
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
- //Ustawienie predkosci transmisji 9600bps
- USART_InitStructure.USART_BaudRate = 9600;
- //Dlugosc wysylanego slowa
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;
- //Ustawienie jednego bitu stopu
- USART_InitStructure.USART_StopBits = USART_StopBits_1;
- //Kontrola parzystosci wylaczona
- USART_InitStructure.USART_Parity = USART_Parity_No;
- //Wylaczenie kontroli przeplywu danych
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
- //Tryb pracy linii odpowiednio odbior i nadawanie
- USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
- //Konfiguracja ukladu
- USART_Init(USART1, &USART_InitStructure);
- //Wlaczenie USART1
- USART_Cmd(USART1, ENABLE);
- //Wlaczenie przerwania na RX1
- USART1->CR1 |= USART_CR1_RXNEIE;
- //Wprowadzenie ustawien do przerwan
- NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
- NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
- NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
- NVIC_Init(&NVIC_InitStruct);
- }
- void GPIO_Initialize(void)
- {
- //konfigurowanie portow GPIO
- GPIO_InitTypeDef GPIO_In;
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
- //TX dla pinu PB6
- GPIO_In.GPIO_Pin = GPIO_Pin_6;
- GPIO_In.GPIO_PuPd = GPIO_PuPd_UP;
- GPIO_In.GPIO_OType = GPIO_OType_PP;
- GPIO_In.GPIO_Mode = GPIO_Mode_AF;
- GPIO_In.GPIO_Speed = GPIO_Speed_100MHz;
- GPIO_Init(GPIOB, &GPIO_In);
- //RX dla pinu PB7
- GPIO_In.GPIO_Pin = GPIO_Pin_7;
- GPIO_In.GPIO_Mode = GPIO_Mode_AF;
- GPIO_In.GPIO_PuPd = GPIO_PuPd_UP;
- GPIO_In.GPIO_OType = GPIO_OType_PP;
- GPIO_In.GPIO_Speed = GPIO_Speed_100MHz;
- GPIO_Init(GPIOB, &GPIO_In);
- //Wlaczenie transmisji na podanych pinach
- GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_USART1);
- GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_USART1);
- }
- void USART_Send(volatile char *c)
- {
- //Petla dziala do puki bedzie jakis znak do wyslania
- while(*c)
- {
- //Sprawdza czy rejestr danych zostal oprózniony
- while( !(USART1->SR & 0x00000040) );
- //Przeslij dane,
- USART_SendData(USART1, *c);
- *c++;
- }
- }
- void SendChar(char c)
- {
- //Sprawdza czy bufor nadawczy jest pusty
- while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
- USART_SendData(USART1, c);
- }
Drugi program będzie zawierał przykład, który będzie odbierał dane z komputera.
- //Program wykorzystujacy funckje printf
- #include "stm32f4xx.h"
- #include "stm32f4xx_gpio.h"
- #include "stm32f4xx_rcc.h"
- #include "stm32f4xx_usart.h"
- #include "stdio.h"
- #include "misc.h"
- //struktura FILE zawierajca jeden parametr
- struct __FILE {
- int parametr;
- };
- //Stworzenie zmiennej z struktury FILE
- //Parametr musi miec taka nazwe
- FILE __stdout;
- void send_char(char);
- void USART_Initialize(void);
- void GPIO_Initialize(void);
- void USART_Send(volatile char *s);
- int PutFile(int ch, FILE *f);
- void Send_Charc(volatile char c);
- int main(void)
- {
- float Wartosc2 = 1.85456;
- //Inicjalizacja pinów
- GPIO_Initialize();
- //Inicjalizacja USARTU
- USART_Initialize();
- //Wyslanie danych
- USART_Send("\n1234 \n");
- printf("\nFunkcja printf \r\n");
- printf("Zmiennoprzecinkowa - %.3f \r\n", Wartosc2);
- while (1)
- {
- }
- }
- void USART_Initialize(void)
- {
- //Inicjalizacja kontrolera przerwan
- NVIC_InitTypeDef NVIC_InitStruct;
- //konfiguracja ukladu USART
- USART_InitTypeDef USART_InitStructure;
- //Ustawienie kanalu IRQ
- NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
- //Wlaczenie zegara dla USART1
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
- //Ustawienie predkosci transmisji 9600bps
- USART_InitStructure.USART_BaudRate = 9600;
- //Dlugosc wysylanego slowa
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;
- //Ustawienie jednego bitu stopu
- USART_InitStructure.USART_StopBits = USART_StopBits_1;
- //Kontrola parzystosci wylaczona
- USART_InitStructure.USART_Parity = USART_Parity_No;
- //Wylaczenie kontroli przeplywu danych
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
- //Tryb pracy linii odpowiednio odbior i nadawanie
- USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
- //Konfiguracja ukladu
- USART_Init(USART1, &USART_InitStructure);
- //Wlaczenie USART1
- USART_Cmd(USART1, ENABLE);
- //Wlaczenie przerwania na RX1
- USART1->CR1 |= USART_CR1_RXNEIE;
- //Wprowadzenie ustawien do przerwan
- NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
- NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
- NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
- NVIC_Init(&NVIC_InitStruct);
- }
- void GPIO_Initialize(void)
- {
- //konfigurowanie portow GPIO
- GPIO_InitTypeDef GPIO_In;
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
- //TX dla pinu PB6
- GPIO_In.GPIO_Pin = GPIO_Pin_6;
- GPIO_In.GPIO_PuPd = GPIO_PuPd_UP;
- GPIO_In.GPIO_OType = GPIO_OType_PP;
- GPIO_In.GPIO_Mode = GPIO_Mode_AF;
- GPIO_In.GPIO_Speed = GPIO_Speed_100MHz;
- GPIO_Init(GPIOB, &GPIO_In);
- //RX dla pinu PB7
- GPIO_In.GPIO_Pin = GPIO_Pin_7;
- GPIO_In.GPIO_Mode = GPIO_Mode_AF;
- GPIO_In.GPIO_PuPd = GPIO_PuPd_UP;
- GPIO_In.GPIO_OType = GPIO_OType_PP;
- GPIO_In.GPIO_Speed = GPIO_Speed_100MHz;
- GPIO_Init(GPIOB, &GPIO_In);
- //Wlaczenie transmisji na podanych pinach
- GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_USART1);
- GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_USART1);
- }
- void USART_Send(volatile char *c)
- {
- //Petla dziala do puki bedzie jakis znak do wyslania
- while(*c)
- {
- //Sprawdza czy rejestr danych zostal oprózniony
- while( !(USART1->SR & 0x00000040) );
- //Przeslij dane,
- USART_SendData(USART1, *c);
- *c++;
- }
- }
- //Funkcja wysylajaca dane do strumienia
- //Jej nazwy nie mozna zmieniac
- int fputc(int ch, FILE *f)
- {
- volatile char c = ch;
- //Wyslanie danych
- USART1->DR = (uint16_t)(c & 0x01FF);
- //Odczekanie az bufor zostanie oprozniony
- while (!((USART1)->SR & USART_FLAG_TXE))
- {}
- return ch;
- }
- void Send_Charc(volatile char c)
- {
- while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
- USART_SendData(USART1, c);
- }