Внимание!!! Баг контроллера!

Обсуждаем контроллеры компании Atmel.
Ответить
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница

Сообщение urry »

Я, конечно, извиняюсь, но раз там все до тактов рассчитано - вы учитываете время входа в прерывание ?
Ведь таймер в это время тикает.
И может быть ситуация, что к тому времени, когда все уже считано и собираетесь вернуться внутрь, поступает новый запрос от таймера - и оно там так и висит в том прерывании.
Контактная информация:
Реклама
Вымогатель припоя
Аватара пользователя
Сообщения: 577
Зарегистрирован: Ср июн 19, 2013 08:10:48
Откуда: Москва, СПб, Липецк, Рязань

Сообщение ИС-пытатель »

Итак, код СИ:

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


#include <stdio.h>
#include <avr\interrupt.h>

volatile unsigned char counter = 0, counter2 = 0; // можно int, long
volatile unsigned int adc_data = 0;

// Timer 0 по совпадению с регистром сравнения А
ISR(TIMER0_COMPA_vect)
{
ADCSRA |= (1<<ADSC);
}

// ADC по готовности результата
ISR(ADC_vect)
{
adc_data = ADCW; // получает результат 1 раз. выдает постоянно только его
PORTA = adc_data; // (для контроля изменений результата измерения - будет отображать только первое измеренное значение)
counter++;
PORTB = counter; // Отображает младший байт счетчика. (0x01, значение не меняется)
}

int main (void)
{
	
// Инициализация
{ 
// Скобка, чтобы можно было свернуть и не мозолило глаза

// Предделитель тактовой частоты - 8
// CLKPR=0x80;
asm ("push r20"); // Предварительно сохраняем регистр. Но обычно студия его не использует
asm ("ldi r20, 0x80");
asm ("sts 0x61, r20");
//CLKPR=0x03;
asm ("ldi r20, 3");
asm ("sts 0x61, r20");
asm ("pop r20"); // Загружаем обратно в регистр его исходное значение
// сделано через ассемблер потому, что на низких уровнях оптимизации бывает после первой команды 
// проходит более 4 тактов и предделитель не устанавливается

// Отключаем сторожевой таймер
asm ("eor r1,r1"); // очистка регистра r1. Ни на что не влияет. студия всегда держит в нем 0
MCUCR = 0; //сброс флагов регистра (необходим для отключения стор. таймера) (см. даташит)
asm ("wdr");
WDTCSR |= 0b11000; // собственно, отключение стор. таймера (фузы установлены "как надо") ;)
asm ("sts 0x60,r1"); //WDTCSR

// Порты на выход
DDRA = 0xFF;
DDRB = 0xFF;
DDRC = 0xFF;

// Timer 0 
TCCR0A = 0b00000010; // COM0A1 | COM0A0 | COM0B1 | COM0B0 | --- | --- | WGM01 | WGM00   Режим сброс по совпадению
TCCR0B = 0b00000010; // FOC0A | FOC0B | --- | --- | WGM02 | CS02 | CS01 | CS00  Предделитель 8 (125 кГц)
TCNT0 = 0;
OCR0A = 15; // Сброс на 15 такт. деление частоты таймера на (15+1). Зона значений появления бага от 12 до 19. (если память не изменяет)
OCR0B = 0;

// Timer 0 Инициализация прерывания
TIMSK0 = 0b10; // по совпадению с А.  OCIE0B | OCIE0A | TOIE0

// Инициализация АЦП
ADMUX = 0; // REFS1 | REFS0 | ADLAR | MUX4 - MUX0   источник питания АЦП - питание контроллера,
// выравнивания вправо нет, вход ADC0 (порт PF0)
ADCSRA=0b11001011; // ADEN | ADSC | ADATE | ADIF | ADIE | ADPS2-ADPS0   вкл, первый запуск, одиночный режим, разрешить прерывания
// при установке ADATE в 1 (авто режим) баг не проявляется.

while (ADCSRA & (1<<ADIF)); //Ожидание конца первого измерения (25 тактов)
ADCSRA |= (1<<ADIF); // Сброс флага прерывания

TIFR0 = 0xFF; // Сброс флагов от таймера

}


asm ("sei"); // разрешаем прерывания

while (1) // Основной цикл программы. Выполняется всегда
{
   counter2++;
   PORTC = counter2; // Младший байт counter в порт. Также будет отображать только 0x01
}

}

Последний раз редактировалось ИС-пытатель Чт мар 13, 2014 22:09:34, всего редактировалось 2 раза.
Реклама
Вымогатель припоя
Аватара пользователя
Сообщения: 577
Зарегистрирован: Ср июн 19, 2013 08:10:48
Откуда: Москва, СПб, Липецк, Рязань

Сообщение ИС-пытатель »

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

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

+ время входа в прерывание 2-3 такта контроллера. а баг проявляется в довольно широком изменении времени срабатывания таймера (приблизительно 7 тиков. а это умноженное на предделитель таймера 8 = 7*8=56 тактов контроллера)
Мудрый кот
Аватара пользователя
Сообщения: 1811
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Сообщение Kavka »

А может вот так?

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

unsigned char counter2 = 0; // можно int, long
volatile unsigned char counter = 0;
volatile unsigned int adc_data = 0;
Добавил:

Про 2-3 такта это вы погорячились.
6.7.1
Interrupt Response Time
The interrupt execution response for all the enabled AVR interrupts is four clock cycles mini-
mum.
И учтите ещё пролог/эпилог Си-шной функции.
Последний раз редактировалось Kavka Чт мар 13, 2014 19:00:46, всего редактировалось 1 раз.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Реклама
Эиком - электронные компоненты и радиодетали
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Сообщение a_skr »

adc_data = ADCW; // получает результат 1 раз. выдает постоянно только его
Не выдает постоянно, а выдал один раз.
PORTB = counter; // Отображает младший байт счетчика. (0x01, значение не меняется)
Потому что в это прерывание больше ни разу не попали.
pps. поставьте точку останова в протеусе. Один раз попали и все. Протеус тоже баг эмулирует? ;)

ps.
PORTC = counter2; // Младший байт counter в порт. Также будет отображать только 0x01
В протеусе счетчик нормально крутится. В железе нет? :dont_know:

ppps. Запускаете АЦП чаще, чем заканчивается преобразование.
Реклама
Мудрый кот
Аватара пользователя
Сообщения: 1811
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Сообщение Kavka »

ИС-пытатель, а про SFIOR (Special FunctionIO Register) не читали? Может так будет проще запускать АЦП?
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Реклама
Вымогатель припоя
Аватара пользователя
Сообщения: 577
Зарегистрирован: Ср июн 19, 2013 08:10:48
Откуда: Москва, СПб, Липецк, Рязань

Сообщение ИС-пытатель »

Kavka писал(а):
А может вот так?
Да, конечно, волатайл! )) Забыл просто. Но это не суть. в той программе было указано. поправил

Добавил
Про 2-3 такта это вы погорячились.
6.7.1
Interrupt Response Time
The interrupt execution response for all the enabled AVR interrupts is four clock cycles mini-
mum.
И учтите ещё пролог/эпилог Си-шной функции.
я говорил без учета пролога. Именно время входа в прерывание. точно не помню, но не более 10 тактов 100% там идет дальний джамп и сохранение счетчика.
Последний раз редактировалось ИС-пытатель Чт мар 13, 2014 20:36:01, всего редактировалось 1 раз.
Вымогатель припоя
Аватара пользователя
Сообщения: 577
Зарегистрирован: Ср июн 19, 2013 08:10:48
Откуда: Москва, СПб, Липецк, Рязань

Сообщение ИС-пытатель »

Kavka писал(а):ИС-пытатель, а про SFIOR (Special FunctionIO Register) не читали? Может так будет проще запускать АЦП?
Читал. Но это довольно специфический регистр и назначение его битов от модели к модели меняется. К тому же, заглянул в даташит и не нашел там его вовсе для 2560. Что там должно быть в нем? ))

Да и в принципе, не все ли равно, как запускать?
Последний раз редактировалось ИС-пытатель Чт мар 13, 2014 22:48:20, всего редактировалось 1 раз.
Вымогатель припоя
Аватара пользователя
Сообщения: 577
Зарегистрирован: Ср июн 19, 2013 08:10:48
Откуда: Москва, СПб, Липецк, Рязань

Сообщение ИС-пытатель »

