STM32F4 USART

Masz problem z Arduino? Tutaj możesz szukać pomocy.
zsefb123
Młodszy majsterkowicz
Posty: 4
Rejestracja: 3 sty 2017, 10:45

STM32F4 USART

Postautor: zsefb123 » 3 sty 2017, 11:31

Dzień dobry. Posiadam płytkę STM32f411RE nucleo. Muszę zrobić komunikację mikrokontrolera z komputerem. Postanowiłem do tego użyć interfejsu USART oraz bibliotek HAL. Niestety pomimo wielu prób komunikacja nie chce zadziałać. Przeglądałem różne rozwiązania ale żadne nie rozwiązało mojego problemu. Poniżej załączam swój kod.

Kod: Zaznacz cały

#include "stm32f4xx.h"
#include "stm32f4xx_nucleo.h"
#include "stm32f4xx_hal_gpio.h"
#include "stm32f4xx_hal_usart.h"

void SystemClock_Config(void);
void Error_Handler(void);
void initUsart2(USART_HandleTypeDef* usart);
void initLed(GPIO_InitTypeDef* led);
static GPIO_InitTypeDef led1;
static USART_HandleTypeDef usart2;

size_t strlen(char const *s)
{
   size_t i;

   i= 0;
   while(s[i]) {
      i+= 1;
   }

   return i;
}

void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
  GPIO_InitTypeDef GPIO_InitStruct;
  if(huart->Instance==USART2)
  {
    __GPIOA_CLK_ENABLE();
    __USART2_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_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  }
}

int main(void)
{
    HAL_Init();

     /* Configure the system clock */
     //SystemClock_Config();
     __HAL_RCC_GPIOA_CLK_ENABLE();
     initLed(&led1);
     initUsart2(&usart2);

     char *msg = "Hello Nucleo Fun!\n\r";

     HAL_USART_Transmit(&usart2, (uint8_t*)msg, strlen(msg), 500);
     while(1){


        HAL_StatusTypeDef state = HAL_USART_Transmit(&usart2, (uint8_t*)msg, strlen(msg), 500);
        if(state == HAL_TIMEOUT){
           HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, 1);
           HAL_Delay(100);
           HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, 0);
           HAL_Delay(100);
        }
     }
}


void initUsart2(USART_HandleTypeDef* usart){

   __HAL_USART_ENABLE(usart);
   usart->Instance = USART2;
   usart->Init.BaudRate = 9600;
   usart->Init.WordLength = USART_WORDLENGTH_8B;
    usart->Init.StopBits = USART_STOPBITS_1;
    usart->Init.Parity = USART_PARITY_NONE;
    usart->Init.Mode = USART_MODE_TX_RX;
    HAL_USART_Init(usart);
 }
void initLed(GPIO_InitTypeDef* led){
   led->Pin = GPIO_PIN_5;
   led->Mode = GPIO_MODE_OUTPUT_PP;
   led->Pull = GPIO_NOPULL;
   led->Speed = GPIO_SPEED_FREQ_HIGH;
   HAL_GPIO_Init(GPIOA, led);
}


Bardzo bym prosił o jakiś prosty kod pozwalający na odbiór oraz wysyłanie danych i ewentualne wytłumaczenie błędów które popełniłem w swoim kodzie. Za pomoc z góry dziękuję.
Awatar użytkownika
Marhef
Złota rączka
Posty: 886
Rejestracja: 18 lis 2011, 02:18

Re: STM32F4 USART

Postautor: Marhef » 3 sty 2017, 11:40

A jak łączysz płytkę z komputerem?
zsefb123
Młodszy majsterkowicz
Posty: 4
Rejestracja: 3 sty 2017, 10:45

Re: STM32F4 USART

Postautor: zsefb123 » 3 sty 2017, 11:47

Płytka ma dołączony fabrycznie programator ST-LINK v2 no i z niego kabelkiem usb do koputera. Ogólnie to znalazłem błąd w tym kodzie na wysyłanie, funkcja zamiast funkcji HAL_USART_MspInit użułem jej odpowiednmika dla UART. no i jej nie wywołałem w main(). Ale i tak będę miał pytania do odbioru danych w przerwaniach.
Awatar użytkownika
Marhef
Złota rączka
Posty: 886
Rejestracja: 18 lis 2011, 02:18

Re: STM32F4 USART

Postautor: Marhef » 3 sty 2017, 12:36

Może się mylę, ale przecież ST-LINK nie ma UARTa. Do niego powinieneś mieć przejściówkę UART <=> USB
EDIT:
W opisie na stronie producenta też nie znalazłem informacji o tym, że ST-LINK posiada wbudowaną przejściówkę z UARTa
zsefb123
Młodszy majsterkowicz
Posty: 4
Rejestracja: 3 sty 2017, 10:45

Re: STM32F4 USART

Postautor: zsefb123 » 3 sty 2017, 12:57

