2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу 1, 2  След.
 
 Странное поведение fuses в atmega8a
Сообщение23.04.2025, 17:52 


15/12/22
224
МК работает с внешним кристаллом 16МГц, судя по мануалу это максимальная частота, на которой он надёжно работает. Следуя рекомендациям, для надёжной работы на высокой частоте, выставляю CKOPT=0, что должно увеличивать мощность генератора.
Однако с этой опцией МК не запускается. Если же поставить CKOPT=1, то он работает как нужно, тактовая частота 16 МГц, никаких сбоев.
В чём тут может быть проблема?

 Профиль  
                  
 
 Posted automatically
Сообщение24.04.2025, 10:57 
Админ форума


02/02/19
2949
 i  Тема перемещена из форума «Механика и Техника» в форум «Hardware»
Причина переноса: в более подходящий раздел.

 Профиль  
                  
 
 Re: Странное поведение fuses в atmega8a
Сообщение24.04.2025, 11:20 
Заслуженный участник


20/08/14
12107
Россия, Москва
CKOPT меняет не мощность (это побочный эффект), а размах выходного сигнала XTAL2. Для тех кварцев, которые нестабильно возбуждаются малым сигналом (т.е. на вход XTAL1 приходит слишком малый размах сигнала для его переключения). Иногда рекомендуют шунтировать кварц резистором порядка мегаома, что увеличивает размах входного сигнала.
С другой стороны, при слишком сильном сигнале возбуждения (тем более прямоугольником вместо близкого к синусу) кварц может сбиться и например завестись на высших гармониках - а это уже mega никак не потянет.
Ткнитесь осцилом в XTAL2 (не XTAL1, там осцил своей ёмкостью запросто собьёт генерацию) и посмотрите на частоту сигнала.
Ну и разумеется проверить CKSEL и SUT.
Да, и надеюсь питание 5В и фронт его нарастания до этого значения меньше указанного в SUT, а то бывают знаете ли случаи, поставят десятки тысяч мкФ от маломощного источника питания и удивляются чего это ничего не запускается ...

 Профиль  
                  
 
 Re: Странное поведение fuses в atmega8a
Сообщение24.04.2025, 14:01 


15/12/22
224
Dmitriy40 в сообщении #1683559 писал(а):
Да, и надеюсь питание 5В

питание 3.3V atmega8A должен нормально работать при таком напряжении на 16 МГц, он в общем то и работает, но почему то только с CKOPT=1, а не наоборот

 Профиль  
                  
 
 Re: Странное поведение fuses в atmega8a
Сообщение24.04.2025, 14:42 
Заслуженный участник


20/08/14
12107
Россия, Москва
Missir в сообщении #1683592 писал(а):
питание 3.3V atmega8A должен нормально работать при таком напряжении на 16 МГц,
Не должен, 16МГц гарантируются лишь для напряжений выше 4.5В. Смотрите Figure 26-1 на странице 234 pdf на мегу. При 3.3В гарантированный максимум лишь $\dfrac{16-8}{4.5-2.7}(3.3-2.7)+8=10.67$МГц.
Соответственно всё что у Вас происходит - недокументировано и никакое поведение не может считаться неправильным (или правильным, без разницы). Может происходить вообще что угодно. Может работать, может не работать, может работать только по средам, и так далее.
Да, многие кристаллы работают. Но никогда нет уверенности что заработает каждый следующий кристалл, или что данный конкретный продолжит работать завтра или в других условиях (скажем температура изменится). Пока не провели масштабные тесты - не используйте изделия вне документированных границ.
Максимум на что можно относительно безопасно их раздвинуть - 5%-10% (обычный допуск на дискретные компоненты и на точность напряжений). И то, придётся максимально снизить влияние всех других факторов нестабильности.
Короче ничего особо странного в поведении меги нет. Странное поведение скорее у Вас - использовать изделие вне пределов его работоспособности. ;-)

Что же до причины про CKOPT, я склоняюсь к версии запуска кварца на более высокой гармонике от слишком прямоугольного сигнала возбуждения. Но версия так себе, даже не 80% уверенности. Просто других вменяемых не вижу.
Кстати сгладить сигнал XTAL2 можно по идее нагрузочными кондёрами, которые 12-18пФ об землю, можно добавить скажем до пары сотен пФ и посмотреть не улучшит ли это. Будет ли кварцу от этого легче - без понятия, не настолько знаю радиоэлектронику. Или можно между кварцем и XTAL2 включить резистор, сотни Ом (посчитать по ёмкости чтобы частота среза была незначительно выше рабочей частоты, но и в десятки кОм не уходить, у меня выходит порядка 500Ом), это тоже сгладит сигнал возбуждения кварцу и подавит высшие гармоники.

 Профиль  
                  
 
 Re: Странное поведение fuses в atmega8a
