STM32F1xx HAL UART Recibir

Estoy tratando de enviar y recibir datos hacia y desde un STM32F1xx. Tengo el STM32 para enviar correctamente los datos a la computadora. Lo hice usando el siguiente código.

__HAL_RCC_USART1_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

//Setup UART RX Pin
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

UartHandle.Instance = USART1;
UartHandle.Init.BaudRate = 9600;
UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
UartHandle.Init.StopBits = UART_STOPBITS_1;
UartHandle.Init.Parity = UART_PARITY_NONE;
UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
UartHandle.Init.Mode = UART_MODE_TX_RX;

//Error handling
if(HAL_UART_DeInit(&UartHandle) != HAL_OK) {
    Error_Handler();
}
if(HAL_UART_Init(&UartHandle) != HAL_OK) {
    Error_Handler();
}
char msg[] = "testing\n\r";
while(1) {
  HAL_UART_Transmit(&UartHandle, (uint8_t*)msg, sizeof(msg), 10);
}

El código anterior funciona perfectamente. Luego traté de enviar datos desde la computadora al STM32. Probé el siguiente código

 if(HAL_UART_Receive_IT(&UartHandle, (uint8_t*)msg, 5) == HAL_OK) {
          char msg[] = "HAL_OK";
          HAL_UART_Transmit(&UartHandle, (uint8_t*)msg, sizeof(msg), 10);
 } 

y no funcionó. No se enviaron datos a la computadora cuando envié un byte al STM32. Hice un poco de depuración y la función de recepción devuelve HAL_OK una vez al principio, y luego de eso devuelve HAL_BUSY. Esto me hace pensar que tienes que usar interrupciones, pero las estoy usando con Receive_IT. ¿Cómo soluciono este problema?

Ciertamente no tienes que usar interrupciones. ¿Dónde estás poniendo esa declaración if? ¿En el while (1) reemplazando la instrucción de transmisión original? Mi consejo sería deshacerse del horrible HAL y escribir su código desde cero. Aprenderá mucho más sobre el micro de esa manera y terminará con un código más pequeño, más rápido y más ordenado.
@DiBosco La declaración if está en el while(1)ciclo reemplazando la declaración de transmisión.
Solo busque cuánto código termina usando la llamada HAL. Compare con el pseudocódigo de: if ((USART1->SR & DATA_RX_BIT) == DATA_RX_BIT) { Leer registro y procesar datos} Luego piense cuánto aprende sobre el procesador y su periférico haciéndolo de esa manera.
En mi opinión, la velocidad de desarrollo supera el tamaño de la biblioteca.
¿Cómo te va esa velocidad ahora? Incluso si estaba ayudando. eso es solo cortoplacismo en mi opinión. A la larga, será un ingeniero de desarrollo mucho mejor aprendiendo cómo funciona un sistema y creará un código mejor y más rápido.
Eso es lo que es, esto es para un prototipo rápido.
El _ITsufijo significa que HAL_UART_Receive_IT()se supone que debe usarse en modo de interrupción. Pero no estás tratando de usar el modo de interrupción. Tal vez deberías usar HAL_UART_Receive()en su lugar.
@DiBosco por mucho que odio a HAL, debo admitir que nos ahorró literalmente meses de desarrollo cuando tuvimos que ejecutar el mismo código en más de 10 MCU diferentes. Además, cuando no usamos HAL, seguimos escribiendo nuestras propias clases abstrayendo el hardware tanto como sea posible. Cuando la E/S es solo una pequeña parte del todo, primero se debe aplicar un "código mejor y más rápido" a la lógica empresarial.

Respuestas (2)

No lo veo habilitando la interrupción UART o llamando a los controladores IRQ apropiados y eso podría ser un problema.

Aquí hay un ejemplo completo de una aplicación UART Echo hecha con HAL que escribí para el tema de documentación SO STM32. Como la documentación de SO se cerrará, he citado el ejemplo completo. Fue escrito para un STM32F4 pero con HAL es casi lo mismo para un STM32F1.

Aplicación Echo - Biblioteca HAL

En este ejemplo, el microcontrolador devuelve los bytes recibidos al remitente mediante la interrupción 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)
  {

  }
}

Este ejemplo usó un STM32F4 Discovery (STM32F407VG), GPIO y los valores de funciones alternativas deben cambiarse de acuerdo con el microcontrolador STM32 en uso.

No debería necesitar usar interrupciones, la agrupación es un método válido para la comunicación UART. Mirando su código, la configuración de GPIO parece estar apagada. El pin Tx está configurado como función alternativa pero no definió la función.

Al mirar la respuesta de @Bence, puede ver que los pines usan af 7 para las funciones USART. Sugeriría agregar la siguiente línea antes de llamar al primer HAL_GPIO_Init:

GPIO_InitStruct.Alternate = GPIO_AFx_USART1;

Y cambie GPIO_InitStruct.MODE para el pin Rx a lo siguiente:

GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Alternate = GPIO_AFx_USART1;

Tendrá que reemplazar "AFx" con la función alternativa adecuada para que esos pines funcionen con USART1. Puede encontrar esa información en la hoja de datos de MCU. Por lo general, en una mesa después de la descripción del pin.

Cuando se utilizan pines conectados a un periférico en lugar de una E/S simple, debe realizar un mux adecuado del físico. Lea un poco sobre la muxización de pines del microcontrolador.