Skocz do zawartości

Zawieszająca się komunikacja USART


Pomocna odpowiedź

Napisano

Witam,

Uczę się programowania STM32 (dokładnie STM32F103VB) i napisałem kod do komunikacji USART mikrokontrolera z komputerem. Problemem jest jednak to, że po naciśnięciu przycisku SW_PIN1...SW_PIN4, nie zawsze otrzymuję wiadomość o wciśnięciu przycisku w terminalu. Tak jakby komunikacja działała z opóźnieniem/zawieszała się. Jak mogę poprawić kod, żeby otrzymywać wiadomość bez opóźnień?

#if F1
#include "stm32f1xx_hal.h"
#else
#error "Nie znaleziono biblioteki, którą można by załączyć dla tej rodziny STM32."
#endif

#define LED_PIN1    GPIO_PIN_15
#define LED_PIN2    GPIO_PIN_14                          
#define LED_PIN3    GPIO_PIN_13 
#define LED_PIN4    GPIO_PIN_12
#define LED_PIN5    GPIO_PIN_11 
#define LED_PIN6    GPIO_PIN_10 
#define LED_PIN7    GPIO_PIN_9 
#define LED_PIN8    GPIO_PIN_8  
#define SW_PIN1   GPIO_PIN_3     
#define SW_PIN2   GPIO_PIN_2
#define SW_PIN3   GPIO_PIN_1
#define SW_PIN4   GPIO_PIN_0

#define LED_GPIO_PORT   GPIOB
#define SW_GPIO_PORT    GPIOA
#define LED_GPIO_CLK_ENABLE()   __HAL_RCC_GPIOB_CLK_ENABLE()
#define SW_GPIO_CLK_ENABLE()    __HAL_RCC_GPIOA_CLK_ENABLE()

typedef enum {TRUE = 1, FALSE = 0} bool;

//static void SystemClock_Config(void);

UART_HandleTypeDef huart1;

char TxBuf[15] = {'o','n','L','E','D',':',',',' '};

int main(void) {
  HAL_Init();
  //SystemClock_Config();
  LED_GPIO_CLK_ENABLE(); // podpiecie zegara portu GPIOB
  SW_GPIO_CLK_ENABLE(); // podpiecie zegara portu GPIOA
  RCC_Conf_Copilot();
  GPIO_Conf_Copilot();
  USART_Conf_Copilot();

  const char msg[] = "Hello World!\r\n";
  const char msg_button_1[] = "Przycisk 1";
  const char msg_button_2[] = "Przycisk 2";
  const char msg_button_3[] = "Przycisk 3";
  const char msg_button_4[] = "Przycisk 4";
  uint8_t button_counter = 0;  

  HAL_Delay(100);

  while (1)
  {
        if(HAL_GPIO_ReadPin(SW_GPIO_PORT, SW_PIN1)) {
          HAL_GPIO_WritePin(LED_GPIO_PORT, LED_PIN1, GPIO_PIN_RESET);
        }
        else {
          HAL_GPIO_WritePin(LED_GPIO_PORT, LED_PIN1, GPIO_PIN_SET);
          button_counter++;
          HAL_UART_Transmit(&huart1, (uint8_t*)msg_button_1, strlen(msg), HAL_MAX_DELAY);            
          HAL_UART_Transmit(&huart1, &button_counter, 1, HAL_MAX_DELAY);
        }

        if(HAL_GPIO_ReadPin(SW_GPIO_PORT, SW_PIN2)) {
          HAL_GPIO_WritePin(LED_GPIO_PORT, LED_PIN2, GPIO_PIN_RESET);
        }
        else {
          HAL_GPIO_WritePin(LED_GPIO_PORT, LED_PIN2, GPIO_PIN_SET);
          button_counter++;
          HAL_UART_Transmit(&huart1, (uint8_t*)msg_button_2, strlen(msg), HAL_MAX_DELAY);            
          HAL_UART_Transmit(&huart1, &button_counter, 1, HAL_MAX_DELAY);
        }

        if(HAL_GPIO_ReadPin(SW_GPIO_PORT, SW_PIN3)) {
          HAL_GPIO_WritePin(LED_GPIO_PORT, LED_PIN3, GPIO_PIN_RESET);
        }
        else {
          HAL_GPIO_WritePin(LED_GPIO_PORT, LED_PIN3, GPIO_PIN_SET);
          button_counter++;
          HAL_UART_Transmit(&huart1, (uint8_t*)msg_button_3, strlen(msg), HAL_MAX_DELAY);            
          HAL_UART_Transmit(&huart1, &button_counter, 1, HAL_MAX_DELAY);
        }

        if(HAL_GPIO_ReadPin(SW_GPIO_PORT, SW_PIN4)) {
          HAL_GPIO_WritePin(LED_GPIO_PORT, LED_PIN4, GPIO_PIN_RESET);
        }
        else {
          HAL_GPIO_WritePin(LED_GPIO_PORT, LED_PIN4, GPIO_PIN_SET);
          button_counter++;
          HAL_UART_Transmit(&huart1, (uint8_t*)msg_button_4, strlen(msg), HAL_MAX_DELAY);            
          HAL_UART_Transmit(&huart1, &button_counter, 1, HAL_MAX_DELAY);
        } 
  }

}

void SysTick_Handler(void)
{
  HAL_IncTick();
}

void NMI_Handler(void)
{
}

void HardFault_Handler(void)
{
  while (1) {}
}


void MemManage_Handler(void)
{
  while (1) {}
}

void BusFault_Handler(void)
{
  while (1) {}
}

void UsageFault_Handler(void)
{
  while (1) {}
}

void SVC_Handler(void)
{
}


void DebugMon_Handler(void)
{
}

