Moduł uart (usart) to jeden z kilku moich ulubionych tematów i co jakiś czas staram się coś poprawić i unowocześnić w kodach, które wam proponuję.
Przy okazji pracy z modułem uart warto mieć możliwość buforowania odebranych danych, a czasem tych wysyłanych również. temat wysyłki danych z pomocą programowego bufora cyklicznego jest dyskusyjny, bo przecież można wykorzystać do tego celu DMA, autoinkrementację adresu źródłowego oraz zapętlenie tegoż adresu (modulo). Tak czy siak programowy bufor może się przydać do przerzucania małej i średniej ilości danych. Można go wykorzystać do zbierania jakichś próbek, przechowywania wskaźników na obrazki (choć tu chyba lepsza jest zwykła tablica), czy czegokolwiek, co wam przyjdzie do głowy. Dzisiejszy przykład wykorzystania bufora cyklicznego oparłem o współpracę z modułem USART2 w mikrokontrolerze STM32L152RE. W programie zobaczycie zwyczajne uruchomienie uartu, konfigurację pinów oraz najprostszą z możliwych konfigurację przerwań od tego modułu.
Program wysyła ramkę powitalną, a następnie oczekuje na ramki pracując w nieblokującej pętli. Każdą odebraną ramkę odsyła z powrotem na terminal. Zarówno odbiór danych, jak i ich wysyłka odbywa się przy pomocy buforów cyklicznych (programowych). Opis użycia bufora znajduje się w pliku circularbuffer.c, ale stwierdziłem, że kompletny i działający przykład będzie najlepszą formą prezentacji. Gdyby jednak narodziły się jakieś pytania, to proszę śmiało pisać, odpowiem na wszystkie. Tutaj mamy inicjalizację uartu oraz przygotowanie callbacka:
Kod: Zaznacz cały
/*
* @file main.c
* @author Arkadiusz Pytlik
* @version V0.1a
* @date 18-Jun-2016
* @brief Simple circular buffer demo application.
*/
#include <stddef.h>
#include <stdbool.h>
#include "stm32l1xx.h"
#include "usart/usart.h"
/* My frame buffer */
BUFFER_TYPE UART_WorkBuffer[128];
/* This function will be called right after "event character" is received. */
void UART_Callback(BUFFER_TYPE *buf);
int main(void)
{
/* Set callback, buffer & "event character". */
UART_OnFrameReceived(UART_Callback, UART_WorkBuffer, '\n');
/* Initialize uart module. */
UART_Init(USART2, 9600);
/* Simple greeting text. */
UART_Puts(USART2, "Hello from STM32L152RE\r\n"
"Greetings for www.microgeek.eu\r\n");
while (true)
{
/* Task checks a flag indicating received frame.
* If any frame is received, frame is copied to the
* UART_WorkBuffer and UART_Callback is called */
UART_Task();
}
return 0;
}
/* This callback puts back unchanged frame received from USART2 */
void UART_Callback(BUFFER_TYPE *buf)
{
UART_Puts(USART2,(const char*) buf);
}
A tutaj mamy inicjalizację buforów cyklicznych. Początkowo może się wydawać nieco karkołomna, ale po chwili wszystko nabiera sensu:
Kod: Zaznacz cały
/*
* usart.c
*
* Created on: May 10, 2016
* Author: Arkadiusz Pytlik
*/
#include "stm32l1xx.h"
#include "usart.h"
/* Private circular buffers */
static BUFFER_TYPE rxBuffer[USART_USART2_RX_SIZE];
static BUFFER_TYPE txBuffer[USART_USART2_TX_SIZE];
/* Handlers for Rx & Tx buffers */
static BUFFER_HandleTypeDef hBufferRx =
{
.Init.pBuffer = rxBuffer,
.Init.Size = (sizeof(rxBuffer)/sizeof(BUFFER_TYPE))
};
static BUFFER_HandleTypeDef hBufferTx =
{
.Init.pBuffer = txBuffer,
.Init.Size = (sizeof(txBuffer)/sizeof(BUFFER_TYPE))
};
A tutaj obrazek pokazujący efekt działania programu:
Ach, bym zapomniał... Paczka z softem:
Pozdrawiam!