Szukaj…


Wprowadzenie

Ten temat dotyczy komunikacji szeregowej z wykorzystaniem urządzenia peryferyjnego Universal Asynchronous Receiver / Transmitter (UART) mikrokontrolerów STM32.

Aplikacja Echo - biblioteka HAL

W tym przykładzie mikrokontroler odsyła odebrane bajty do nadawcy za pomocą przerwania UART RX.

#include "stm32f4xx.h"

UART_HandleTypeDef huart2;

/* Single byte to store input */
uint8_t byte;

void SystemClock_Config(void);

/* UART2 Interrupt Service Routine */
void USART2_IRQHandler(void)
{
  HAL_UART_IRQHandler(&huart2);
}

/* This callback is called by the HAL_UART_IRQHandler when the given number of bytes are received */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  if (huart->Instance == USART2)
  {
    /* Transmit one byte with 100 ms timeout */
    HAL_UART_Transmit(&huart2, &byte, 1, 100);

    /* Receive one byte in interrupt mode */ 
    HAL_UART_Receive_IT(&huart2, &byte, 1);
  }
}

void uart_gpio_init()
{
  GPIO_InitTypeDef GPIO_InitStruct;

  __GPIOA_CLK_ENABLE();

  /**USART2 GPIO Configuration
  PA2     ------> USART2_TX
  PA3     ------> USART2_RX
  */
  GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_3;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
  GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

void uart_init()
{
  __USART2_CLK_ENABLE();

  huart2.Instance = USART2;
  huart2.Init.BaudRate = 115200;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  HAL_UART_Init(&huart2);

  /* Peripheral interrupt init*/
  HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(USART2_IRQn);
}

int main(void)
{
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
             
  uart_gpio_init();
  uart_init();

  HAL_UART_Receive_IT(&huart2, &byte, 1);

  while(1)
  {

  }
}

W tym przykładzie zastosowano wykrywanie STM32F4 (STM32F407VG), GPIO i wartości funkcji alternatywnych należy zmienić zgodnie z używanym mikrokontrolerem STM32.

Przesyłaj dużą ilość danych przy użyciu DMA i przerwań - biblioteka HAL

W tym przykładzie 2000 bajtów zostanie przesłanych przy użyciu DMA, przerwań Half Complete i Transmit Complete, aby osiągnąć najlepszą wydajność.

Pierwsza połowa bufora nadawczego jest ładowana przez CPU nowymi danymi w wywołaniu zwrotnym przerwania Transmit Half Complete, podczas gdy druga połowa bufora jest przesyłana przez DMA w tle.

Następnie w zakończeniu transmisji druga połowa bufora nadawczego jest ładowana przez nowe dane przez CPU, podczas gdy pierwsza połowa (poprzednio zaktualizowana) jest przesyłana przez DMA w tle.

#include "stm32f4xx.h"

uint8_t dma_buffer[2000];
volatile uint8_t toggle = 0;

UART_HandleTypeDef huart2;
DMA_HandleTypeDef hdma_usart2_tx;

void uart_gpio_init()
{
  GPIO_InitTypeDef GPIO_InitStruct;

  __GPIOA_CLK_ENABLE();

  /**USART2 GPIO Configuration
  PA2     ------> USART2_TX
  PA3     ------> USART2_RX
  */
  GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
  GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

void uart_dma_init()
{
  /* DMA controller clock enable */
  __DMA1_CLK_ENABLE();

  /* Peripheral DMA init*/
  hdma_usart2_tx.Instance = DMA1_Stream6;
  hdma_usart2_tx.Init.Channel = DMA_CHANNEL_4;
  hdma_usart2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
  hdma_usart2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
  hdma_usart2_tx.Init.MemInc = DMA_MINC_ENABLE;
  hdma_usart2_tx.Init.PeriphDataAlignment = DMA_MDATAALIGN_BYTE;
  hdma_usart2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
  hdma_usart2_tx.Init.Mode = DMA_NORMAL;
  hdma_usart2_tx.Init.Priority = DMA_PRIORITY_LOW;
  hdma_usart2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
  HAL_DMA_Init(&hdma_usart2_tx);

  __HAL_LINKDMA(&huart2,hdmatx,hdma_usart2_tx);

  /* DMA interrupt init */
  HAL_NVIC_SetPriority(DMA1_Stream6_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Stream6_IRQn);
}

void uart_init()
{
  __USART2_CLK_ENABLE();

  huart2.Instance = USART2;
  huart2.Init.BaudRate = 115200;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  HAL_UART_Init(&huart2);

  /* Peripheral interrupt init*/
  HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(USART2_IRQn);
}

/* This function handles DMA1 stream6 global interrupt. */
void DMA1_Stream6_IRQHandler(void)
{
  HAL_DMA_IRQHandler(&hdma_usart2_tx);
}

void USART2_IRQHandler(void)
{
  HAL_UART_IRQHandler(&huart2);
}

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
  uint16_t i;
  toggle = !toggle;

  for(i = 1000; i < 1998; i++)
  {
    if(toggle)
      dma_buffer[i] = '&';
    else
      dma_buffer[i] = 'z';
  }

  dma_buffer[1998] = '\r';
  dma_buffer[1999] = '\n';
}

void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart)
{
  uint16_t i;

  for(i = 0; i < 1000; i++)
  {
    if(toggle)
      dma_buffer[i] = 'y';
    else
      dma_buffer[i] = '|';
  }
}

int main(void)
{
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  uart_gpio_init();
  uart_dma_init();
  uart_init();

  uint16_t i;

  for(i = 0; i < 1998; i++)
  {
    dma_buffer[i] = 'x';
  }

  dma_buffer[1998] = '\r';
  dma_buffer[1999] = '\n';

  while(1)
  {
    HAL_UART_Transmit_DMA(&huart2, dma_buffer, 2000);
  }
}

Przykład został napisany dla płyty Discovery STM32F4 (STM32F407VG). Odpowiednią instancję DMA, kanał UART-DMA, GPIO i alternatywne ustawienia funkcji należy zmienić zgodnie z używanym mikrokontrolerem STM32.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow