Jump to content
dim3740

Ошибка / пропуски при буферизации данных

Recommended Posts

Читается порт UART на микроконтроллере Atmega. Применяю типовой алгоритм, но аппаратно вижу ошибки. Что неверное, или отчего они могут быть?
 

unsigned char rx_buffer[128]; //накопительный буфер
unsigned char indexW; // индекс при наполнении накопительного буфера
unsigned char Count; // счетчик накопительного буфера
unsigned char indexR; // индекс при опорожнении накопительного буфера
int Max; // максимум до переполнения
char tempMessage; // временная переменная

int main(void)
{

   Max=100; // пробовал разные

   while(1)
    {
        _delay_us(40); // пробовал от 10 мкс до мс
        
                if (Count > 0) 
        {
            tempMessage=rx_bufferR[indexR];  
            
                        MesComplite(tempMessage); //тут анализ каждого считанного байта. Это занимает время 
                                        //поэтому и нужен буфер
            
            indexR++;  
            
            if (indexR>=Max)  indexR=0;  //Значение Max одинаковое для чтения и записи. Может разные проба?
            
            cli();  // для надежности запрет прерывания
            Count--;
            sei(); //разрешение
            
            if (Count>=Max)  Count=0;
        
        }
        
    }
}

ISR(USART_RXC_vect)  
{
    if (UCSRA & (1<<7))   
    {
        
        rx_buffer[indexW]=UDR;
        
        indexW++;  
        
        if (indexW>=Max)  indexW=0;
     
            Count++;
        
        if (Count>Max)  Count=0; 
    
    }
}


1. Задержка нужна в цикле whole? У меня при нуле еще больше ошибок(((
2. Размеры 128 и 100 методом подбора?
3. Инкременты ++ ставить после команды?
4. запреты прерывания нужны?
5. If делаю на "равенство и больше". Верно?
6. Какие есть иные методы повышения надежности, кроме повторной отправки при ошибке?

Share this post


Link to post
Share on other sites

Вопрос в том ещё, что скажем есть 2-3 алгоритма устранения дребезга. Неужели нет других алгоритмов и по сабжу? Скажем что если юзать сразу три буферных одномерных массивов и потом сверять их на идентичность данных по одному и тому же индексу?

Share this post


Link to post
Share on other sites

Изготовление 2-х слойных плат от 2$, а 4-х слойных от 5$!

Быстрое изготовление прототипа платы всего за 24 часа! Прямая доставка с нашей фабрики!

Смотрите видео о фабрике JLCPCB: https://youtu.be/_XCznQFV-Mw

Посетите первую электронную выставку JLCPCB https://jlcpcb.com/E-exhibition чтобы получить купоны и выиграть iPhone 12, 3D-принтер и так далее...

Странноватый код. Я правда не помню когда я атмел последний раз видел, так что тапками не кидаться, но все-таки:

0) Вы уверены что инициализация UART правильная? Как минимум, проверьте что ошибка в baud rate на разных сторонах линка не более 2%, иначе будут глюки. Из вашего сорца не видно какой baud вы пытаетесь получить и все такое.

1) Delay какой-то в основном цикле. Он несет какой-то смысл? Обработчик прерывания свое время сам урвет. На то оно и прерывание что вышибет основную программу. Похоже на костыль маскирующий истинную проблему.

2) Размеры буфера - по размеру максимального пакета который вы хотите жевать за раз (и доступной памяти). Это зависит от того что вы намереваетесь делать с данными и какими порциями они имеют смысл. Кроме того, лимит в 100 байтов в обработчике при 128 байтах буфера приводит к тому что 28 байтов оперативки сжираются под буфер но никогда не используются, поскольку при достижении 100 обработчик делает разворот. Оставшиеся байты на вид вроде бы просто потеряны, а у атмела не настолько уж огромная оперативка.

3) В вашем коде нет никаких способов понять где начало передачи данных и все такое прочее. Ну то-есть если алгоритм начал вкалывать с середины передачи с той стороны - он что-то конечно примет. С произвольного места. А вот имеет ли принятое смысл - отдельный вопрос.

4) При малейшей неидеальности ваш код вероятно рассинхронизируется с передатчиком и врядли вернется в синхронизм. Ну как, протокола у вас нет, чексум нет, анализа ошибок UART тоже нет. Причина ошибок останется загадкой, просто потому что никто нигде не проверяет ошибки и не заморачивается ре-синхронизацией по допустим протокольному таймауту (т.е. сброс состояния протокола на исходное по таймауту например).