Hmm, w zasadzie to akurat nie szukałem informacjo o tym, ale wysyłanie danych do komputera działa, sprawdzałem to w programie RealTerm oraz we własnej aplikacji napisanej w c#. W części programatora są piny Tx Rx jeśli to ważna informacja. Ogólnie teraz mam problem z odbiorem danych z komputera w przerwaniach.
Awatar użytkownika
Marhef
Złota rączka
Posty: 886
Rejestracja: 18 lis 2011, 02:18

Re: STM32F4 USART

Postautor: Marhef » 3 sty 2017, 13:06

Ooo, nauczyłem się czegoś nowego. Nie wiedziałem, że ST dodało możliwość komunikacji po UARcie. Przepraszam za zamieszanie. Wieczorem spróbuję zajrzeć do kodu, teraz nie mam takiej możliwości.
zsefb123
Młodszy majsterkowicz
Posty: 4
Rejestracja: 3 sty 2017, 10:45

Re: STM32F4 USART

Postautor: zsefb123 » 4 sty 2017, 11:49

Jak pisałem wcześniej przesyłanie danych do komputera za pomocą USATR2 działa bez problemów. Problem jest natomiast z odbiorem danych, nawet bez przerwań niestety. Poniżej zamieszczam poprawiony kod.

Kod: Zaznacz cały


#include "stm32f4xx.h"
#include "stm32f4xx_nucleo.h"
#include "stm32f4xx_hal_gpio.h"
#include "stm32f4xx_hal_usart.h"

void initUsart2(USART_HandleTypeDef* usart);
void initLed(GPIO_InitTypeDef* led);
static GPIO_InitTypeDef led1;
static USART_HandleTypeDef usart2;
static uint8_t receiveChar = 0;
size_t strlen(char const *s);
void delay(int time);


int main(void)
{
    HAL_Init();

     __HAL_RCC_GPIOA_CLK_ENABLE();
     HAL_USART_MspInit(&usart2);
     HAL_NVIC_EnableIRQ(USART2_IRQn);
     HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
     initLed(&led1);
     initUsart2(&usart2);
    __HAL_USART_ENABLE_IT(&usart2, USART_IT_RXNE);

     char *msg0 = "-50,56\n";
     char *msg1 = "-5,77777\n";
     char *msg3 = "hurra\n";
     char* array[2];
     array[0] = msg0;
     array[1] = msg1;

     int i = 0;
     while(1){

        HAL_USART_Transmit(&usart2, (uint8_t*)array[i], strlen(array[i]), 500);
        HAL_Delay(1000);
        if(receiveChar == 96){
           HAL_USART_Transmit(&usart2, (uint8_t*)msg3, strlen(msg3), 5000);
        }
     }
}

void delay(int time){
     while(time--)
        asm("nop");
}

size_t strlen(char const *s){
   size_t i=0;
   while(s[i])
      i+= 1;
   return i;
}

void HAL_USART_RxCpltCallback(USART_HandleTypeDef* usart){


   int i = 5;
   while(i--){
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, 1);
        delay(100000UL);
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, 0);
        delay(100000UL);
   }
}

void USART2_IRQHandler(void){

   //HAL_USART_IRQHandler(&usart2);
   //HAL_USART_RxCpltCallback(&usart2);
   int i = 5;
   while(i--){
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, 1);
        delay(100000UL);
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, 0);
        delay(100000UL);
   }
}

void HAL_USART_MspInit(USART_HandleTypeDef* huart)
{
  GPIO_InitTypeDef GPIO_InitStruct;
  if(huart->Instance==USART2)
  {
    __GPIOA_CLK_ENABLE();
    __USART2_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_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  }
}

void initUsart2(USART_HandleTypeDef* usart){

   usart->Instance = USART2;
   usart->Init.BaudRate = 9600;
   usart->Init.WordLength = USART_WORDLENGTH_8B;
    usart->Init.StopBits = USART_STOPBITS_1;
    usart->Init.Parity = USART_PARITY_NONE;
    usart->Init.Mode = USART_MODE_TX_RX;
    usart->RxXferSize = 240;
    HAL_USART_Init(usart);
 }
void initLed(GPIO_InitTypeDef* led){
   led->Pin = GPIO_PIN_5;
   led->Mode = GPIO_MODE_OUTPUT_PP;
   led->Pull = GPIO_NOPULL;
   led->Speed = GPIO_SPEED_FREQ_HIGH;
   HAL_GPIO_Init(GPIOA, led);
}



Ogólnie to jeśli tylko włączę przerwania za pomocą makra __HAL_USART_ENABLE_IT(&usart2, USART_IT_RXNE) i oczywiście włączę przerwanie w NVIC to wykonuje się ciągle handler USART2_IRQHandler(void), nawet main się nie wykonuje. Ma ktoś pomysł dlaczego tak się dzieje? Dodam jeszcze, że w środku handlera nie mogłem użyć HAL_Delay() bo była zwiecha, musiałem zrobić własne opóźnienie. Może priorytety są źle ustawione? Nie wiem kompletnie dlaczego to przerwanie cały czas się wykonuje jeśli nic nie wysyłam z komputera.

Wróć do „Jak to zrobić?”

Kto jest online

Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 2 gości