verlaty

Stm32: Cubemx+Uart_Dma

68 сообщений в этой теме

verlaty    0

Ясно. Но я сейчас думаю как то проследить ошибки, статусы, флаги или еще чего там. Передача у меня идет нормально.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
mail_robot    1 437

ну вот принимаем байт (у меня последовательность байт), тут же засылаем его в функцию эха. В ней уже делаем форматирование для удобства и шлем в консоль. В итоге все что контроллер принял вывалится на экран компа. Задача просто дождаться момента зависона и посмотреть на чем все застопорилось.

Я там еще пробелы добавляю и конец строки (перевод каретки + ноль символ) чтобы удобнее читать было

как только прием встал, анализируем последние байты и смотрим что там получилось. Делаем выводы

можно в эхо добавить переменки среды и флаги успешных посылок к примеру. Все что угодно что поможет понять в чем причина остановки приема. Дебаггер это с такой скоростью не отловит, сильно мудрить надо

Изменено пользователем mail_robot

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
verlaty    0

Кажется выловил ошибку.

huart1.ErrorCode выдает 8.

а это HAL_UART_ERROR_ORE ((uint32_t)0x00000008) /*!< Overrun error

ORE — ошибка: переполнение входного буфера — приняты новые данные, а старые ещё не прочитаны

во всяком случае есть куда капать.

Буду разбираться. Если есть дельные советы - внимательно слушаю

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
mail_robot    1 437

для начала попробовать

__HAL_UART_FLUSH_DRREGISTER(&huart1);

первой строчкой в колбэке

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
verlaty    0

Пробую сбрасывать флаг

void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
E_CODE = HAL_UART_GetError (huart);
switch (E_CODE)
{
case HAL_UART_ERROR_ORE:
 __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF);
 CLEARFL = HAL_UART_GetError (huart);
break;
}

сделал переменную CLEARFL для контроля

Ну в общем не сбрасывает. Кто сталкивался с этой бедой?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
mail_robot    1 437

возможно прежде чем сбросить флаг, надо устранить причину его возникновения, иначе следующим же тактом он опять будет поднят

см. предыдущий пост

ну и сам подход неверен. Сбросить флаг в железе может быть совсем не одно и то же для HAL. Лучше использовать макрос сброса (для F1 и F0)

для трешки еще можно попробовать вот эти вот макросы

UART Advanced Feature Overrun Disable

UART_ADVFEATURE_OVERRUN_ENABLE

UART_ADVFEATURE_OVERRUN_DISABLE

IS_UART_OVERRUN

единственное я на них доки не нашел, лучше посмотреть что там в них за код и покумекать как их поставить раком

Изменено пользователем mail_robot

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
verlaty    0

Точно. Надо сначала очистить буфер.

void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
E_CODE = HAL_UART_GetError (huart);
switch (E_CODE)
{
 case HAL_UART_ERROR_ORE:
  __HAL_UART_FLUSH_DRREGISTER(huart);
  __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF);
  CLEARFL = HAL_UART_GetError (huart);
 break;
}
}

Не прокатило

Изменено пользователем verlaty

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
mail_robot    1 437

отписал в добавку постом выше. Возможно не тот метод

возможно еще надо сделать status_reset после сброса флага

есть макрос очистки флага без функции

UART_CLEAR_OREF

OverRun Error Clear Flag

поставь в код и почитай чего там написано. (у меня либы F3 нет)

Изменено пользователем mail_robot

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
verlaty    0

В Кубе можно отключить overrun в конфигурации USART. Раз эта опция есть, значит ее можно тыкать.Вопрос на что это повлияет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
mail_robot    1 437

вот это уже хз. не проверял

думаю потеря байт в пакетах некоторых. но если будет проверка целостности пакетов и не все они нужны, то можно забить

понять бы почему этот самый оверран возникает при такой мизерной скорости... У меня даже на больших скоростях такого небыло

Изменено пользователем mail_robot

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
mail_robot    1 437

I ran into a similar problem as yours a few months ago on a Cortex M4 (SAM4S). I have a function that gets called at 100 Hz based on a Timer Interrupt.

In the meantime I had a UART configured to interrupt on char reception. The expected data over UART was 64 byte long packets and interrupting on every char caused latency such that my 100 Hz update function was running at about 20 Hz. 100 Hz is relatively slow on this particular 120 MHz processor but interrupting on every char was causing massive delays.

I decided to configure the UART to use PDC (Peripheral DMA controller) and my problems disappeared instantly.

DMA allows the UART to store data in memory WITHOUT interrupting the processor until the buffer is full saving lots of overhead.

In my case, I told PDC to store UART data into an buffer (byte array) and specified the length. When UART via PDC filled the buffer the PDC issued an interrupt.

In PDC ISR:

  1. Give PDC new empty buffer
  2. Restart UART PDC (so can collect data while we do other stuff in isr)
  3. memcpy full buffer into RINGBUFFER
  4. Exit ISR

As swineone recommended above, implement DMA and you'll love life.

короче говоря, убирай ожидание первого байта по прерыванию и читай все по ДМА. Попробовать так

там еще написано следующее

типок выделил для ДМА кольцевой буфер, и как только тот заполнялся, он входил в прерывание ДМА и выделял ему новый буфер, а старый в это время обрабатывал. Как то так

Изменено пользователем mail_robot

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
verlaty    0

тема изначально назвалась Cubemx + uart_dma. Заметил такую вещь. Один уарт у меня принимает пачки по 8 байт второй по 3. Тот который по 8 практически не зависает, а вот по 3 постоянно. Хотя все реализовано аналогично, на одной плате, на оном камне, но факт на лице.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
mail_robot    1 437

почитал буржуев. В общем оверран возникает тогда, когда не успеваешь прочитать предыдущий байт, а следующий уже начал приниматься (откапитанил). Флаг оверрана может не сбрасываться программно, до тех пор пока байт не будет физически прочитан из буфера (то есть он не затирается, а ждет чтения). Очистка регистра данных может и поможет, а может и нет. Судя по всему не помогает. Или следующий оверран просто перетирает флаг быстрее чем оклимается контроллер.

Выводы.

Надо делать непрерывный прием в некий буфер в памяти. У меня таким буфером была очередь, поэтому видимо все и успевало, хотя принимал я по одному символу и камень был F103. Очевидно надо думать как ускорить чтение или организовывать буфер. Костыли типа сброса флага не помогут.

Возможно на первом канале приоритет прерываний или канала DMA выше, поэтому он и не глючит так.

Печалька

Изменено пользователем mail_robot

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
mail_robot    1 437

вот так вот происходила обработка из очереди в операциоке. В принципе обрабатывалось по одному байту. Можно попробовать сделать прием в буфер длинной 1 байт и обрабатывать на лету прямо в колбэке приема. До 0,9 мегабита работает железобетонно на камне F051 и F103 (частотки 48 и 72 МГц соответственно)

void StartUserTask01(void const * argument)
{
char lReceivedValue;
portBASE_TYPE xStatus;
const portTickType xTicksToWait = 1000 / portTICK_RATE_MS;
short int rxindex = 0;
uint8_t ErrorFlag = UART_PACKET_OK;
char rxString[MAXSTRING];

for( ;; )
{
UBaseType_t i = 0;
i = uxQueueMessagesWaiting( myQueue01Handle );
while (i != 0)
{
xStatus = xQueueReceive( myQueue01Handle, &lReceivedValue, xTicksToWait );
 if( xStatus == pdPASS )
 {
 if (lReceivedValue == 8 || lReceivedValue == 127) // If Backspace or del
{
rxindex--;
if (rxindex < 0) rxindex = 0;
}
else if (lReceivedValue == '\n') // If Enter
{
if (ErrorFlag == UART_PACKET_OK)
{
 rxString[rxindex] = '\n';
 rxindex++;
 rxString[rxindex] = 0;

 rxindex = 0;

 command_processor(rxString); // command handler
}
else
{
 //TODO - UART Error handler
 ErrorFlag = UART_PACKET_OK; // reset error state
}
}
else
{
if (lReceivedValue != '\r' && ErrorFlag == UART_PACKET_OK) // Ignore return
{
 rxString[rxindex] = lReceivedValue; // Add that character to the string
 rxindex++;
 if (rxindex >= MAXSTRING) // User typing too much, we can't have commands that big
 {
 ErrorFlag = UART_PACKET_TOO_LONG;
 rxindex = 0;
 rxString[rxindex] = '\000';
 }
}
}
 }
 else
 {
 taskYIELD();
 }
i--;
}
}
}

счас нарою проект с голым уартом на эту тему

вот, делал просто голыш без использования операционки, работал неделями, ни разу не сбоил

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
static short int rxindex = 0;
static uint8_t ErrorFlag = UART_PACKET_OK;
//__HAL_UART_FLUSH_DRREGISTER(&huart1); // Clear the buffer to prevent overrun
if (rxBuffer == 8 || rxBuffer == 127) // If Backspace or del
{
rxindex--;
if (rxindex < 0) rxindex = 0;
}
else if (rxBuffer == '\n') // If Enter
{
if (ErrorFlag == UART_PACKET_OK)
{
rxString[rxindex] = rxBuffer; // Add that character to the string
rxindex++;
rxString[rxindex] = 0;
rxindex = 0;
if (huart->State != HAL_UART_STATE_BUSY_TX_RX) UART_Send (rxString);
}
else
{
if (huart->State != HAL_UART_STATE_BUSY_TX_RX) UART_Send ("ERROR > UART packet too long\n");
ErrorFlag = UART_PACKET_OK; // reset eeror state
}
}
else
{
if (rxBuffer != '\r' && ErrorFlag == UART_PACKET_OK) // Ignore return
{
rxString[rxindex] = rxBuffer; // Add that character to the string
rxindex++;
if (rxindex >= MAXSTRING) // User typing too much, we can't have commands that big
{
ErrorFlag = UART_PACKET_TOO_LONG;
rxindex = 0;
rxString[rxindex] = '\000';
}
}
}
}

могу прям проектами в почту отправить целиком. (все под Keil правда)

Изменено пользователем mail_robot

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
mail_robot    1 437

да, именно так. Буфер на один символ. Принимает все подряд до тех пор пока не примет \n. Дальше передает принятое в обработчик строки. Работало 100%

могу отправить весь проект. Но там ничего особенного. В мэйне стартует прием по дма сразу после инитки и в глобальных переменках определен односимвольный буфер. Все стандартно

ну и еще определен глобальный массив под строку для складирования в колбэке. ДМА читает в односимвольный буфер, а колбэк из него пихает в массив который управляется rxindex. ДМА работает в цикле и никогда не останавливается

суть в чем - даже если прерывания не будут поспевать за приемом, то оверрана не будет. Просто потеряется символ и все на этапе обработки. Но до 0,9М такого не происходило. Реальные потери начинаются гдето в районе 1,3...1,5Мб/с. На 3,5 Мб/с теряется примерно каждый 3-й символ

Изменено пользователем mail_robot

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
verlaty    0

Запустил UART в режим DMA circular. Слегка подправил свой код для работы в этом режиме, без постоянных запусков HAL_UART_Receive_DMA . Все проблемы снялись, все работает. Отдельное спасибо mail_robot за активную помощь и участие.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ваша публикация должна быть проверена модератором

Гость
Вы не авторизованы. Если у вас есть аккаунт, пожалуйста, войдите.
Ответить в тему...

×   Вставлено в виде отформатированного текста.   Восстановить форматирование

  Разрешено не более 75 смайлов.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставить изображения напрямую. Загрузите или вставьте изображения по ссылке.

Загрузка...

  • Сообщения

    • Выкладываю фото в порядке увеличения амплитуды сигнала. Частота синуса 20 кГц. Китайский щуп ослика стоит на 10Х, так как при 1Х в экран картина не помещается.
    • Да кто спорит...  В сети навалом всякого, как букв на заборе.  Зачем народ-дилетант приходит на форум? С желанием выслушать прямой разумный совет от специалиста, без отсылки к штудированию литератур и копанию сети. Частенько пришелец и вопрос-то сформулировать не знает как, поэтому обьясняться вживую, на пальцах - оно доходчивей. Если конечно, есть такое желание у сторон. 
      К чему отсылать неофита к изучению книжек, типа ты вот сначала всю премудрость превзойди, а потом мы еще проверим, где тебя на кукан подсадить нам будет очень приятно. Типа если  послать кого в трамвае - могут и по роже дать, а тут, на форуме - безопасно.  Критерий Босфорта, байпассы семьсот сорок четвертого порядка, формулы, расчеты - ох, какоой же ты умный, птица-говорун - подразумевается восхищение всей форумской публики. На работе мрак, денег нету, дома жена достает, дети просят купить покушать вкусного - отвалите от меня все, я бандпас шестого порядка считаю! Во какой я! Не хрен собачий, калькулятором умею пальцем тыкать. 
      Великий человек! - воскликнет публика, разинув рот от восторга. Какие умные слова знает!  Нет чтобы на  простой вопрос ответить столь же просто,  без распальцовки.  Кстати, к вам, Meshin, этот пассаж не относится. Вы вроде вполне нормальный человек. За ваши советы спасибо.
    • Да мне плевать на твои ответы. Ты обычный жирный трoлль, которому нечего сказать по существу и не более того.
    • У меня так происходит когда держу сверло пальцами и раззенковываю или снимаю фаски с отверстий.
    • Должен греться. Нормально все. Просто трансформатор сильно перегружен током. Однако этот ток ты не видишь, т.к. используешь амперметр неправильной системы. Дело в том, что все доступные амперметры ПЕРЕМЕННОГО ТОКА калибруются на переменном токе строго синусоидальной формы. Но в тиристорном регуляторе форма тока очень сильно отличается от синусоидальной. Фактически от синусоиды остаются лишь жалкие обрезки треугольной формы очень большой амплитуды, а между этими треугольниками тока и вовсе нет. Как результат, традиционный тестер дает сильно заниженное значение ПЕРЕМЕННОГО тока.

      Выстави ток 2,73А на вторичной обмотке трансформатора по любому щитовому амперметру ЭЛЕКТРОМАГНИТНОЙ системы. У «правильного» амперметра начало шкалы будет сильно «скомкано», а на шкале снизу будет значок как вверху средней колонки таблицы. Эти амперметры почти все на 5А, независимо от того, что написано на шкале. Ток понижается до 5А специальным трансформатором, но он тебе в данном случае не нужен. Коэффициент пересчета (коэффициент трансформации трансформатора тока) указывается на шкале амперметра. Например, ТТ500/5 или просто 500/5.

      Но я сразу могу сказать, что ДЕЙСТВУЮЩЕМУ значению ПЕРЕМЕННОГО ТОКА 2,73А на вторичной обмотке трансформатора будет соответствовать СРЕДНЕЕ значение ПОСТОЯННОГО ТОКА ЗАРЯДКИ всего лишь 1…1,5А, в зависимости от угла отпирания тиристора.

      Однозначно нужно менять трансформатор на более мощный. Для тока зарядки 5А нужен трансформатор на ток хотя бы 10А. Но лучше на 15А. Можно использовать и ТПП276, но только летом понадобятся ЧЕТЫРЕ таких трансформатора, соединенные параллельно. Зимой может хватить и трех трансформаторов.
    • Тут ещё амплитуду индукции надо учитывать , чтоб потери в феррите были не большие. Посчитайте программой Старичка,но лучше мотать на кольце из порошкового железа смесь-2, красно-черное , обмотку желательно однослойную. 
    • Приветствую сообщество.
      Подскажите в последних библиотеках с сайта нет разъема ХН, не могу найти хоть подобные.