5) Подозрительно выглядит main loop, например sei вы сделали, а потом if (Count>=Max)  Count=0; - а если между сравнением и присвоением приедет IRQ, то чего? IRQ не в курсе намерений сделать Count = 0, он что-то сделает с Сount, наверное не просто, вернется. А тут вы хлоп Count в 0 когда выполнение вернулось обратно main. Но хотели вы наверное не этого? Похоже на race condition вроде.

6) Неплохо бы чтобы у протокола еще и чексуммы какие-то были для понимания что данные побились. Или если это интерактив через терминалку то короткие команды и выход по таймаутам или характерным маркерам типа перевода строк на исходное состояние "ждем команду".

7) Что до дребезга, железо UART обычно делает oversampling порядка 8 отсчетов на бит и принимает решение что за бит по мажоритарному принципу. Как оно у атмела написано в их даташите. И если у вас все настолько плохо что uart ловит мусор и вас беспокоит дребезг - где хотя-бы обработка framing error и проч? Да и после того как вы узнали что ошибка - часть данных возможно потеряна. У вас на этот счет был план? Если UART поймает стартовый бит там где его не было, вся последовательность будет сдвинута. UART поймает сколько-то данных, в конце концов заметит framing error, когда STOP в нужном месте не окажется. Часть данных окажется порушена, часть не принята. Если вы хотите работать в окружении где ошибки норма, придется сделать какой-нибудь протокол. Если данные ценные, их придется попросить у отправителя еще раз. Если не очень - хотя-бы выйти на исходное состояние.

8) Сразу 3 массива - да вы эстет. Вы хотите слать данные 3 раза и выбирать по мажоритарному принципу? А оно надо? К тому же при framing error uart может принять что-то из середины битового потока и не сразу заметить проблему. В конце концов он скорее всего отхватит framing error, не найдя STOP вовремя, но сколько данных до этого приедет и что в них будет - никто не обещает. И трояная посылка одного и того же байта может в этом случае не помочь.

А так для повышения надежности можно слать не абы что а пакет с характерным маркером начала, указанием длины и чексумой, возможно маркером конца. И подтверждать отправителю что получили, если это важно. Если подтверждения нет - слать пакет еще раз. При этом понятно и где начало данных (маркер должен совпасть, иначе пропускаем мусор мимо ушей пока правильный маркер не появится), и получили ли мы все что хотел послать отправитель (по размеру пакета и возможно маркеру конца), и правильно ли это приехало (по чексуме). При этом и хардварные проблемы будут видны не в виде нежданчиков а в виде какой-нибудь статистики протокола. Кстати все это актуально и для второй стороны линка. Особенно забавно когда там компьютер с многозадачной ОС, там некоторые забавные особенности есть.

Edited by guest87

Share this post


Link to post
Share on other sites

Вебинар "Новый BlueNRG-LP с Bluetooth 5.2 и Long Range — волшебная палочка разработчика IoT" (04/02/2021)

Приглашаем 4 февраля на бесплатный вебинар о BlueNRG-LP - новой системе-на-кристалле (SoC) STMicroelectronics. На вебинаре будут детально рассмотрены функциональные блоки, особенности подключения, аппаратные и программные средства для разработки, настройка сценариев с помощью BlueNRG-GUI, практические примеры работы с микросхемой, а также примеры применения BlueNRG-LP в устройствах интернета вещей.

Подробнее

13 минуты назад, guest87 сказал:

Странноватый код. Я правда не помню когда я атмел последний раз видел, так что тапками не кидаться, но все-таки:

0) Вы уверены что инициализация UART правильная? Как минимум, проверьте что ошибка в baud rate на разных сторонах линка не более 2%, иначе будут глюки. Из вашего сорца не видно какой baud вы пытаетесь получить и все такое.

31250. Прием MIDI сообщений в музыкальном оборудовании.  Сбой примерно 1 на сотню нажатых клавиш (т.е. получено около 600 байт)

13 минуты назад, guest87 сказал:

1) Delay какой-то в основном цикле. Он несет какой-то смысл? Обработчик прерывания свое время сам урвет. На то оно и прерывание что вышибет основную программу. Похоже на костыль маскирующий истинную проблему.

Это методом тыка. Почему то без него сбоев гораздо больше

13 минуты назад, guest87 сказал:

2) Размеры буфера - по размеру максимального пакета который вы хотите жевать за раз (и доступной памяти). Это зависит от того что вы намереваетесь делать с данными и какими порциями они имеют смысл. Кроме того, лимит в 100 байтов в обработчике при 128 байтах буфера приводит к тому что 28 байтов оперативки сжираются под буфер но никогда не используются, поскольку при достижении 100 обработчик делает разворот. Оставшиеся байты на вид вроде бы просто потеряны, а у атмела не настолько уж огромная оперативка.

