STM32F04 UART-Übertragung mit Unterbrechungen

Ich habe mein Projekt mit dem STM32F103 „Bluepill“ prototypisiert und möchte für das Endprodukt auf den STM32F042F6 umsteigen, der einen kleineren TSSOP-20-Footprint hat. Ich muss UART in meiner Kommunikation mit dem Gerät verwenden, also habe ich versucht, ein einfaches UART-Sendeprogramm zu erstellen, um zu überprüfen, ob das UART-Peripheriegerät ordnungsgemäß funktioniert. Hier ist mein Code.

#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);
} 

Das UART-Peripheriegerät wird korrekt initialisiert, da der Error Handler erst aufgerufen wird, nachdem Startup_Sequence() abgeschlossen ist. Warum wird also der ErrorHandler aufgerufen, wenn ich versuche zu übertragen? Ich habe versucht, im Sperrmodus zu senden, aber es kommt jedes Mal zu einer Zeitüberschreitung.

EDIT: Ich habe den Fehler bis zur Initialisierungsfunktion verfolgt. Hier ist das GDB-Protokoll https://hastebin.com/xopohaniyu.coffeescript , aber ich kann nirgendwo finden, wo HAL_OK nicht zurückgegeben wird.

Stimmt etwas mit meiner Einrichtung des UART-Peripheriegeräts nicht? Oder gibt es ein Problem mit der Systemuhr? Bitte beraten.

Warum führen Sie in Ihrer Verzögerungsberechnung unnötigerweise Gleitkommaberechnungen durch? Teilen Sie einfach 1000 durch den ganzzahligen Divisor. Generell besteht ein Problem mit Ihrem Code darin, dass unklar ist, was aus einer Quelle kopiert wurde und was original ist. Wahrscheinlich sollten Sie versuchen, einen vorhandenen Code unverändert zum Laufen zu bringen , bevor Sie versuchen, Änderungen vorzunehmen, damit Sie eine bessere Vorstellung davon haben, wo spätere Probleme entstehen könnten. Stellen Sie außerdem sicher, dass Ihr Build ausschließlich für die STM32F0-Serie bestimmt ist und keine Dateien enthält, die zu der ziemlich anderen STM32F1-Serie gehören, die Sie zuvor verwendet haben.
Setzen Sie schließlich einen Haltepunkt für den Fehlerhandler und führen Sie dann einen Backtrace durch, um zu sehen, wie er dorthin gelangt ist - Ihr Debug-Protokoll enthält nicht den tatsächlichen Fehler, ist also nicht sehr nützlich.

Antworten (1)

Das GPIO-Setup ist beim F0 etwas komplizierter und flexibler. Hier sollten Sie auch setzen GPIO_InitStruct.Alternate = GPIO_AF1_USART1, da es sonst einen zufälligen Wert bekommt, da es sich um eine unitialisierte automatische Variable handelt. Aktivieren Sie die Warnungen im Compiler und achten Sie darauf, sie sind aus einem bestimmten Grund da.

HAL_UART_Transmit_IT()wird erneut aufgerufen, bevor die vorherige Übertragung beendet ist. Sie sollten warten, bis das UartReadyFlag gesetzt ist, und es vor dem Wiederholen zurücksetzen.