Микроконтролери и електроника
http://mcu-bg.com/mcu_site/

Проблем с Uart Interrupt STM32
http://mcu-bg.com/mcu_site/viewtopic.php?f=3&t=19159
Страница 1 от 1

Автор:  bborisov567 [ Сря Апр 24, 2024 9:44 pm ]
Заглавие:  Проблем с Uart Interrupt STM32

Здравейте, контролерът е STM32F103C8T6. Кодът е реализиран по следния начин:
Код:

while (1)
  {
   ...
           HAL_UART_Receive_IT(&huart1,buffer, 1);
   ...
  }



и callback преди main() функцията

Код:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{

   if(huart->Instance == huart1.Instance)
      {
      tx_counter++;
      HAL_UART_Receive_IT(&huart1,&buffer[tx_counter],1);
      if (strstr(buffer, "\r\n") != 0) {
         tx_counter=0;
         strcpy(Rx_data, buffer);
         buffer[0]=0;
      }
      }
}




Идеята е да приемам по един байт с всяко прекъсване и при достигане на края на съобщението ( наличието на \r\n ), да копирам буфера в Rx_data и да чакам за полуването на ново съобщение. Проблемът е, че работи само веднъж. Първият път след ресет всичко минава както трябва, но след това като изпращам не се получава нищо от контролерът.

Автор:  stefan63 [ Сря Апр 24, 2024 9:59 pm ]
Заглавие:  Re: Проблем с Uart Interrupt STM32

Предполагам - калбак функцията се вика от прекъсване на уарта по приет байт. И функцията HAL_UART_Receive_IT е сложена в калбак от StmCube?
Не виждам смисъл от нея в main().

Автор:  bborisov567 [ Сря Апр 24, 2024 10:05 pm ]
Заглавие:  Re: Проблем с Uart Interrupt STM32

Код:
HAL_UART_Receive_IT(&huart1,&buffer[tx_counter],1);
e в callback-a, за да мога да продължа да приемам байтове. Сложена е от мен. Ако не стартирам отново приемането след като съм влязъл в callback-a, ще приема само един байт. За да не стане объркване аз приемам едно съощбение в мoмента (напр. 12345\r\n) и след това при следващо пращане не приемам нищо.

Автор:  stefan63 [ Чет Апр 25, 2024 7:58 am ]
Заглавие:  Re: Проблем с Uart Interrupt STM32

Калбак функцията не се ли генерира от STMcube?
Не че ще е съвършена, ама твоята ми изглежда слаба.

Цитат:
Ако не стартирам отново приемането след като съм влязъл в callback-a, ще приема само един байт.


Имам смътни посозрения за какво говориш, но подобен стил ми е далечен.
HAL_UART_Receive_IT(&huart1,&buffer[tx_counter],1);
Това не е ли блокираща функция за приемане на един байт?
С Уарт просто не се работи така.

Автор:  bborisov567 [ Чет Апр 25, 2024 11:23 am ]
Заглавие:  Re: Проблем с Uart Interrupt STM32

Предполагам, че не е най-добрият начин, но не съм толкова навътре в нещата, за да го направя без HAL. Водя се по примера в сайта на ST : https://wiki.st.com/stm32mcu/wiki/Getting_started_with_UART#Configure_UART_Interrupt

Там го правят за 10 байта, аз за 1, за да мога всеки път да влизам в callback-a и да проверявам за край на съобщението.

Автор:  stefan63 [ Чет Апр 25, 2024 12:04 pm ]
Заглавие:  Re: Проблем с Uart Interrupt STM32

Разбирам.
Неприятното е ,че и HAL и STMcube са твърде обемисти неща.
Разгледах примера, който използваш ...не мисля ,че ST ти помагат много.
Бих те посъветвал
- Използвай тяхното инициализиране на Уарта.
Разгледай функциите, които ти осигуряват и се опитай да си напишеш собствена.
Намери функцията , която се изпълнява при приет байт. Там трябва да пипнеш , но другите им функции са за избягване.

- Реално трябва да приемаш каквото и да дойде и да го записваш в буфер (докато се напълни буфера или пък използваш кръгов буфер - това става в прекъсване).
Тоест трябва да стартираш приемане на 4ГБ в къгов буфер 100 байта , това в термините , които ползваш ти. При тебе буфера май не е кръгов , затова стартирай приемане на 1000 байта в буфер с дължина 1020 байта.
Но това трябва да е някава неблокираща функция - викаш я, тя записва няколко стойности тук там и се връща, не чака 1000 байта. Тия 1000байта ще се приемат в прекъсването.

В някаква твоя функция периодично проверяваш има ли изменение в буфера, ако да - проследяваш/обработваш новите байтове, ако видиш \r\n - ресетваш буферния указател.
Периодично се проверяват и статусните битове на УАРТа- след някои грешки приемането се блокира , докато не се изчистят съответните флагове или не се реинициализира порта.Но това го остави за малко по-късно.

Последно - тоя калбак ,дето го споменаваме- void HAL_UART_RxCpltCallback , май не е извикване от прекъсването, а го викаш след като приемеш байт.Не знам защо му казват калбак в случая.

На мене по ми харесва работа през DMA, но с прекъсване си е школовка, която не бива да се прескача.

Автор:  jordan-bg [ Чет Апр 25, 2024 12:25 pm ]
Заглавие:  Re: Проблем с Uart Interrupt STM32

премести HAL_UART_Receive_IT(&huart1,buffer, 1); преди while (1)

Автор:  TheWizard [ Чет Апр 25, 2024 12:35 pm ]
Заглавие:  Re: Проблем с Uart Interrupt STM32

:D чатГПТ обясни