Сообщение24.04.2025, 14:51 


15/12/22
224
Понятно, значит такой кварц не годится, работает просто случайно, ставить нужно на 8 МГц, может тогда всё и заработает как положено.

 Профиль  
                  
 
 Re: Странное поведение fuses в atmega8a
Сообщение24.04.2025, 16:35 


15/12/22
224
Dmitriy40
пользуясь случаем хотелось бы у Вас спросить, не знаете случайно, почему после прошивки МК все фьюзы устанавливаются по дефолту?
Прошиваю я так:
Код:
minipro -p ${MCU} -z -w ${TARGET}.hex -c code

приходится сначала считывать установленные значения
Код:
minipro -p ${MCU} -r fuses.conf -c config

а потом снова их же и записывать
Код:
minipro -p ${MCU} -u -e -w fuses.conf -c config

как сделать, чтобы после прошивки фьюзы оставались какими и были?

 Профиль  
                  
 
 Re: Странное поведение fuses в atmega8a
Сообщение24.04.2025, 16:49 
Заслуженный участник


20/08/14
12107
Россия, Москва
Можно и на 10МГц, и даже в общем на 11МГц.
А на 16МГц работает потому что обычно есть большой запас, а тут нужен всего 16/10.67=1.5 раза, это конечно много, но значит хватает надежности чтобы работать. Но не во всём. Границы то гарантированы, а не просто "работает или не работает". Вот эта гарантия и даёт запас, ведь в нём учитываются и колебания температуры, влажности, погрешностей производства.
Просто при использовании вне гарантированной области всегда можно неожиданно напороться на странное поведение, заранее неизвестно где.

(Оффтоп)

Вот например у меня меги (другие, сотни штук) не всегда шьются по ISP при 3.3В, хотя повышалка же внутренняя и по идее должны шиться, ан нет, процентов до 20 шьются лишь со второго раза (стёр, прошил, проверил, беда, стёр, прошил, проверил, ок), или на низкой частоте SPI (хотя от неё прошивка вообще зависеть не должна), а у некоторых (процентов 10) всё шьётся хорошо кроме fuses защиты, они не выставляются с первого раза, повторишь раза два-три-пять только прошивку их - и встают. И это в пределах допустимых условий, а вы хотите вне их ...

Missir в сообщении #1683609 писал(а):
пользуясь случаем хотелось бы у Вас спросить, не знаете случайно, почему после прошивки МК все фьюзы устанавливаются по дефолту?
Тут не подскажу, у меня нет minipro, я шью обычно гальванически развязанным программатором (у которого свои глюки).
Посмотрите на доку к minipro по командам, может он при этом выставляет и fuses в стандартные значения.

 Профиль  
                  
 
 Re: Странное поведение fuses в atmega8a
Сообщение25.04.2025, 02:10 


15/12/22
224
Dmitriy40
не могли бы Вы ещё ответить на вопрос, дело в том, что как впоследствии выяснилось, через некоторое время программа зависает.
Данные перестают поступать по UART в ПК. Они передаются из обработчик прерывания INT0, в котором считываются по I2C. Прерывания генерирует устройство по готовности данных. Чтобы исключить многие вопросы, я поставил _delay_ms(20) и отправку символа "A" по UART в основном цикле. В начале обработчика прерываний поставил отправку по UART символа "I".
В общем символы "A" пока всё работает появляются редко, т.е. программа почти всё время проводит в обработчике.
Потом, когда всё "замирает" никаких символов нет вообще.
По идее, если устройство перестаёт посылать прерывания, то должен работать основной цикл и пойти одни символы "A", но их нет.
Если какая то ошибка в обработчике, то должны пойти символы "I", но их тоже нет.

Внутри обработчика зависнут особо нечему, он вот такой:
код: [ скачать ] [ спрятать ]
Используется синтаксис C

ISR(INT0_vect)
{  send_uart('I');
   if (start_i2c())
   {  if (send_i2c(GY521<<1, 0x18))  
         if (send_i2c(0x3B, 0x28))    
           if (start_i2c())
             if (send_i2c((GY521<<1)|0x01, 0x40))
             {
                 for (int i=0; i<6; i++) {val[i]=(rec_i2c(1)<<8); val[i]|=rec_i2c(1);}
                 val[6]=(rec_i2c(1)<<8); val[6]|=rec_i2c(0);
                 
                 for (int i=0; i<7; i++) mv[i]+=val[i]; st++;
                 
                 if (st==512)
                 {
                   for (int i=0; i<7; i++)
                   { x=mv[i]/st; mv[i]=0;
                     if (x<0) {ch[0]='-'; x*=(-1);} else ch[0]='+';
                     send_uart(' '); send_uart(' '); send_uart(' ');
                     for (int i=6; i>0; i--) {ch[i]=(x%10)+48; x/=10;}
                     for (int i=0; i<7; i++) send_uart(ch[i]);
                     send_uart(' '); send_uart(' '); send_uart(' ');
                     
                    }
                    send_uart('\r'); st=0;
                  }
                 
             }
       TWCR=(1<<TWINT) | (1<<TWEN) | (1<<TWSTO);  // STOP i2c
   }
 }
 


