ATMega8 кварц 12Mhz

Обсуждаем контроллеры компании Atmel.
Ответить
modeler
Родился
Сообщения: 15
Зарегистрирован: Пт фев 04, 2011 22:07:03

ATMega8 кварц 12Mhz

Сообщение modeler »

Здравствуйте коллеги!
Есть один момент, который ввел меня в глубокий ступор:
ATMega8 с внешним кварцем 12Mhz, но на какой частоте она реально работает ХЗ :)
в общем фьюзы выставлены, кварц работает, осциллограф показывает на Xtal1 12МГц, НО даже вот такой незамысловатый код:

Код: Выделить всё

int main(){
   DDRC = 0b00010000; PORTC = 0b00000000;
   while(1){
      PORTC ^= 1 << 4;
      _delay_ms(5);
   }
}


приводит к странным результатам, а именно частота/период/длительность ровно в 4 РАЗА БОЛЬШЕ! :shock: причем независимо от величины задержки т.е. получается, что мега как бы работает на частоте 48МГц? :)
в принципе раньше я натыкался в attiny13 на другой эффект, но там было наоборот выходная частота была ниже в 2^x раз, но этим процессом можно было как-то управлять (сейчас уже не помню, какой-то регистр)
перерыл даташит на мегу, но каких-то вещей отвечающих за умножение не нашел да и в принципе раз USB протокол работает

вообще началось все с того что я хотел реализовать термометр типа http://eldigi.ru/articles/usb_termometr и прикол в том что
готовая прошивка залитая в МК работает, но когда я сам компилирую прошивку из проекта то получается хрень, т.е. прога не работает, стал разбираться и оказалось что все сигналы (в данном случае критические) на датчик идут с большей частотой
причем, в плане USB все как ни странно исправно работает в обоих прошивках. в результате создал новый проект с кодом который привел выше - таже хрень. очевидно что МК не может работать на такой частоте, т.е. видимо косяк где-то в самом delay, возможно что по какой-то неизвестной мне причине компилятор "думает" что выбран более медленный режим работы мк (получается 3МГц) и исходя из этих данных и генерируется другая меньшая (в 4 раза) задержка, только вот не могу понять причину такого поведения компилятора...
насколько я понимаю на delay влияют несколько факторов: тип/модель мк (могут быть специфичные асембленые костыли), частота (F_CPU=12000000) и собственно сам генератор (в данном случае кварц 12МГЦ)

может кто сталкивался и наступал уже на эти грабли?
Аватара пользователя
Mishany
Электрический кот
Сообщения: 1031
Зарегистрирован: Чт июн 20, 2013 00:00:58
Откуда: москва, м.Сходненская

Re: ATMega8 кварц 12Mhz

Сообщение Mishany »

a в чем пишете?
по тому кусочку проги трудно что либо посоветовать.
для правильной работы delay много чего надо прописать...
либо кварц брак, либо fuse, как говориться чудес не бывает
vdavid
Мучитель микросхем
Сообщения: 410
Зарегистрирован: Чт ноя 13, 2008 16:33:42

Re: ATMega8 кварц 12Mhz

Сообщение vdavid »

modeler, Это студия? Там в тулчейне есть известный баг в delay.h. В WinAvr его нет.
Почитайте, например, здесь http://www.avrfreaks.net/forum/bug-avr-lib-delayfunc?name=PNphpBB2&file=viewtopic&t=100131.
Попробуйте сделать вот это:
#define __DELAY_BACKWARD_COMPATIBLE__
modeler
Родился
Сообщения: 15
Зарегистрирован: Пт фев 04, 2011 22:07:03

Re: ATMega8 кварц 12Mhz

Сообщение modeler »

да это 4-ая студия с тулчейном, недавно скачал 6-ую но пока не установил.
а что вообще посоветуете, что лучше для разработки под авр на си?

#define __DELAY_BACKWARD_COMPATIBLE__ - не поможет хоты бы потому что нигде в файлах тулчейна не встречается
vdavid
Мучитель микросхем
Сообщения: 410
Зарегистрирован: Чт ноя 13, 2008 16:33:42

Re: ATMega8 кварц 12Mhz

Сообщение vdavid »