Пакетов нет... все непрерывно. Оперативка, выделение памяти по "правильные" переменные, оптимизация ее - это удел профи, и нехватки ресурсов. У меня примитивная задача, и минимальной атмеги хватит за глаза)))) Зачем экономит то, то не жалко?

13 минуты назад, guest87 сказал:

3) В вашем коде нет никаких способов понять где начало передачи данных и все такое прочее. Ну то-есть если алгоритм начал вкалывать с середины передачи с той стороны - он что-то конечно примет. С произвольного места. А вот имеет ли принятое смысл - отдельный вопрос.

Да. Но сбой именно где-то в середине и т.п. передачи...

13 минуты назад, guest87 сказал:

4) При малейшей неидеальности ваш код вероятно рассинхронизируется с передатчиком и врядли вернется в синхронизм. Ну как, протокола у вас нет, чексум нет, анализа ошибок UART тоже нет. Причина ошибок останется загадкой, просто потому что никто нигде не проверяет ошибки и не заморачивается ре-синхронизацией по допустим протокольному таймауту (т.е. сброс состояния протокола на исходное по таймауту например).

Анализ ошибок эффективен, если есть возможность сообщения источнику о ней. У меня сигнал идет от синтезатора. на котором играем музыкант. Естесвенно, он не станет переигрывать сбойную ноту.)))

13 минуты назад, guest87 сказал:

5) Подозрительно выглядит main loop, например sei вы сделали, а потом if (Count>=Max)  Count=0; - а если между сравнением и присвоением приедет IRQ, то чего? IRQ не в курсе намерений сделать Count = 0, он что-то сделает с Сount, наверное не просто, вернется. А тут вы хлоп Count в 0 когда выполнение вернулось обратно main. Но хотели вы наверное не этого? Похоже на race condition вроде.

М.б. это действительно, ошибка.  Я не проф. программист, а музыкант. Поэтому многое делаю не понимая((((

13 минуты назад, guest87 сказал:

6) Неплохо бы чтобы у протокола еще и чексуммы какие-то были для понимания что данные побились. Или если это интерактив через терминалку то короткие команды и выход по таймаутам или характерным маркерам типа перевода строк на исходное состояние "ждем команду".

7) Что до дребезга, железо UART обычно делает oversampling порядка 8 отсчетов на бит и принимает решение что за бит по мажоритарному принципу. Как оно у атмела написано в их даташите. И если у вас все настолько плохо что uart ловит мусор и вас беспокоит дребезг - где хотя-бы обработка framing error и проч? Да и после того как вы узнали что ошибка - часть данных возможно потеряна. У вас на этот счет был план? Если UART поймает стартовый бит там где его не было, вся последовательность будет сдвинута. UART поймает сколько-то данных, в конце концов заметит framing error, когда STOP в нужном месте не окажется. Часть данных окажется порушена, часть не принята. Если вы хотите работать в окружении где ошибки норма, придется сделать какой-нибудь протокол. Если данные ценные, их придется попросить у отправителя еще раз. Если не очень - хотя-бы выйти на исходное состояние.

Про деребезг - это я для примера, и конечно, простых кнопок, а не UART.

13 минуты назад, guest87 сказал:

8) Сразу 3 массива - да вы эстет. Вы хотите слать данные 3 раза и выбирать по мажоритарному принципу? А оно надо? К тому же при framing error uart может принять что-то из середины битового потока и не сразу заметить проблему. В конце концов он скорее всего отхватит framing error, не найдя STOP вовремя, но сколько данных до этого приедет и что в них будет - никто не обещает. И трояная посылка одного и того же байта может в этом случае не помочь.

Это я не подумал. Я предполагал, один UART и писать в три массива. Но, думаю, что ошибки идут чисто аппаратные (фронты сигналов, помехи и т.п.) и ошибка запишется во все три массива. Забыли эту мысль!

13 минуты назад, guest87 сказал:

А так для повышения надежности можно слать не абы что а пакет с характерным маркером начала, указанием длины и чексумой, возможно маркером конца. И подтверждать отправителю что получили, если это важно. Если подтверждения нет - слать пакет еще раз. При этом понятно и где начало данных (маркер должен совпасть, иначе пропускаем мусор мимо ушей пока правильный маркер не появится), и получили ли мы все что хотел послать отправитель (по размеру пакета и возможно маркеру конца), и правильно ли это приехало (по чексуме). При этом и хардварные проблемы будут видны не в виде нежданчиков а в виде какой-нибудь статистики протокола.

 

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

 

Вообще имеем черный ящик. На него приходят байты от источника (синтезатор). С него уходят байта на другой синтезатор. В Ч,Я - разные алгоритмы преобразования инфы. Допустим, что преобразования не нужно. Тогда справедлив ли код в обработчике UART, типа:

 temp=UDR  и сразу UDR=temp.

Да, он работает. Тут нет буфера, ибо зачем он нужен, если программист знает алгоритм работы девайса в целом и понимает, что НИЧТО не прервет эту отправку СРАЗУ. Ибо нет более высокого уровня задачи, нет падений питания, нет нажатия кнопок, таймеров и т.п. Но... он н универсален, ибо это частный случай. Идем дальше: пусть надо "вклинить" опрос пары кнопок. Размещаем этот опрос в главном цикле. Но опять таки играя музыкант НЕ нажимает эти кнопки. Так может опять буфер не нужен?  А когда он нужен? Когда, нужно сделать что-то именно с поступающими байтами. Логика верна? Я не знаю, просто советуюсь....

Share this post


Link to post
Share on other sites

Новые компактные конденсаторы Panasonic серии TPS. Закаленный характер.

Panasonic представил новую серию TPS твердотельных танталовых конденсаторов с проводящим полимером для поверхностного монтажа. Конденсаторы серии TPS обладают уникальными особенностями, что делает их отличным выбором для использования в приложениях с высокими требованиями.

Подробнее

28 minutes ago, dim3740 said:

31250. Прием MIDI сообщений в музыкальном оборудовании. 

Ого, понятно. Тогда про блоки придется забыть. А вы запрограммили именно такой baud rate на стороне МК, с точностью не хуже 2%? Уж простите я не помню как у атмела синтез baud делается.

Сбой примерно 1 на сотню нажатых клавиш (т.е. получено около 600 байт)

Понятно. А если для начала без прерываний читать в tight loop из регистра, без задержек (ориентируясь на флаг приема) ничего с данными не делая - ошибки будут? Если да - похоже на проблему "железного" характера. Если нет - логика буферизации. Если проблема с железом - у вас сделана опторазвязка как советуют на https://learn.sparkfun.com/tutorials/midi-tutorial/all ? Без этого есть шанс собрать солидные наводки и принимать черти-что, у вас наверное провода длинные. Спасибо если только это - хорошая наводка на длинный кабель может и порт вынести. В случае опторазвязки нет левых токов в порты, да и убить транзистор малореально в отличие от порта IO.

Это методом тыка. Почему то без него сбоев гораздо больше

Нет смысла прятать проблему под ковер. Она от этого не пропадет - стоит понять в чем причина. Мне не нравится что обработчик и main живут своими жизнями настолько независимо что одурачивают друг друга внезапными сменами переменных. Хотя у вас и аппаратная проблема может быть.

Пакетов нет... все непрерывно. Оперативка, выделение памяти по "правильные" переменные, оптимизация ее - это удел профи, и нехватки ресурсов. У меня примитивная задача, и минимальной атмеги хватит за глаза)))) Зачем экономит то, то не жалко?