в чём тогда может быть дело? может что не так с UART (там используется FT232), или может _delay_ms() как то конфликтует с прерыванием?

Вообще работает долго, минут 30 и больше, а потом зависает. Если включить/выключить питание, начинает работать, похоже дело всё таки не в FT232

 Профиль  
                  
 
 Re: Странное поведение fuses в atmega8a
Сообщение25.04.2025, 14:44 
Заслуженный участник


20/08/14
12107
Россия, Москва
Missir в сообщении #1683670 писал(а):
через некоторое время программа зависает.
Вполне обычное явление при переразгоне, в данном случае меги.
Missir в сообщении #1683670 писал(а):
По идее, если устройство перестаёт посылать прерывания, то должен работать основной цикл
Не должен. Зависание может быть совершенно произвольным, вплоть до просто останова внутреннего тактирования счётчика команд и остановки выборки команд из флеш.
Вообще, на процесс "сбой" не даётся вообще никаких гарантий, никаких! Он может проходить как угодно. И каждый раз по разному. Любые гарантии даются только на нормальную работу.
Missir в сообщении #1683670 писал(а):
Внутри обработчика зависнут особо нечему,
Зависнуть может на абсолютно любой команде. Не забывайте что команды могут просто некорректно считываться из флеш и попадать в ядро avr уже кривыми (вполне вероятная причина сбоев). При нестабильной работе может быть ЧТО УГОДНО. Ну, мега конечно ИИ не породит и в космос не улетит, но вот скажем устроить внутреннее КЗ вполне может, в теории, сам не наблюдал и не слышал о таком.

 Профиль  
                  
 
 Re: Странное поведение fuses в atmega8a
Сообщение25.04.2025, 16:50 


15/12/22
224
В общем, попробовал запитать схему не прямо от FT232, а от Li-Ion, хоть напряжение такое же, но работает уже 12 часов и ни одного сбоя не было. Надо потом попробовать поставить конденсатор по питанию, чтобы удостовериться в этом дело или нет.

Dmitriy40 как Вы думаете, возможно ли ускорит обработчик прерывания? а то выходит, что кроме считывания и усреднения на МК больше ничего и не сделать ...

 Профиль  
                  
 
 Re: Странное поведение fuses в atmega8a
Сообщение25.04.2025, 17:46 
Заслуженный участник


20/08/14
12107
Россия, Москва
Missir в сообщении #1683722 писал(а):
Dmitriy40 как Вы думаете, возможно ли ускорит обработчик прерывания? а то выходит, что кроме считывания и усреднения на МЛ больше ничего и не сделать ...
Понятия не имею. Я вообще его не смотрел.
Вот вижу send_uart() - она как байт отсылает? Ждёт освобождения UART и записывает его в буфер передачи? Это разумеется плохо. Надо делать промежуточную буферизацию в памяти, чтобы она просто записывала байт в буфер (если там есть достаточно места или ждать пока оно не появится, а это максимум 100мкс), а из него по прерываниям от UART отправлялись. Размер буфера выбирается чтобы в него поместилось две строки максимально возможной длины, тогда send_uart() почти никогда не будет ждать. Но конечно будут заморочки с опустошением буфера и перезапуском процесса отсылки его по UART.
И кстати возможно будет выгодна замена преобразования чисел в строку на sprintf() и отсылка сразу готовой строки.
И у вас i2c блокируется на всё время отсылки строки, это тоже нехорошо, лучше быстро прочитать данные с i2c, освободить его, а потом уже усреднять, преобразовывать и отсылать.

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

 Профиль  
                  
 
 Re: Странное поведение fuses в atmega8a
Сообщение25.04.2025, 20:16 


15/12/22
224
Dmitriy40 в сообщении #1683727 писал(а):
Вот вижу send_uart() - она как байт отсылает? Ждёт освобождения UART и записывает его в буфер передачи?

да, вот так
Используется синтаксис C
void send_uart(char value)
{
    while( !((UCSRA >> UDRE) & 1) ) ;  
    UDR = value;
}
 


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

Как Вы думаете, в таком виде будет какое то заметное улучшение по быстродействию?
код: [ скачать ] [ спрятать ]
Используется синтаксис C
unsigned char st=0;
short hig, low, val[7]={0,0,0,0,0,0,0}, rst[7]={0,0,0,0,0,0,0};
.........................

