Свежие обсуждения
Микроконтроллеры

Сил уже больше нет - ПРЕРЫВАНИЯ и АТМЕГА8

1 4

В аттаче проект на CodeVision и Протеус, небольшая программка для измерения тока и напряжения с использованием прерывания и спящего режима.... Подскажите почему не работает, т.е. измерения путаются и показывает непонятно чего. Если поставить задержку перед измерением то все в порядке, в чем причина?
И попутно вопрос Протеус меняет местами входы АЦП, 0 и 1 канал, в чем может быть проблема? Не дайте погибнуть !!!!

 

Вот аттач

106071.rar

 

Сначала выбираем канал (ADMUX=...)
И только потом запускаем преобразование (ADCSRA |= 0x40)

 

Спасибо огромное АНТОХА !!!!
ОК понял, да тут проглядел, но это по поводу смены местами входов АЦП. А почему само преобразование с прерыванием так себя непонятно ведет?
т.е. не совсем непонятно, как бы переодически меняются местами измерения, как будто бы прерывание срабатывает еще до того как закончилось преобразование и считывается код из предыдущего канала....

 

Попробуй для начала без прерывания и без спячки:


u16 adc_read(u08 ch)
{
ADMUX = _BV(REFS0) | (ch & 0x1F); // set channel (VREF = VCC)
ADCSRA &= ~_BV(ADIF); // clear hardware "conversion complete" flag
ADCSRA |= _BV(ADSC); // start conversion
while(ADCSRA & _BV(ADSC)); // wait until conversion complete
return ADC; // read ADC (full 10 bits);
}

Если всё будет нормально, можно добавить прерывание. Потом спячку.

 

Глюк вроде нашелся, но я не понимаю
Если делать подряд 2 преобразования с разных каналов, то чтобы все работало необходимо между ними вставлять задержку, зачем?
или это просто так Протеус отрабатывает?

 

Хорошо сейчас поробую
но вот так ведь работает в железе и в Протеусе

unsigned int read_adc(unsigned char adc_input) // Чтение результата преобразования
{
ADMUX=0xC0|adc_input; // Выбираем канал для АЦП в adc_input, 0xC0 - источник опорного напряжения - внутренний
ADCSRA|=0x40; // Старт преобразования и внешний конденсатор
while ((ADCSRA & 0x10)==0); // Ждем конца преобразованиия флаг ADIF станет = 0
return ADCW;
}

..........

Volt_ACP = read_adc(0x01);
Amper_ACP = read_adc(0x00);

Volt = (Volt_ACP / 1024) * 30; // Верхняя шкала 30V
Amper= (Amper_ACP / 1024) * 15; // Верхняя шкала 15A

сейчас присмотрелся это тоже самое что ты предложил, так работает замечательно...

 

Lerik: Если делать подряд 2 преобразования с разных каналов, то чтобы все работало необходимо между ними вставлять задержку, зачем?

Такое может быть, если АЦП настроен на непрерывное преобразование. В этом случае при смене канала он сначала завершает текущее преобразование.

Ещё вариант - контроллер выходит из sleep по какому-то другому прерыванию, не от АЦП. Есть другие прерывания?

 

да в том то и дело что нет, во всяком случае я не назначал, посмотри плиз код, может увидишь криминал?
Этот код работает нормально, но.... задержка

106084.c

 

Lerik, что-то не совсем понял химию вокруг MCUCR. Если в нем установлен ADC Noice Reduction, никаких sleep делать не надо - при установке флага начала преобразования процессор сам переходит в спячку. Для этого этот режим и задумывался.