STM32F04 UART Transmitir con interrupciones

1

He estado creando un prototipo de mi proyecto con el STM32F103 "Bluepill" y, para el producto final, quiero pasar al STM32F042F6 que tiene una huella TSSOP-20 más pequeña. Necesito usar UART en mis comunicaciones con el dispositivo, así que intenté crear un programa de transmisión UART simple para verificar que el periférico UART funcionaba correctamente. Aquí está mi código.

#include "stm32f0xx.h"
#include "stm32f0xx_hal.h"
#include "stm32f0xx_hal_conf.h"

void Startup_Sequence(void);
void Error_Handler(void);
void SystemClock_Config(void);
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *UartHandle);
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle);

UART_HandleTypeDef UartHandle;
__IO ITStatus UartReady = RESET;

int main(void)
{
    HAL_Init();
    //SystemInit();
    SystemClock_Config();

    GPIO_InitTypeDef  GPIO_InitStruct;
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_USART1_CLK_ENABLE();

   // Setup LED Pin
   GPIO_InitStruct.Pin = GPIO_PIN_4;
   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; 
   GPIO_InitStruct.Pull = GPIO_NOPULL;
   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

   // Setup UART Tx Pin
  GPIO_InitStruct.Pin = GPIO_PIN_9;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  // Setup UART Rx pin
  GPIO_InitStruct.Pin = GPIO_PIN_10;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  //Setup UART Instance
  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;
  UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;
  UartHandle.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  UartHandle.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;

  //Error handling
  if(HAL_UART_Init(&UartHandle) != HAL_OK) {
      Error_Handler();
  }

  Startup_Sequence();

  HAL_NVIC_SetPriority(USART1_IRQn, 0, 1);
  HAL_NVIC_EnableIRQ(USART1_IRQn);  

  char hello[6] = "hello\n";

  while(1) {
      if(HAL_UART_Transmit_IT(&UartHandle, (uint8_t *)hello, 6) != HAL_OK) {
          Error_Handler();
      }     
  }
}

void Startup_Sequence(void) {
    int i;
    for (i=1; i<50;i++) {
        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_4);
        HAL_Delay((1.0/i) * 1000);
    }
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
}

void Error_Handler(void) {
    while(1) {
        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_4);
        HAL_Delay(1000);
    }
}

/**
  * Associates the interrupt handler with the UartHandle
 */
void USART1_IRQHandler(void) {
    HAL_UART_IRQHandler(&UartHandle);
}

/**
 * This function is called when transmitting
 * @param UartHandle [Pointer to UartHandle]
 */
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *UartHandle) {
    UartReady = SET;
}

/**
 * This function is called when receiving
 * @param UartHandle [Pointer to UartHandle]
 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle) {
    UartReady = SET;
}

void SystemClock_Config(void) {
    RCC_OscInitTypeDef RCC_OscInitStruct;
    RCC_ClkInitTypeDef RCC_ClkInitStruct;
    RCC_PeriphCLKInitTypeDef PeriphClkInit;

    /**Initializes the CPU, AHB and APB busses clocks 
    */
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48;
    RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    {
        Error_Handler();
    }

    /**Initializes the CPU, AHB and APB busses clocks 
    */
    RCC_ClkInitStruct.ClockType = 
    RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                           |RCC_CLOCKTYPE_PCLK1;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI48;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != 
    HAL_OK)
    {
        Error_Handler();
    }

    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;
    PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK1;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
    {
        Error_Handler();
    }

    /**Configure the Systick interrupt time 
    */
    HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

    /**Configure the Systick 
    */
    HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

    /* SysTick_IRQn interrupt configuration */
    HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
} 

El periférico UART se inicializa correctamente, porque no se llama al controlador de errores hasta después de que se haya completado la Startup_Sequence (). Entonces, ¿por qué se llama ErrorHandler cuando intento transmitir? He intentado enviar utilizando el modo de bloqueo, pero solo se agota el tiempo de espera cada vez.

EDITAR: He rastreado el error hasta la función de inicialización. Aquí está el Registro de GDB enlace pero no puedo encontrar ningún lugar donde no se devuelva HAL_OK.

¿Hay algún problema con mi configuración del periférico UART? ¿O hay un problema con el reloj del sistema? Por favor avise.

    
pregunta Tom Eaton

1 respuesta

3

La configuración de GPIO es algo más complicada flexible en la F0. Aquí también debe configurar GPIO_InitStruct.Alternate = GPIO_AF1_USART1 , de lo contrario obtendrá un valor aleatorio, ya que es una unidad unificada. variable automatica Habilite las advertencias en el compilador, y preste atención a ellas, están ahí por una razón.

Se vuelve a llamar a HAL_UART_Transmit_IT() antes de que finalice la transmisión anterior. Debes esperar hasta que se establezca la marca UartReady y restablecerla antes de repetir.

    
respondido por el berendi

Lea otras preguntas en las etiquetas