ISR(INT0_vect)
{
   if (start_i2c())
   {  if (send_i2c(GY521<<1, 0x18))   // адрес GY-521 на запись
         if (send_i2c(0x3B, 0x28))     // адрес первой ячейки памяти accel_xout_high
           if (start_i2c())
             if (send_i2c((GY521<<1)|0x01, 0x40)) // адрес GY-521 для чтения
             {
               for (int i=0; i<6; i++)
               { hig=rec_i2c(1); low=rec_i2c(1); if (hig && 0x80) rst[i]-=low; else rsti]+=low; val[i]+=hig; }
               hig=rec_i2c(1); low=rec_i2c(0); if (hig && 0x80) rst[i]-=low; else rst[i]+=low; val[i]+=hig; st++;

               TWCR=(1<<TWINT) | (1<<TWEN) | (1<<TWSTO);  // STOP i2c

               if (!st)
               { for (int i=0; i<7; i++) val[i]+=(rst[i]>>8);
                        ...................
                             PROC();
                        ...................
               for (int i=0; i<7; i++)  val[i]=0; rst[i]=0;
               }
               st=0;
             }
                 
    }
}            
 


нужно ли останавливать i2c в случае неудачного чтения?

 Профиль  
                  
 
 Re: Странное поведение fuses в atmega8a
Сообщение25.04.2025, 20:57 
Заслуженный участник


20/08/14
12107
Россия, Москва
Missir в сообщении #1683741 писал(а):
нужно ли останавливать i2c в случае неудачного чтения?
Это зависит от устройств на шине. Пока не было i2c_stop шина считается занятой, но если всем устройствам на ней это пофиг (или оно одно и по сигналу stop ничего не делает), то и пусть. Но вот например запись в устройство обычно происходит именно по получению сигнала stop, до него данные пишутся в промежуточный буфер внутри устройства (так флешки работают, и некоторые другие) и если стопа не будет, то и данные не запишутся. Но это зависит от конкретного устройства на шине.
Так весь кусок кода начиная со строки с STOP i2c можно вынести в самый конец прерывания, за все if.
А я бы вынес вообще из прерывания в основной цикл, только с арбитражен st и копированием val[] в другой массив - тогда накопление может происходить одновременно с отсылкой (или другой обработкой) предыдущих данных.

Missir в сообщении #1683741 писал(а):
Как Вы думаете, в таком виде будет какое то заметное улучшение по быстродействию?
А что изменили? Усложнили суммирование, уж наверное x*=(-1) компилятор и раньше заменял на изменение знака.
Упростить код можно если hig,low объявить как union или как два байта, в которые и читать с i2c, или как одно слово со знаком, которое и добавлять к среднему.
И кстати, если девайс выдаёт слово со знаком, то суммирование 512 их разве не вылезет за размеры слова? val[] надо бы 4-х байтным иметь, типа long.
А так особых изменений нет, по прежнему время будет в основном в i2c (ну сами прикиньте, даже на 400КГц каждый байт это 22.5мкс или аж 360 тактов на 16МГц, а тут я вижу 19 байтов, это 427мкс или 6840 тактов - уж наверное суммирование займёт на порядок меньше тактов). И от этого никак не избавиться.

 Профиль  
                  
 
 Re: Странное поведение fuses в atmega8a
Сообщение25.04.2025, 21:17 


15/12/22
224
Dmitriy40 в сообщении #1683747 писал(а):
Так весь кусок кода начиная со строки с STOP i2c можно вынести в самый конец прерывания, за все if.


вообще то так раньше и было, но Вы написали что шину желательно освобождать как можно быстрее, вот я и перенёс, хотя если STOP будет в конце, то получается намного проще. Так как лучше сделать?

Dmitriy40 в сообщении #1683747 писал(а):
А что изменили? Усложнили суммирование, уж наверное x*=(-1)

теперь нет сдвига <<8, байты суммируются по отдельности, о объединяются уже в конце, раз в 256 раз, тут вопрос что будет быстрее, сдвиг <<8 или дополнительное сложение и проверка условия if()

Dmitriy40 в сообщении #1683747 писал(а):
если девайс выдаёт слово со знаком, то суммирование 512 их разве не вылезет за размеры слова? val[] надо бы 4-х байтным иметь, типа long

не вылезает, в исходной реализации тип массива val само собой long, код ведь работает, показания верные

Dmitriy40 в сообщении #1683747 писал(а):
ну сами прикиньте, даже на 400КГц каждый байт это 22.5мкс или аж 360 тактов на 16МГц, а тут я вижу 19 байтов, это 427мкс или 6840 тактов - уж наверное суммирование займёт на порядок меньше тактов

не совсем так, данные идут непостоянно, прерывания приходят с частотой около 1 кгц. Там всего 14 байт, это 22,5*14=315мкс, т.е. 1/3 от периода. Остаётся 600мкс, в них нужно и поместиться.

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 16 ]  На страницу 1, 2  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group