Да я уж посмотрел. Хоть и не занимался именно миди, но протокол нашел по быстрому. Там и правда все побайтово. Но сказать что пакетов нет - не совсем так. Есть некое состояние - байты описывающие что это такое и потом 1 или несколько ожидаемых байтов для некоторых команд как я понимаю. Это не совсем независимые байты и вывод о том получили ли все что хотели сделать можно.

Кстати данных немного и можно наверное вообще в tight loop ловить все и там же парсить. Или если хочется по фэншую, с прерыванием и буфером, наверное в прерывание вынести немного логики разбора midi, как минимум понимание где начало очередной команды, сколько байтов ждать и поймали ли всю команду или нет. И анонс main что все что хотели - приехало. Или если вся команда за разумное время не приехала - забываем и ждем новую.

Да. Но сбой именно где-то в середине и т.п. передачи...

На самом деле может быть по куче причин, от несовпадения baud и длинного шнура поймавшего помехи до кривой логики буферизации. Я бы попробовал для начала получать байты как есть без прерываний глупым poll. Это фи по использованию ресурсов, зато все предельно просто и ошибиться негде. Кстати 31250 битов в секунду это 3125 байтов в секунду (8-N-1=10 битов). У вас есть 1/3125 секунды (=32мкс) чтобы с байтом что-то сделать, не потеряв следующий. Это не то чтобы очень много, но для простых вещей хватит.

Анализ ошибок эффективен, если есть возможность сообщения источнику о ней. У меня сигнал идет от синтезатора. на котором играем музыкант. Естесвенно, он не станет переигрывать сбойную ноту.)))

Да, тут уж увы, если это миди - тогда так. И тут только добиваться приема без ошибок. Что на стороне железа что на стороне софта. Но все-таки анализ флагов типа ошибок фрейминга или что там атмел умеет - позволит понять есть ли проблемы "железного" характера. Ну как, в идеале ошибок фрейминга и проч быть не должно и если они есть это повод посмотреть что с "железом".