a_skr писал(а):
adc_data = ADCW; // получает результат 1 раз. выдает постоянно только его
Не выдает постоянно, а выдал один раз.
PORTB = counter; // Отображает младший байт счетчика. (0x01, значение не меняется)
Потому что в это прерывание больше ни разу не попали.
pps. поставьте точку останова в протеусе. Один раз попали и все. Протеус тоже баг эмулирует? ;)
Как ни странно, да! ))) Меня по началу тоже это смутило. И я долго искал, где накосячил. Не нашел.. )) К тому же, не люблю Протеус. Он тоже БАГ на БАГе весь. Железо надежней! ;) Но не на много... :shock:
ps.
PORTC = counter2; // Младший байт counter в порт. Также будет отображать только 0x01
В протеусе счетчик нормально крутится. В железе нет? :dont_know:
в 2560 крутится, а в 168 нет
ppps. Запускаете АЦП чаще, чем заканчивается преобразование.
А вот и нет. Это раз.
А если бы и так, то это не должно никак мешать. Потому что запустить его раньше не смогу чисто физически. (бит ADCS сбрасывается аппаратно по завершению обработки результата). Это два.
И при изменении частоты таймера в большую сторону (уменьшение OCR0A, опережение АЦП) норм работает. И при изменении в меньшую сторону (увеличение OCR0A, АЦП отстает) тоже норм работает. Но все опять с определенных значений. Это три!
Последний раз редактировалось ИС-пытатель Чт мар 13, 2014 20:38:55, всего редактировалось 2 раза.
Вымогатель припоя
Аватара пользователя
Сообщения: 577
Зарегистрирован: Ср июн 19, 2013 08:10:48
Откуда: Москва, СПб, Липецк, Рязань

Сообщение ИС-пытатель »

Внимание господа! )) А теперь тот же самый СИ код, только дезассемблированный. Все лишнее выкинул (цикл обнуления переменных) и заменил (добавил меток в джампах и в "плохих прерываниях" поставил reti). Файл студио с расширением .LSS:

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


.cseg

__vectors:
jmp	__ctors_end	
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
jmp	__vector_21	; Таймер
reti
reti
reti
reti
reti
reti
reti
jmp	__vector_29	; АЦП
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti

__ctors_end: // установка стека
ldi	r28, 0xFF	; 255
ldi	r29, 0x21	; 33
out	SPH, r29	; 62
out	SPL, r28	; 61

jmp	main	; 0x17c <main>

__vector_21:
;volatile unsigned char counter = 0, counter2 = 0; // можно int, long
;volatile unsigned int adc_data = 0;

;// Timer 0 по совпадению с регистром сравнения А
;ISR(TIMER0_COMPA_vect)
;{
push	r1				; Вот эти нехорошие команды, которые блочат контроллер!!! Если закомментировать
push	r0				; все команды Push и Pop, то все работает ОК
in	r0, 0x3f	; 63
push	r0				; причем, это не обязательно Push и Pop
in	r0, 0x3b	; 59
push	r0				; блокирует любое обращение к регистрам SPL и SPH!!!!!!!!
eor	r1, r1
push	r24
push	r30
push	r31
;ADCSRA |= (1<<ADSC);
ldi	r30, 0x7A	; 122
ldi	r31, 0x00	; 0
ld	r24, Z
ori	r24, 0x40	; 64
st	Z, r24
;}
pop	r31
pop	r30
pop	r24
pop	r0
out	0x3b, r0	; 59
pop	r0
out	0x3f, r0	; 63
pop	r0
pop	r1
reti

__vector_29:

;// ADC по готовности результата
;ISR(ADC_vect)
;{
push	r1				; А вот здесь команды Push и Pop на баг не влияют.
push	r0				; Хотя они здесь не особо нужны и их тоже можно выкинуть
in	r0, 0x3f	; 63
push	r0
eor	r1, r1
push	r24
push	r25
;adc_data = ADCW; // получает результат 1 раз. выдает постоянно только его
lds	r24, 0x0078
lds	r25, 0x0079
sts	0x0203, r25
sts	0x0202, r24
;PORTA = adc_data; // (для контроля изменений результата измерения - будет отображать только первое измеренное значение)
lds	r24, 0x0202
lds	r25, 0x0203
out	0x02, r24	; 2
;counter++;
lds	r24, 0x0200
subi	r24, 0xFF	; 255
sts	0x0200, r24
;PORTB = counter; // Отображает младший байт счетчика. (0x01, значение не меняется)
lds	r24, 0x0200
out	0x05, r24	; 5
;}
pop	r25
pop	r24
pop	r0
out	0x3f, r0	; 63
pop	r0
pop	r1
reti

