W tym poście pokaże jak obsłużyć układ USART z konwerterem wbudowanym w płytkę Nucleo
Wstęp
Wbudowany konwerter USART podłączony jest do USART2, który jest podłączony do pinów PA2 oraz PA3.
Układ wbudowany jest w płytkę, dzięki temu po podłączeniu do komputera i odpowiednim zaprogramowaniu można od razu z niego korzystać. Nie ma potrzeby stosowania dodatkowych elementów.
Program 1
Programowanie przebiega w standardowy sposób, przedstawiony we wcześniejszych postach. Dlatego teraz od razu wklejam program. W nim zawarte są komentarze pozwalające na efektywne zrozumienie całego kodu.
#include "stm32f4xx.h" #include "stm32f4xx_gpio.h" #include "stm32f4xx_rcc.h" #include "stm32f4xx_usart.h" #include "misc.h" void USART_Initialize(void); void GPIO_Initialize(void); void USART_Send(volatile char *s); int main(void) { GPIO_Initialize(); USART_Initialize(); USART_Send("Dziala\r\n"); while (1) {} } void USART_Initialize(void) { //konfiguracja układu USART USART_InitTypeDef USART_InitStructure; //Włączenie zegara dla USART2 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); //Ustawienie prędkości transmisji 9600bps USART_InitStructure.USART_BaudRate = 9600; //Długosc wysylanego slowa USART_InitStructure.USART_WordLength = USART_WordLength_8b; //Ustawienie jednego bitu stopu USART_InitStructure.USART_StopBits = USART_StopBits_1; //Kontrola parzystości wyłączona USART_InitStructure.USART_Parity = USART_Parity_No; //Wylaczenie kontroli przepływu 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 układu USART_Init(USART2, &USART_InitStructure); //Włączenie USART2 USART_Cmd(USART2, ENABLE); } void GPIO_Initialize(void) { //konfigurowanie portow GPIO GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //TX dla pinu PA2 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); //RX dla pinu PA3 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); //Włączenie transmisji na podanych pinach GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART1); GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART1); } void USART_Send(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( !(USART2->SR & 0x00000040) ); //Prześlij dane, USART_SendData(USART2, *c); *c++; } }
Program 2
W przypadku kiedy chcemy przesłać informacje inne niż string dobrze jest zintegrować z funkcją printf. Zwiększa ono niestety wielkość programu, pozwala także na łatwiejszą edycję tekstu.
Żeby umożliwić wykorzystywanie funkcji printf należy dołączyć odpowiednie funckje edycji tekstu.
int __io_putchar(int c) { send_char(c); return c; } void send_char(char c) { while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET); USART_SendData(USART2, c); }
Pozostała część programu pozostaje bez zmian. Natomiast funkcja main() prezentuje się następująco:
int main(void) { int Wartosc1 = 1; float Wartosc2 = 54.8725; GPIO_Initialize(); USART_Initialize(); USART_Send("Dziala\r\n"); //Przykładowe dane liczbowe printf("Calkowita - %d\r\n", Wartosc1); printf("Zmiennoprzecinkowa - %.3f\r\n", Wartosc2); while (1) {} }
Wynik działania programu przedstawiłem na rysunku 1.1.
Rys. 1.1. Wynik działania programu