М.б. это действительно, ошибка.  Я не проф. программист, а музыкант. Поэтому многое делаю не понимая((((

Однако ж начать с довольно продвинутой работы с прерываниями и чем-то типа кольцевого буфера - замах весьма солиден. И хотя ряд вещей вызывают подозрения, общая идея работы с прерыванием какая-то такая. Вот только такой кольцевой буфер вам наверное вообще не надо. А переменные которые меняет ISR стоит указывать как volatile. Иначе си может оптимизировать доступ к ним на свою голову, оформив переменную как значение регистра а не адрес в памяти. ISR же не в курсе такой подляны, он вызывается железом, регистры в этот момент уже другое и можно потенциально огрести глюков. Но это "в си и МК вообше", я не помню насколько это критично для атмела, но все с чем имеет дело IRQ стоит декларить как volatile.

Про деребезг - это я для примера, и конечно, простых кнопок, а не UART.

Однако аппаратные UART нечто подобное в виде оверсэмпла делают. Так устойчивее.0

Это я не подумал. Я предполагал, один UART и писать в три массива. Но, думаю, что ошибки идут чисто аппаратные (фронты сигналов, помехи и т.п.) и ошибка запишется во все три массива. Забыли эту мысль!

Не очень понимаю что дадут именно 3 буфера. Я еще могу понять если поток данных очень большой, обработка очень сложная, то можно получать в один буфер пока разбирать другой. Но в этом случае опять же IRQ должен немного заняться "состояниями протокола" чтобы кормить того кто разбирает командами целиком, чтоли.

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

Я бы попробовал для начала тупым poll из регистра UART читать все что валится и посмотреть насколько то что валится (не)правильное для понимания виновато ли железо в чем либо. За 32 мкс до следующего байта (быстрее он не приедет чисто физически) можно успеть и флаги ошибок посмотреть и даже что-то сделать (например в второй uart загнать если у него baud выше, отфорвардив на комп).

Но поскольку я атмеги видел давно и все забыл и с миди не работал - я наверное не лучший специалист в этом. Просто я с уартами работал и некоторые проблемы знаю.

 

Share this post


Link to post
Share on other sites

SiC MOSFET на 1200 В для схем флайбэк до 500 Вт!

Компания Wolfspeed выпустила новые карбид-кремниевые транзисторы C3M0350120D/J на 1200 В, предназначенные для маломощных устройств мощностью до 500 Вт. Карбид-кремниевые транзисторы в сравнении с кремниевыми демонстрируют меньший на 75% уровень потерь на переключение и меньшее на 50% значение потерь проводимости в рабочем режиме при температуре кристалла 100…150°С.

Подробнее

2 часа назад, guest87 сказал:

Но поскольку я атмеги видел давно и все забыл и с миди не работал - я наверное не лучший специалист в этом. Просто я с уартами работал и некоторые проблемы знаю.

Это не страшно)) Главное, что Вы не пытаетесь учить меня профкодированию, а согласны подойти к проблеме обобщенно. Я также сейчас выдаю все "от печки", по сути задачи в целом, но и ваши советы проанализирую. Итак. На базе вышеприведенного кода я сделал почти 2 десятка МИДИ устройств за 3 года. И, для любительских задач "1\600" ошибка приемлима. Но, сейчас хотел бы все таки решить этот косяк. Ибо в профоборудовании его не наблюдаю. Кабели те же. Другое железо попробовать? МК есть PIC STM  и т.п. Может вообще на AVR нет позитивных результатов ни у кого? Но тогда возникает вопрос об сравнимости "условий" эксперимента. Одно дело компьютерщик-музканант тыкает мышкой на компе, набирая по-нотке. Другое - сцена и игра 10 пальцами, кулаками, и еще и ногами и головой (как я). Тут поток сообщений гораздо выше.  Идея: нужно создать тестовый генератор МИДИ последовательностей с регулируемым периодом посыла. И получить функцию "ошибка от периода". А сейчас все идет так: барабаню на клавишах ахинею, - "чем быстрее и больше - тем более вероятна ошибка". И жду, когда она появится.. А она непредсказуема((( Но если появляется - то это конфуз на сцене.... Вот так. Это эмоции))). Далее. Я вообще не могу найти алгоритмов как сделано подобное в проф.девайсах. ПОэтому - все - "от любительского опыта".  Потом выложу код, что "разбор" 3-х байтов (определение стартового = "некого "пакета") и прочее я делаю ПОСЛЕ выхода из п\п уарта. Вы пИшите, что можно сделать его в самой п\п. Это мне нужно понять))) Тут надо оценить и вложенность прерываний, что я пока не анализировал. А мысль, что пока попробовать вообще опросом бита регистра - вообще нова до нельзя!  

Edited by dim3740

Share this post


Link to post
Share on other sites

1.

        rx_buffer[indexW]=UDR;                  indexW++;                    if (indexW>=Max)  indexW=0;                   Count++;                  if (Count>Max)  Count=0; 

Почему вы обнуляете кол-во данных при переполнении?

2. у вас не синхронизирован прием и чтение из данного буфер

 

Читайте про кольцевой буфер.

Если вы читали, значит поняли что тоне так

Share this post


Link to post
Share on other sites

@hasl пример слизал отсюда...http://www.proavr.narod.ru/z5.htm и приложил скрин фрагмента.

А синхронизация, имхо, как раз не нужна... на то и буфер. Хотя, думаю, что под синхро вы имели что-то другое. Скажу тогда, что игра на пианино имеет "паузы", и опорожнение буфера будет всегда. Да, код НЕ универсален, но я хочу делать то, что нужно именно в конкретном случае по ТЗ.

И еще: как объяснить, что на 99% код работает? 

 

 

пример.jpg

Edited by dim3740

Share this post


Link to post
Share on other sites

1. на заборе много что пишут

2.Слизав не разобравшись - от сюда ошибки

 

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

т.е. фактически данные были но вы их как бы не видите

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

Еще раз говорю, код кольцевого буфера не корректный

Share this post


Link to post
Share on other sites

Я не только слизал с весьма авторитетного источника, но и разобрался в меру своего опыта. Ваша мысль про размер буфера понятна и принята. Конечно, если приемник НЕ ГОТОВ по скорости принять инфу, то буфер переполнится. Но... мой приемник - это не более, как... скажем, громкоговоритель. Там нет никаких других процессов, кроме чтения. Синтезатор, который воспроизводит приемный поток свободен... на нем никто не играет (в отличие от синтезатора- источника). Поэтому в МОЕМ случае, имхо, ошибка никак не связана с размером буфера. Я пробовал кольцевой ставить всего 2 (и то успевает) , а пробовал 1000, ибо памяти мне не жалко. Эффект одинаковый. Т.е. сбой есть, но редкий.

Edited by dim3740

Share this post


Link to post
Share on other sites

. сделайте размер буфера 1 и посмотрите, что будет

11 минуту назад, dim3740 сказал:

с весьма авторитетного источника,

LOL

авторитетные источники н-и-к-а-д-а не пишут статей, они пишут DataSheet & userManual но  и там косяков хватает

Edited by hasl

Share this post


Link to post
Share on other sites

Ну это для меня авторитетные они))) Сделал 1, т.е. фактически это один байт стал [0] , тоже работает на вскидку. Сбой, как всегда, после пары минут интенсивной игры...... Это все не дело)))) . я точно понял, что надо писать тестовый генератор (как писал выше), чем сейчас и занимаюсь на C#.  Но это не просто, потому что надо тогда и МИДИ входной порт аппаратно задействовать.  Но имхо тут все же мне помогут)))) На форуме программистов вообще МК не хотят заниматься(((( 