main:
;{ 
;// Скобка, чтобы можно было свернуть и не мозолило глаза

;// Предделитель тактовой частоты - 8
;// CLKPR=0x80;
;asm ("push r20"); // Предварительно сохраняем регистр. Но обычно студия его не использует
push	r20
;asm ("ldi r20, 0x80");
ldi	r20, 0x80	; 128
;asm ("sts 0x61, r20");
sts	0x0061, r20
;//CLKPR=0x03;
;asm ("ldi r20, 3");
ldi	r20, 0x03	; 3
;asm ("sts 0x61, r20");
sts	0x0061, r20
;asm ("pop r20"); // Загружаем обратно в регистр его исходное значение
pop	r20
;// сделано через ассемблер потому, что на низких уровнях оптимизации бывает после первой команды 
;// проходит более 4 тактов и предделитель не устанавливается

;// Отключаем сторожевой таймер
;asm ("eor r1,r1"); // очистка регистра r1. Ни на что не влияет. студия всегда держит в нем 0
eor	r1, r1
;MCUCR = 0; //сброс флагов регистра (необходим для отключения стор. таймера) (см. даташит)
out	0x35, r1	; 53
;asm ("wdr");
wdr
;WDTCSR |= 0b11000; // собственно, отключение стор. таймера (фузы установлены "как надо") ;)
lds	r24, 0x0060
ori	r24, 0x18	; 24
sts	0x0060, r24
;asm ("sts 0x60,r1"); //WDTCSR
sts	0x0060, r1

;// Порты на выход
;DDRA = 0xFF;
ldi	r24, 0xFF	; 255
out	0x01, r24	; 1
;DDRB = 0xFF;
out	0x04, r24	; 4
;DDRC = 0xFF;
out	0x07, r24	; 7

;// Timer 0 
;TCCR0A = 0b00000010; // COM0A1 | COM0A0 | COM0B1 | COM0B0 | --- | --- | WGM01 | WGM00   Режим сброс по совпадению
ldi	r24, 0x02	; 2
out	0x24, r24	; 36
;TCCR0B = 0b00000010; // FOC0A | FOC0B | --- | --- | WGM02 | CS02 | CS01 | CS00  Предделитель 8 (125 кГц)
out	0x25, r24	; 37
;TCNT0 = 0;
out	0x26, r1	; 38
;OCR0A = 15; // Сброс на 15 такт. деление частоты таймера на (15+1). Зона значений появления бага от 12 до 19. (если память не изменяет)
ldi	r25, 0x0F	; 15
out	0x27, r25	; 39
;OCR0B = 0;
out	0x28, r1	; 40

;// Timer 0 Инициализация прерывания
;TIMSK0 = 0b10; // по совпадению с А.  OCIE0B | OCIE0A | TOIE0
sts	0x006E, r24

;// Инициализация АЦП
;ADMUX = 0; // REFS1 | REFS0 | ADLAR | MUX4 - MUX0   источник питания АЦП - питание контроллера,
sts	0x007C, r1
;// выравнивания вправо нет, вход ADC0 (порт PF0)
;ADCSRA=0b11001011; // ADEN | ADSC | ADATE | ADIF | ADIE | ADPS2-ADPS0   вкл, первый запуск, одиночный режим, разрешить прерывания
ldi	r24, 0xCB	; 203
sts	0x007A, r24
;// при установке ADATE в 1 (авто режим) баг не проявляется.

;while (ADCSRA & (1<<ADIF)); //Ожидание конца первого измерения (25 тактов)
metka1:
lds	r24, 0x007A
sbrc	r24, 4
rjmp	metka1      	
;ADCSRA |= (1<<ADIF); // Сброс флага прерывания
lds	r24, 0x007A
ori	r24, 0x10	; 16
sts	0x007A, r24

;TIFR0 = 0xFF; // Сброс флагов от таймера
ldi	r24, 0xFF	; 255
out	0x15, r24	; 21

;}


;asm ("sei"); // разрешаем прерывания
sei