Ну не знаю. У меня нет тулчейна. Я пользуюсь WinAvr. На AvrFreaks советуют еще такое:
#define __HAS_DELAY_CYCLES 0
Скачал AVR Toolchain 3.3.0. __DELAY_BACKWARD_COMPATIBLE__ встречается в delay.h неоднократно.
modeler
Родился
Сообщения: 15
Зарегистрирован: Пт фев 04, 2011 22:07:03

Re: ATMega8 кварц 12Mhz

Сообщение modeler »

Код: Выделить всё

int main(){
   DDRC = 0b00010000; PORTC = 0b00000000;
  38:   80 e1          ldi   r24, 0x10   ; 16
  3a:   84 bb          out   0x14, r24   ; 20
  3c:   15 ba          out   0x15, r1   ; 21
   while(1){
      PORTC ^= 1 << 4;
  3e:   90 e1          ldi   r25, 0x10   ; 16
  40:   85 b3          in   r24, 0x15   ; 21
  42:   89 27          eor   r24, r25
  44:   85 bb          out   0x15, r24   ; 21
{
   uint16_t __ticks;
   double __tmp = ((F_CPU) / 4e3) * __ms;
#if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__)
   extern void __builtin_avr_delay_cycles(unsigned long);
   __builtin_avr_delay_cycles(__tmp);
  46:   e5 ea          ldi   r30, 0xA5   ; 165
  48:   fe e0          ldi   r31, 0x0E   ; 14
  4a:   31 97          sbiw   r30, 0x01   ; 1
  4c:   f1 f7          brne   .-4         ; 0x4a <__SREG__+0xb>
  4e:   00 c0          rjmp   .+0         ; 0x50 <__SREG__+0x11>
  50:   00 00          nop
  52:   f6 cf          rjmp   .-20        ; 0x40 <__SREG__+0x1>

00000054 <_exit>:
  54:   f8 94          cli

00000056 <__stop_program>:
  56:   ff cf          rjmp   .-2         ; 0x56 <__stop_program>


вот во что разворачивается сишный код и судя по нему баг находится в глубинах __builtin_avr_delay_cycles, т.е. иными словами на данном тулчейне получить вменяемый delay не судьба!? кто так пишет!? :)

UPD: в общем немного покумекав подшаманил код util/delay.h (AVR studio 4.18 build 716 toolchain/arv-libc 1.7.0)
знаю, что возможно не самое лучшее решение, но зато без дополнительных заморочек в каждом проекте, а то пройдет год про баг забудешь и снова на те же грабли по второму разу наступишь :(

было:

Код: Выделить всё

void
_delay_ms(double __ms)
{
   uint16_t __ticks;
[color=#FF0000]   double __tmp = ((F_CPU) / 4e3) * __ms;[/color]
#if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__)
   extern void __builtin_avr_delay_cycles(unsigned long);
   __builtin_avr_delay_cycles(__tmp);
#else
   if (__tmp < 1.0)
      __ticks = 1;
   else if (__tmp > 65535)
   {
      //   __ticks = requested delay in 1/10 ms
      __ticks = (uint16_t) (__ms * 10.0);
      while(__ticks)
      {
         // wait 1/10 ms
         _delay_loop_2(((F_CPU) / 4e3) / 10);
         __ticks --;
      }
      return;
   }
   else
      __ticks = (uint16_t)__tmp;
   _delay_loop_2(__ticks);
#endif
}

void
_delay_us(double __us)
{
   uint8_t __ticks;
[color=#FF0000]   double __tmp = ((F_CPU) / 3e6) * __us;[/color]
#if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__)
   extern void __builtin_avr_delay_cycles(unsigned long);
   __builtin_avr_delay_cycles(__tmp);
#else
   if (__tmp < 1.0)
      __ticks = 1;
   else if (__tmp > 255)
   {
      _delay_ms(__us / 1000.0);
      return;
   }
   else
      __ticks = (uint8_t)__tmp;
   _delay_loop_1(__ticks);
#endif
}



стало:

Код: Выделить всё

void
_delay_ms(double __ms)
{
   uint16_t __ticks;
#if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__)
[color=#FF0000]   double __tmp = ((F_CPU) / 1e3) * __ms;[/color]
   extern void __builtin_avr_delay_cycles(unsigned long);
   __builtin_avr_delay_cycles(__tmp);
#else
[color=#FF0000]   double __tmp = ((F_CPU) / 4e3) * __ms;[/color]
   if (__tmp < 1.0)
      __ticks = 1;
   else if (__tmp > 65535)
   {
      //   __ticks = requested delay in 1/10 ms
      __ticks = (uint16_t) (__ms * 10.0);
      while(__ticks)
      {
         // wait 1/10 ms
         _delay_loop_2(((F_CPU) / 4e3) / 10);
         __ticks --;
      }
      return;
   }
   else
      __ticks = (uint16_t)__tmp;
   _delay_loop_2(__ticks);
#endif
}

void
_delay_us(double __us)
{
   uint8_t __ticks;
#if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__)
[color=#FF0000]   double __tmp = ((F_CPU) / 1e6) * __us;
[/color]   extern void __builtin_avr_delay_cycles(unsigned long);
   __builtin_avr_delay_cycles(__tmp);
#else
[color=#FF0000]   double __tmp = ((F_CPU) / 3e6) * __us;[/color]
   if (__tmp < 1.0)
      __ticks = 1;
   else if (__tmp > 255)
   {
      _delay_ms(__us / 1000.0);
      return;
   }
   else
      __ticks = (uint8_t)__tmp;
   _delay_loop_1(__ticks);
#endif
}


да как оказалось в _delay_us тоже баг, только длительность меньше не в 4 раза, а всего лишь в 3 :)
modeler
Родился
Сообщения: 15
Зарегистрирован: Пт фев 04, 2011 22:07:03

Re: ATMega8 кварц 12Mhz

Сообщение modeler »

UPS: что-то выделение цветом в коде не сработало :(
в общем суть в том, что раз при #define __HAS_DELAY_CYCLES 0 задержка становится нормальной, стало быть нужно изменить вычисление __tmp в зависимости от условия


vdavid писал(а):Ну не знаю. У меня нет тулчейна. Я пользуюсь WinAvr. На AvrFreaks советуют еще такое:
#define __HAS_DELAY_CYCLES 0
Скачал AVR Toolchain 3.3.0. __DELAY_BACKWARD_COMPATIBLE__ встречается в delay.h неоднократно.


да вполне возможно что за 4 года :) они все таки пофиксили этот огроменный баг сравнимый с настоящей диверсией, но к сожалению я не готов к такому радикальному изменению/обновлению :)

да это #define __HAS_DELAY_CYCLES 0 я тоже попробовал после чего пришел в выводу в предыдущем посте, т.к. это тоже не совсем панацея, не будешь же в каждом проекте менять эту хрень да и забыть очень легко и просто... если уж я использую _delay_ms/_delay_us и подключаю util/delay.h, то он должен работать как delay а не как фишка ляжет!
vdavid
Мучитель микросхем
Сообщения: 410
Зарегистрирован: Чт ноя 13, 2008 16:33:42

Re: ATMega8 кварц 12Mhz

Сообщение vdavid »

Да тулчейн 3.3.0 (который я смотрел) шел со студией 4.19 еще в 2011 году. А дефайн для __HAS_DELAY_CYCLES никто Вам не мешает воткнуть прямо в delay.h.
modeler
Родился
Сообщения: 15
Зарегистрирован: Пт фев 04, 2011 22:07:03

Re: ATMega8 кварц 12Mhz

Сообщение modeler »

да, но IMHO я сделал лучше, т.к в зависимости от настроек проекта и опций компилятора по части оптимизации будет использоваться тот вариант который лучше (по задумке авторов тулчейна)
вообще честно говоря не понятна мотивация авторов по поводу разделения кода, т.е. если есть __builtin_avr_delay_cycles на кой надо было городить огород с кривым забором :)
причем как я понял использование delay требует включение оптимизации иначе они ничего не гарантируют :)
как в прочем и в том случае когда значение задержки меняется по ходу выполнения рпограммы
Аватара пользователя
ua1arn
Встал на лапы
Сообщения: 81
Зарегистрирован: Вт май 08, 2012 23:15:45
Откуда: Санкт - Петербург

Re: ATMega8 кварц 12Mhz

Сообщение ua1arn »

на delay влияют несколько факторов: тип/модель мк (могут быть специфичные асембленые костыли), частота (F_CPU=12000000) и собственно сам генератор (в данном случае кварц 12МГЦ)

Ещё влияет уровень оптимизации. Поставьте -Os - и задержки станут соответствовать. У меня так предупреждение выдавалось при компиляции.
Ответить

Вернуться в «AVR»