Отговори на тема  [ 12 мнения ] 
Проблем с Uart Interrupt STM32 
Автор Съобщение
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Съб Фев 04, 2023 2:42 am
Мнения: 14
Мнение Проблем с 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 и да чакам за полуването на ново съобщение. Проблемът е, че работи само веднъж. Първият път след ресет всичко минава както трябва, но след това като изпращам не се получава нищо от контролерът.


Сря Апр 24, 2024 9:44 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Вто Фев 07, 2012 11:22 pm
Мнения: 3084
Мнение Re: Проблем с Uart Interrupt STM32
Предполагам - калбак функцията се вика от прекъсване на уарта по приет байт. И функцията HAL_UART_Receive_IT е сложена в калбак от StmCube?
Не виждам смисъл от нея в main().


Сря Апр 24, 2024 9:59 pm
Профил
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Съб Фев 04, 2023 2:42 am
Мнения: 14
Мнение Re: Проблем с Uart Interrupt STM32
Код:
HAL_UART_Receive_IT(&huart1,&buffer[tx_counter],1);
e в callback-a, за да мога да продължа да приемам байтове. Сложена е от мен. Ако не стартирам отново приемането след като съм влязъл в callback-a, ще приема само един байт. За да не стане объркване аз приемам едно съощбение в мoмента (напр. 12345\r\n) и след това при следващо пращане не приемам нищо.


Сря Апр 24, 2024 10:05 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Вто Фев 07, 2012 11:22 pm
Мнения: 3084
Мнение Re: Проблем с Uart Interrupt STM32
Калбак функцията не се ли генерира от STMcube?
Не че ще е съвършена, ама твоята ми изглежда слаба.

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


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


Чет Апр 25, 2024 7:58 am
Профил
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Съб Фев 04, 2023 2:42 am
Мнения: 14
Мнение Re: Проблем с Uart Interrupt STM32
Предполагам, че не е най-добрият начин, но не съм толкова навътре в нещата, за да го направя без HAL. Водя се по примера в сайта на ST : https://wiki.st.com/stm32mcu/wiki/Getting_started_with_UART#Configure_UART_Interrupt

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


Чет Апр 25, 2024 11:23 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Вто Фев 07, 2012 11:22 pm
Мнения: 3084
Мнение Re: Проблем с Uart Interrupt STM32
Разбирам.
Неприятното е ,че и HAL и STMcube са твърде обемисти неща.
Разгледах примера, който използваш ...не мисля ,че ST ти помагат много.
Бих те посъветвал
- Използвай тяхното инициализиране на Уарта.
Разгледай функциите, които ти осигуряват и се опитай да си напишеш собствена.
Намери функцията , която се изпълнява при приет байт. Там трябва да пипнеш , но другите им функции са за избягване.

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

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

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

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


Чет Апр 25, 2024 12:04 pm
Профил
Online
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Пет Ное 21, 2014 1:25 pm
Мнения: 26
Мнение Re: Проблем с Uart Interrupt STM32
премести HAL_UART_Receive_IT(&huart1,buffer, 1); преди while (1)


Чет Апр 25, 2024 12:25 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Сря Апр 27, 2005 12:48 pm
Мнения: 6094
Мнение 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) {
        // Тук може да извършвате други операции
    }
}

_________________
main[-1u]={1};


Чет Апр 25, 2024 12:35 pm
Профил ICQ
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Съб Фев 04, 2023 2:42 am
Мнения: 14
Мнение 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);
      }
      }
}


Чет Апр 25, 2024 9:02 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Съб Сеп 25, 2004 12:32 pm
Мнения: 8382
Местоположение: София
Мнение Re: Проблем с Uart Interrupt STM32
декларацията на buffer?


Нед Апр 28, 2024 9:20 pm
Профил
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Съб Фев 04, 2023 2:42 am
Мнения: 14
Мнение Re: Проблем с Uart Interrupt STM32
Реконструктор написа:
декларацията на buffer?



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


Пон Апр 29, 2024 4:46 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Съб Сеп 25, 2004 12:32 pm
Мнения: 8382
Местоположение: София
Мнение Re: Проблем с Uart Interrupt STM32
bborisov567 написа:
Реконструктор написа:
декларацията на buffer?



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


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


Вто Май 07, 2024 11:45 pm
Профил
Покажи мненията от миналия:  Сортирай по  
Отговори на тема   [ 12 мнения ] 

Кой е на линия

Потребители разглеждащи този форум: 0 регистрирани и 3 госта


Вие не можете да пускате нови теми
Вие не можете да отговаряте на теми
Вие не можете да променяте собственото си мнение
Вие не можете да изтривате собствените си мнения
Вие не можете да прикачвате файл

Търсене:
Иди на:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.
Хостинг и Домейни