;while (1) // Основной цикл программы. Выполняется всегда
;{
;   counter2++;
metka2:
lds	r24, 0x0201
subi	r24, 0xFF	; 255
sts	0x0201, r24
;   PORTC = counter2; // Младший байт counter в порт. Также будет отображать только 0x01
lds	r24, 0x0201
out	0x08, r24	; 8
rjmp	metka2 
Последний раз редактировалось ИС-пытатель Чт мар 13, 2014 22:50:27, всего редактировалось 1 раз.
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Сообщение a_skr »

:facepalm: :facepalm: :facepalm:
Я Вас просил вывести временнУю диаграмму на осциллограф в протеусе...
"Я написал программу как получилось, она глючит - значит это баг контроллера, который и симуляторы поддерживают. Докажите, что это не так"?
А вот и нет. Это раз.
А если бы и так, то это не должно никак мешать. Потому что запустить его раньше не смогу чисто физически. (бит ADCS сбрасывается аппаратно по завершению обработки результата). Это два.
Что его мешает запустить? Он запускается в момент записи единицы в ADSC. А что там было до этого - не имеет никакого значения.
Вымогатель припоя
Аватара пользователя
Сообщения: 577
Зарегистрирован: Ср июн 19, 2013 08:10:48
Откуда: Москва, СПб, Липецк, Рязань

Сообщение ИС-пытатель »

Для меня Протеус - не авторитет (для меня авторитет реальное железо). Если Вас этот вопрос очень беспокоит - модифицируйте программу, выворачивайте руки Протеусу - и пусть он выводит для Вас все, что угодно. Благо, руки у Вас есть.

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

Если в ADSC единица, то сколько в него ее не записывай - там она и будет.

Руки-ноги есть? пишите сами! Удовлетворять желания всех не собираюсь.
Грызет канифоль
Сообщения: 278
Зарегистрирован: Вт дек 03, 2013 11:04:04
Откуда: Киев

Сообщение kobzar »

Послушай ТС!
Веди себя нормально а не как какоето быдло!
Ты попросил помочь. А когда тебя просят предоставить какие либо данные или дают совет
ты всех отправляешь писать код самому и ведешь диалог как будто ты самый умный а вокруг стадо баранов!
То что у тебя вторая стадия зведной болезни - мы уже поняли.
Просто либо веди себя уважительно по отношению к другим участникам форума - либо раз ты такой ахуенно умный - то не позорься задавая вопросы. Умные вопросы не задают - они на них отвечают.
В какой топик с твоим участием не глянешь - везде ты "самый агурец"
:(
Влодение рускай арфаграфией - это как владение кунг-фу: настаящие мастира не преминяют ево бес ниабхадимости
Контактная информация:
Вымогатель припоя
Аватара пользователя
Сообщения: 577
Зарегистрирован: Ср июн 19, 2013 08:10:48
Откуда: Москва, СПб, Липецк, Рязань

Сообщение ИС-пытатель »

kobzar писал(а):Послушай ТС!
Веди себя нормально а не как какоето быдло!
Ты попросил помочь. А когда тебя просят предоставить какие либо данные или дают совет
ты всех отправляешь писать код самому и ведешь диалог как будто ты самый умный а вокруг стадо баранов!
То что у тебя вторая стадия зведной болезни - мы уже поняли.
Просто либо веди себя уважительно по отношению к другим участникам форума - либо раз ты такой ахуенно умный - то не позорься задавая вопросы. Умные вопросы не задают - они на них отвечают.
В какой топик с твоим участием не глянешь - везде ты "самый агурец"
:(
Вообще-то помочь мне я не просил. Это раз
В каком тоне спрашивают - в таком и отвечаю. Если ты внимательно посмотришь, то ты увидишь, что у меня есть и доброжелательные ответы и агрессивные. Это два.
Данные я все предоставил. А моделировать и писать под каждого "хочуху" не хочу. Это три
А на вопросы я отвечаю. )) И умные не стесняются задавать вопросов. Потому что знать всего невозможно. Это четыре.
А где я в топиках написал что-то неправильное? (твой топик не в счет. Ты мне реально неприятен, да и уроки твои действительно не айс). Это пять.
Не табе мну учить, БАНДЕРА. ;) (В твоем стиле русского языка) Это на последок. Давай ДО СВИДАНИЯ!
Модератор
Аватара пользователя
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Сообщение ploop »

У вас накладываются прерывания.
Если таймер на меньшую частоту настроить - заработает?
Мудрый кот
Аватара пользователя
Сообщения: 1811
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Сообщение Kavka »

Так, народ, вас порекомендовать в качестве кандидатов для "бани"? :) Хорэ уже не по делу.
ИС-пытатель писал(а):К тому же, загялнул в даташит и не нашел там его вовсе для 2560. Что там должно быть в нем? ))
У 2560 смотрите "ADCSRB – ADC Control and Status Register B"

Теперь по порядку.

"Предделитель тактовой частоты - 8"
Т.е. такт АЦП == такту таймера == такту CPU

Загнал Си-шный код в симулятор.
ISR(TIMER0_COMPA_vect) получилась около 45 тактов.
ISR(ADC_vect) получилась около 50 тактов.