Share this post


Link to post
Share on other sites

Выкиньте этот Count, он тут и даром не нужен. Проверка новых байтов просто по неравенству indexR и indexW:

while(1)
{
    if (indexR !=  indexW) 
    {
        tempMessage=rx_bufferR[indexR];  
        MesComplite(tempMessage); //тут анализ каждого считанного байта. Это занимает время 
        indexR++;  
        if (indexR>=Max)  indexR=0; 
    }
}
ISR(USART_RXC_vect)  
{
    if (UCSRA & (1<<7))   
    {
        rx_buffer[indexW]=UDR;
        indexW++;  
        if (indexW>=Max)  indexW=0;
    }
}

 

Share this post


Link to post
Share on other sites

а MAX вы тоже сделали 1?

я больше скажу

сделав размер массива = 1, но оставив МАХ=100 вы портите память, т.е. если за массивом будут стоять еще переменными, вот будет веселуха

программирование МК на чистом Си не в тапки ссать, это не када за вас все проверяет VS.

В 16.09.2017 в 08:51, dim3740 сказал:

            Count--;             sei(); //разрешение                          if (Count>=Max)  Count=0;

вот здесь еще веселее

вычитая вы сравниваете на макс. 

 

выше вам дали рабочий пример

Edited by hasl

Share this post


Link to post
Share on other sites
11 hours ago, dim3740 said:

Это не страшно)) Главное, что Вы не пытаетесь учить меня профкодированию, а согласны подойти к проблеме обобщенно.

