Перейти к содержанию

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


dim3740

Рекомендуемые сообщения

Читается порт 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. Какие есть иные методы повышения надежности, кроме повторной отправки при ошибке?

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

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

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

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

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 вовремя, но сколько данных до этого приедет и что в них будет - никто не обещает. И трояная посылка одного и того же байта может в этом случае не помочь.

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

Изменено пользователем guest87
Ссылка на комментарий
Поделиться на другие сайты

Сравнительное тестирование аккумуляторов EVE Energy и Samsung типоразмера 18650

Инженеры КОМПЭЛ провели сравнительное тестирование аккумуляторов EVE и Samsung популярного для бытовых и индустриальных применений типоразмера 18650. 

Для теста были выбраны аккумуляторы литий-никельмарганцевой системы: по два образца одного наименования каждого производителя – и протестированы на двух значениях тока разряда: 0,5 А и 2,5 А. Испытания проводились в нормальных условиях на электронной нагрузке EBD-USB от ZKEtech, а зарядка осуществлялась от лабораторного источника питания в режиме CC+CV в соответствии с рекомендациями в даташите на определенную модель. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

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.

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

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

Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре. 

Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств. Подробнее параметры и результаты тестов новой серии PLM по ссылке.

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

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 выше, отфорвардив на комп).

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

 

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

Литиевые батарейки и аккумуляторы от мирового лидера  EVE в Компэл

Компания Компэл, официальный дистрибьютор EVE Energy, бренда №1 по производству химических источников тока (ХИТ) в мире, предлагает продукцию EVE как со склада, так и под заказ. Компания EVE широко известна в странах Европы, Америки и Юго-Восточной Азии уже более 20 лет. Недавно EVE была объявлена поставщиком новых аккумуляторных элементов круглого формата для электрических моделей «нового класса» компании BMW.

Продукция EVE предназначена для самого широкого спектра применений – от бытового до промышленного. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

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

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

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

Изменено пользователем dim3740
Ссылка на комментарий
Поделиться на другие сайты

1.

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

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

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

 

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

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

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

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

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

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

 

 

пример.jpg

Изменено пользователем dim3740
Ссылка на комментарий
Поделиться на другие сайты

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

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

 

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

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

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

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

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

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

Изменено пользователем dim3740
Ссылка на комментарий
Поделиться на другие сайты

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

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

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

LOL

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

Изменено пользователем hasl
Ссылка на комментарий
Поделиться на другие сайты

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

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

Выкиньте этот 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;
    }
}

 

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

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

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

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

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

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

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

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

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

 

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

Изменено пользователем hasl
Ссылка на комментарий
Поделиться на другие сайты

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 при этом не засовывал.

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

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

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

  Разрешено использовать не более 75 эмодзи.

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

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

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

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...