Т.е. чаще 90-100 тактов у вас измерять не получиться!

Более того, "таймерный" флаг на прерывание будет уже стоят снова к моменту последующему выходу из ISR(TIMER0_COMPA_vect).
Первый раз попали в прерывание по таймеру - запустили АЦП. Выходим - уже стоит флаг на "таймерное" прерывание. Ну, одна команда CPU выполнилась и снова в обработчик прерывания таймера.
А что же с прерыванием АЦП?! А ничего! Он не будет выполняться вообще!
Reset and Interrupt Handling
...
The list also determines the priority levels of the different interrupts. The lower the address the higher is the priority level.
...
Укоротив код в ассемблерном представлении вы "впихнули" код во временнЫе рамки и оно заработало.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Вымогатель припоя
Аватара пользователя
Сообщения: 577
Зарегистрирован: Ср июн 19, 2013 08:10:48
Откуда: Москва, СПб, Липецк, Рязань

Сообщение ИС-пытатель »

ploop писал(а):У вас накладываются прерывания.
Если таймер на меньшую частоту настроить - заработает?
да, заработает. и если на большую - тоже. вообще это не должно иметь значения. очередность прерываний и все такое. )) а вы читали топик? этот вопрос уже рассматривался.
Последний раз редактировалось ИС-пытатель Чт мар 13, 2014 22:01:48, всего редактировалось 1 раз.
Модератор
Аватара пользователя
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Сообщение ploop »

Выше ответили.
Вымогатель припоя
Аватара пользователя
Сообщения: 577
Зарегистрирован: Ср июн 19, 2013 08:10:48
Откуда: Москва, СПб, Липецк, Рязань

Сообщение ИС-пытатель »

Kavka писал(а):
ИС-пытатель писал(а):К тому же, загялнул в даташит и не нашел там его вовсе для 2560. Что там должно быть в нем? ))
У 2560 смотрите "ADCSRB – ADC Control and Status Register B"
там речь про SFIOR велась.
"Предделитель тактовой частоты - 8"
Т.е. такт АЦП == такту таймера == такту CPU
Не совсем так. АЦП == такту таймера == такт CPU/8
Загнал Си-шный код в симулятор.
ISR(TIMER0_COMPA_vect) получилась около 45 тактов.
ISR(ADC_vect) получилась около 50 тактов.

Т.е. чаще 90-100 тактов у вас измерять не получиться!
В принципе, дело и не в частоте. А в том, что контроллер "вылетает"
Более того, "таймерный" флаг на прерывание будет уже стоят снова к моменту последующему выходу из ISR(TIMER0_COMPA_vect).
Первый раз попали в прерывание по таймеру - запустили АЦП. Выходим - уже стоит флаг на "таймерное" прерывание. Ну, одна команда CPU выполнилась и снова в обработчик прерывания таймера.
А что же с прерыванием АЦП?! А ничего! Он не будет выполняться вообще!
Reset and Interrupt Handling
...
The list also determines the priority levels of the different interrupts. The lower the address the higher is the priority level.
...
Укоротив код в ассемблерном представлении вы "впихнули" код во временнЫе рамки и оно заработало.
Допустим. А при чем здесь тогда операции Push и Pop? Именно из-за них происходит сбой. Причем добавлять/удалять можно любые операции. Они ничего не меняют. А вот эти - меняют. Замените все операции Push/Pop на Nop - и все заработает. И второе. Почему тогда переменные 1 раз все-таки инкрементируются? Значит, в прерывание АЦП хотя бы раз, но входит! иначе они бы и раза не инкрементировались. Причем, это не первое измерение АЦП (25 тактов). Потому что первое я провел в цикле инициализиции (можно хоть 10 там сделать - ничего не изменится). Кстати, если мне не изменяет память, то переменные в обработчике Таймера тоже "не работают".

К тому же Вы можете идеально "подогнать" на ассемблере код под временные рамки (чтобы он укладывался с небольшим запасом), а потом добавить в обработчик таймера пару команд push/pop пофиг какого регистра. И у Вас все встанет! ;) Можете и на эти команды рассчитать время, чтобы не впритык было.

Версия хорошая, но не подходит.
Последний раз редактировалось ИС-пытатель Чт мар 13, 2014 22:56:29, всего редактировалось 3 раза.
Модератор
Аватара пользователя
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Сообщение ploop »

Не совсем так. АЦП == такту таймера == такт CPU/8
У вас АЦП = такт ЦПУ/32
Нет, вру, /8
Ответить

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