void PendSV_Handler(void)
{
}
// funkcja konfiguracji GPIO (tak żeby uzyskać lepszą czytelność kodu)
void GPIO_Conf_Copilot(void) {
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  GPIO_InitStruct.Pin = GPIO_PIN_9;  // TX
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

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

    // konfiguracja diod LED (GPIOB 8...11)
    GPIO_InitStruct.Pin = LED_PIN1 | LED_PIN2 | LED_PIN3 | LED_PIN4;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // push-pull
    //GPIO_InitStructure.Pull = GPIO_PULLUP; // czy potrzebne? w książce nie ma
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(LED_GPIO_PORT, &GPIO_InitStruct); // przesłanie adresu GPIO oraz zbioru parametrów
    
    // ustawienie stanu 0 na pinach przynależnych diodom
    HAL_GPIO_WritePin(GPIOB, LED_PIN1 | LED_PIN2 | LED_PIN3 | LED_PIN4, GPIO_PIN_RESET);

    //konfiguracja nieużywanych diod tak żeby nie świeciły same z siebie
    GPIO_InitStruct.Pin = LED_PIN5 | LED_PIN6 | LED_PIN7 | LED_PIN8;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // push-pull
    GPIO_InitStruct.Pull = GPIO_PULLUP; // czy potrzebne? w książce nie ma
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(LED_GPIO_PORT, &GPIO_InitStruct);

    // konfiguracja przycisków (GPIOA 3...0)
    GPIO_InitStruct.Pin = SW_PIN1 | SW_PIN2 | SW_PIN3 | SW_PIN4;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; // zmiana LOW/HIGH nie powoduje widocznych opóźnień - sprawdzić czy zmieni się zużycie energii
    HAL_GPIO_Init(SW_GPIO_PORT, &GPIO_InitStruct);
}
// funkcja konfiuguracji kontrolera NVIC (tak żeby uzyskać lepszą czytelność kodu)
void NVIC_Conf(void) {

}
// funkcja konfiuguracji RCC (tak żeby uzyskać lepszą czytelność kodu)
void RCC_Conf_Copilot(void) {
__HAL_RCC_USART1_CLK_ENABLE();  // Włączenie zegara dla USART1
__HAL_RCC_GPIOB_CLK_ENABLE();  // Włącza zegar dla portu GPIOA, gdzie są piny TX i RX

}
void USART_Conf_Copilot(void) {
      // Konfiguracja USART1
    huart1.Instance = USART1;
    huart1.Init.BaudRate = 9600;
    huart1.Init.WordLength = UART_WORDLENGTH_8B;
    huart1.Init.StopBits = UART_STOPBITS_1;
    huart1.Init.Parity = UART_PARITY_NONE;
    huart1.Init.Mode = UART_MODE_TX_RX;
    huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    huart1.Init.OverSampling = UART_OVERSAMPLING_16;

    HAL_UART_Init(&huart1);
}
// funkcja konfiuguracji USART (tak żeby uzyskać lepszą czytelność kodu)
void USART_Conf(void) {
  // Konfiguracja USART
  USART_InitTypeDef USART_InitStruct;
  USART_InitStruct.BaudRate = 9600;
  USART_InitStruct.WordLength = USART_WORDLENGTH_8B;
  USART_InitStruct.StopBits = USART_STOPBITS_1;
  USART_InitStruct.Parity = USART_PARITY_NONE;
  USART_InitStruct.Mode = USART_MODE_TX_RX;

  HAL_USART_Init(&USART_InitStruct);

  //HAL_USART_Receive_IT() - służy do włączenia przerwań do odebrania danych poprzez USART
}
// funkcja konfigruacji UART (tak żeby uzyskać lepszą czytelność kodu)
void UART_conf(void) {
  UART_InitTypeDef UART_InitStruct;
  UART_InitStruct.BaudRate = 9600;
  UART_InitStruct.WordLength = UART_WORDLENGTH_8B;
  UART_InitStruct.StopBits = UART_STOPBITS_1;
  UART_InitStruct.Parity = UART_PARITY_NONE;
  UART_InitStruct.Mode = UART_MODE_TX_RX;
  UART_InitStruct.HwFlowCtl = UART_HWCONTROL_NONE; // tylko UART_InitTypeDef pozwala na Flow Control
}

Z góry dzięki za wszelkie odpowiedzi.

 

Jedna z metod postępowania, to zawężanie problemu przez maksymalne upraszczanie i eliminowanie rzeczy nieistotnych.

Jeżeli pozbędziesz się z pętli while() wszystkiego oprócz wysyłania napisu do odbiornika (komputer), to wtedy... działa? Na początek można też wprowadzić w pętli while() dodatkowe sztuczne opóźnienie, żeby móc na bieżąco obserwować, co się dzieje po stronie odbornika.
Do czego służy Ci wysyłanie pomiędzy napisami wartości binarnej button_counter? Konsola terminalu na komputerze, w zależności od ustawień, może od tego czasem "głupieć".
Używałeś już debugger-a?

 

Przy zapisie jak poniżej otrzymuję w terminalu kolejne wartości zmiennej jednak czasami wypisywane są jedna po drugiej bez opóźnienia np. 1, <sekunda opóźnienia>, 2 <sekudna opóźnienia>, 3, 4, <sekudna opóźnienia>, 5 itd.
 

  while (1)
  {

          button_counter++;
          HAL_Delay(1000);
          char buffer[10];
          sprintf(buffer, "%d\n", button_counter);
          HAL_UART_Transmit(&huart1, (uint8_t*)buffer, strlen(buffer), HAL_MAX_DELAY);

  }

Mam programator-debugger ZL30PRGv2-1 (SWD) jednak dopiero uczę się jak debugować program przy jego pomocy.

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...