Если обобщенно, сбоить может или физический уровень (на уровне сигналов), или логический (на уровне софта). Или оба сразу, тогда и профи с ума сойдут.

Quote

 temp=UDR  и сразу UDR=temp. 

Если на отправку битрейт такой же (или выше) - номер катит, но неплохо бы проверить что в момент записи нового байта uart не занят отсылкой предыдущего байта (по флагам, у атмела это бит TxC, чтоли). Отправка в провод не моментальна, если вы придете с новым байтом в процессе отправки прошлого - ничего хорошего не выйдет.

11 hours ago, dim3740 said:

Я также сейчас выдаю все "от печки", по сути задачи в целом, но и ваши советы проанализирую. Итак. На базе вышеприведенного кода я сделал почти 2 десятка МИДИ устройств за 3 года. И, для любительских задач "1\600" ошибка приемлима. Но, сейчас хотел бы все таки решить этот косяк. Ибо в профоборудовании его не наблюдаю. Кабели те же.

У вас свой физический уровень и софт. Сбоить могут оба. В профоборудовании инженеры делали правильно и то и другое. UART не очень помехоустойчив. По ссылочке которую я дал советуют опторазвязку для MIDI. Соединение устройств с разными сетевыми источниками питания может подкинуть сюрпризов из-за текущих по линиям токов которые вы не заказывали. В случае UART при этом может приняться хрен знает чего.

11 hours ago, dim3740 said:

Другое железо попробовать? МК есть PIC STM  и т.п. Может вообще на AVR нет позитивных результатов ни у кого?

Не думаю что проблема в AVR, с такими проблемами в чипе производители долго не живут. PIC после AVR врядли понравится, разве что PIC32. STM? STM32 крутые и веселые, могут в разы больше, даже те что дешевле. Но НАМНОГО навернутее. Такое там можно на DMA выгрузить - DMA сам будет байты таскать. Но это имеет смысл лишь при ОЧЕНЬ больших потоках, DMA все-равно надо программить а промашки в нем чреваты. К тому же STM32-ы 3.3V-only, в миди как я понимаю 5V в почете, в "электрике" добавится костылей. В общем avr как мне кажется достаточно сбалансированный выбор, если возможностей хватает.

На лично мое мнение я бы проверил "физику" на безглючность в жестких условиях (типа сцены) и если вы хотите продвинутости типа irq и кольцевого буфера, их придется сделать нормально. Разобравшись как это работает и что реально происходит в системе. Вообще отгрохать такую штуку для любителя - неслабо. Если нормально работает :)

11 hours ago, dim3740 said:

Но тогда возникает вопрос об сравнимости "условий" эксперимента. Одно дело компьютерщик-музканант тыкает мышкой на компе, набирая по-нотке. Другое - сцена и игра 10 пальцами, кулаками, и еще и ногами и головой (как я). Тут поток сообщений гораздо выше.

А еще на сцене чего доброго провода длиннее и какая-нибудь силовуха рядом...

11 hours ago, dim3740 said:

 Идея: нужно создать тестовый генератор МИДИ последовательностей с регулируемым периодом посыла. И получить функцию "ошибка от периода".

Можно с второго микроконтроллера послать, хоть в цикле из main без всяких IRQ, конструкцией в духе while (TxC показывает что Tx не занят) {UDR = чтонибудь}. Получите очень плотный поток данных ограниченный только битрейтом. Быстрее некуда. Можно его проредить, воткнув задержки.

11 hours ago, dim3740 said:

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

Это то понятно, но специалисты от любителей отличаются как раз тем что стараются не халтурить, зная что за это потом воздастся массой неочевидных проблем. А кроме того они в курсе типовых проблем из своей области, что спасает их от массы провалов. Подозрительные места которые не понравились мне я и озвучил, не знаю насколько получилось.

11 hours ago, dim3740 said:

Далее. Я вообще не могу найти алгоритмов как сделано подобное в проф.девайсах. ПОэтому - все - "от любительского опыта".  Потом выложу код, что "разбор" 3-х байтов (определение стартового = "некого "пакета") и прочее я делаю ПОСЛЕ выхода из п\п уарта. Вы пИшите, что можно сделать его в самой п\п. Это мне нужно понять))) Тут надо оценить и вложенность прерываний, что я пока не анализировал. А мысль, что пока попробовать вообще опросом бита регистра - вообще нова до нельзя!  

Я имел в виду "машины состояний". Когда есть состояния протокола и переходы между ними по неким правилам. Можно в виде диаграммы разрисовать. Обработчик IRQ может смотреть на состояния и даже менять их, если это быстро. Зачем? В лучшем случае фоновая программа может получать относительно готовый пакет и неспешно жевать в фоне, не озадачиваясь как он взялся. Но для миди это наверное не пойдет.

И да, из irq надо вываливаться быстро. Но быстро и мгновенно разные вещи. До того как будет новый такой же IRQ, пройдет минимум 32 мкс. Можно посчитать сколько команд проц выполнит за это время зная частоту (порядка сотен или даже тысяч). Есть еще расходы на сохранение состояния фона при входе в irq и возврат проца в вид как было при выходе, а еще времени должно остаться фону и irq других железок (если они используются).

Вложенные IRQ от одной железки - показатель что вы зашились и не успеваете за реальным временем. Нафиг. Фоновая программа при этом встрянет, кстати, а проц будет только вертеться на прерывания. Поэтому прерывания должны завершаться как можно быстрее и их не должно валиться слишком много. У вас максимум 3125 irq в секунду от uart, на частотах близких к максимуму это вполне ок. Много логики я бы в irq при этом не засовывал.

Share this post


Link to post
Share on other sites

Спасибо. Займусь на выходных...пока занят((( Вот из спецификации по приему МИДИ фрагмент:

2017-09-20 19 17 17.jpg

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Сообщения


  • 3D принтер Flyingbear-Ghost 5

  • Similar Content

    • Guest NickL
      By Guest NickL
      Всем привет.
      Имеется датчик давления под управлением микрухи MLX90308. Микруха сия собирает показания с 4-х включенных мостом тензометрических датчиков, и отдает обработанное значение в виде аналогового сигнала. Так же есть пин для получения данных в цифре и калибровки/прошивки этой микрухи. Производитель микрухи предлагает бесплатный софт и свою отладочно-прошивочную плату (EVB90308) за 250 бакинских (дорого), которую ждать 8 недель (долго)
      Судя по докам, там обычный UART, но с другими уровнями. Логический 0 = 0.3*Uвх, т.е. 1.5в, Логическая 1 = 0.7*Uвх, т.е. 3,5в. И всё это засунуто в единственный пин и на прием и на передачу.
      Универ был давно, да и учился я плохо, подскажите пожалуйста пример схемы чтобы 1) свести tx и rx на одну ногу 2)согласовать уровни для чтения/записи сей микрухи доступными средствами. Например, FTDI.
      Даташит микрухи:
      https://www.melexis.com/-/media/files/documents/datasheets/mlx90308-datasheet-melexis.pdf
      Спасибо заранее! Это датчик из блока АБС мотоцикла, замены нет, б/у запчастей нет, а новый блок стоит как сам мотоцикл.
    • By Evgeniy90
      Здравствуйте. Проблема такая:после прошивки USBASP ноутбук перестал его определять. Ошибка в диспетчере устройств:сбой запроса дескриптора USB устройства.
      Прошивал через Arduino UNO и avrdude. Прошивку скачать с офф сайта(последнюю на сайте https://www.fischl.de/usbasp/). Все прошло успешно. Почти))
      Подскажите что можно сделать? 
    • By Дмитрий -
      На примере GSM/GPRS Goouuu Tech IOT-GA6-B и ATtiny85.
      Программа «Звонилка». 
      Программа на BASCOM-AVR. 
      Источник https://178654.blogspot.com/p/uart.html
       

    • By Viktor Golubov
      Почему может неправильно работать uart? Подключил 1 uart к пк через usb/uart переходник, а второй к gsm модему. В первый уарт вывожу инфу для дебага, а во второй AT команды. Суть в том, что сообщения для 2 уарта выводятся в 1 уарт

      и выводятся как то странно

      не полностью

      Вот такой вывод постоянно:

      Begin
      End
      AT+CNMI=2,2,0,0,0
      AT+CMGEnd
      AT+CNMI=2,2,0,0,0

      а должно быть просто

      begin

      end

      и все

      полный код https://pastebin.com/zBBZmZue
    • By IgnatiusF
      Появилась надобность в микроконтрллере STM32 для проектирования устройства. И вопрос вот в чем - в программировании этих стм-ов. Прочитал несколько статей по их программированию - что вообще для этого нужно. Выяснил, что в них (во всех?) есть вшитый bootloader, который может сам прошить МК.
      То есть для этого необходимо подключить какой-либо ...to UART преобразователь, а именно TX, RX, VCC и gnd к соответсвующим ногам микроконтроллера и все? Или надо еще куда-то подавать управляющий сигнал?
      Еще вопрос по поводу бутлоадера - если он занимает 8 КБ (или по разному?), то МК с 16 КБ памяти, по сути, будет иметь 8 КБ для программ?
      Datasheet я только начинаю читать и пока еще не нашел точной информации, так что за помощь буду очень признателен
×
×
  • Create New...