ATMega8 кварц 12Mhz

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

Сообщение 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МГЦ)

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

Сообщение Mishany »

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

Сообщение vdavid »

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

Сообщение modeler »

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

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

Сообщение vdavid »

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

Сообщение 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 :)
Реклама
Родился
Сообщения: 15
Зарегистрирован: Пт фев 04, 2011 22:07:03

Сообщение 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 а не как фишка ляжет!
Мучитель микросхем
Сообщения: 410
Зарегистрирован: Чт ноя 13, 2008 16:33:42

Сообщение vdavid »

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

Сообщение modeler »

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

Сообщение ua1arn »

на delay влияют несколько факторов: тип/модель мк (могут быть специфичные асембленые костыли), частота (F_CPU=12000000) и собственно сам генератор (в данном случае кварц 12МГЦ)
Ещё влияет уровень оптимизации. Поставьте -Os - и задержки станут соответствовать. У меня так предупреждение выдавалось при компиляции.
Ответить

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