`HAL_UART_Receive_IT` е функция в структурата на Hardware Abstraction Layer (HAL) на микроконтролерите от STMicroelectronics, която се използва за приемане на данни по UART (Universal Asynchronous Receiver-Transmitter) с прекъсване (interrupt-driven). Ето как работи тази функция:

1. **Подготовка за приемане**: Функцията се извиква с указател към буфер и дължина на данните, които трябва да бъдат приети. Тя настройва периферията на UART за приемане на данни и задава указателя и дължината на буфера, където ще бъдат записани получените данни.

2. **Разрешаване на прекъсване**: Функцията разрешава прекъсването от UART при получаване на нови данни. Това означава, че когато нови данни пристигнат през UART, микроконтролерът ще генерира прекъсване, което ще активира функцията за обработка на приемането на данните.

3. **Прекъсване при приемане на данни**: Когато прекъсването бъде генерирано от UART порта, контролерът автоматично ще прехвърли получените данни в буфера, който е предварително настроен с `HAL_UART_Receive_IT`.

4. **Известие за приемане на данни**: След като данните бъдат успешно приети, функцията ще извика callback функция, която е предварително зададена от потребителя. Тази callback функция може да обработи получените данни, да активира други операции или да освободи заетите ресурси.

Този начин на приемане на данни с прекъсване позволява на микроконтролера да продължи с изпълнението на други задачи, докато чака настаняването на нови данни по UART, като по този начин се постига по-ефективно използване на ресурсите на системата.


дай пример

Код:
#include "stm32f4xx_hal.h"
#include <stdio.h>

#define UART_HANDLE huart2 // Променете това според вашата конфигурация
#define RX_BUFFER_SIZE 64 // Размер на буфера за получени данни

UART_HandleTypeDef UART_HANDLE;
uint8_t rxBuffer[RX_BUFFER_SIZE];

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
    // Обработка на получените данни тук
    // Пример: просто извеждаме получените данни в конзолата
    printf("Received data: %s\n", rxBuffer);
   
    // Следващо приемане на данни
    HAL_UART_Receive_IT(&UART_HANDLE, rxBuffer, RX_BUFFER_SIZE);
}

int main() {
    // Инициализация на HAL библиотеката
    HAL_Init();
   
    // Инициализация на UART2
    UART_HANDLE.Instance = USART2;
    UART_HANDLE.Init.BaudRate = 115200;
    UART_HANDLE.Init.WordLength = UART_WORDLENGTH_8B;
    UART_HANDLE.Init.StopBits = UART_STOPBITS_1;
    UART_HANDLE.Init.Parity = UART_PARITY_NONE;
    UART_HANDLE.Init.Mode = UART_MODE_TX_RX;
    UART_HANDLE.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    UART_HANDLE.Init.OverSampling = UART_OVERSAMPLING_16;
    HAL_UART_Init(&UART_HANDLE);
   
    // Започваме приемането на данни с прекъсване
    HAL_UART_Receive_IT(&UART_HANDLE, rxBuffer, RX_BUFFER_SIZE);
   
    // Основна програма
    while (1) {
        // Тук може да извършвате други операции
    }
}

Автор:  bborisov567 [ Чет Апр 25, 2024 9:02 pm ]
Заглавие:  Re: Проблем с Uart Interrupt STM32

Мисля, че успях! В крайна сметка се оказа комбинация от доста дреболии и недоглеждания. Първо извадих
Код:
HAL_UART_Receive_IT(&huart1,buffer, 1);
извън while(1), както каза jordan-bg. За съжаление все още не работеше нищо.
След това ми дойде на ум, че функцията strstr() работи само с терминирани стрингове, а buffer-a изобщо не е терминиран, затова подходих към по-сигурен начин за търсене на края на съобщението - а именно сравняване на посления приет байт със знака за нов ред (/n). След това реших да нулирам буфера с memset() и накрая доста болезнено се сетих, че "\n" и '\n' са две доста различни неща. :D Ето го и крайния резултат - засега работи, но предстои тестване... Благодаря за насоките!

Код:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{

   if(huart->Instance == huart1.Instance)
      {
      tx_counter++;
    HAL_UART_Receive_IT(&huart1,&buffer[tx_counter],1);
            if (buffer[tx_counter-1] == '\n') { // дали последния приет знак е '/n' ?
               HAL_UART_AbortReceive_IT(&huart1); // прекъсни приемането
               tx_counter=0;                  // нулирай брояча
               strcpy(Rx_data, buffer);          // копирай данните
               memset(buffer, '\0', sizeof(buffer)); // нулирай буфера
               HAL_UART_Receive_IT(&huart1,&buffer[tx_counter],1); // започни ново приемане
      HAL_GPIO_TogglePin(LED_PRESSUR_GPIO_Port, LED_PRESSUR_Pin);
      }
      }
}

Автор:  Реконструктор [ Нед Апр 28, 2024 9:20 pm ]
Заглавие:  Re: Проблем с Uart Interrupt STM32

декларацията на buffer?

Автор:  bborisov567 [ Пон Апр 29, 2024 4:46 pm ]
Заглавие:  Re: Проблем с Uart Interrupt STM32

Реконструктор написа:
декларацията на buffer?



Всички променливи са декларирани извън функцията.

Автор:  Реконструктор [ Вто Май 07, 2024 11:45 pm ]
Заглавие:  Re: Проблем с Uart Interrupt STM32

bborisov567 написа:
Реконструктор написа:
декларацията на buffer?



Всички променливи са декларирани извън функцията.


Ако излизаш извън него, твърде вероятно е да се ресетва или забива

Страница 1 от 1 Часовете са според зоната UTC + 2 часа [ DST ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/