Помогите разобраться в нюансах прошивки

Программирование микроконтроллеров AVR, PIC, ARM.
Разработка и изготовление печатных плат для модулей.

Помогите разобраться в нюансах прошивки

Сообщение AlexRu » 28 окт 2009, 09:03

День добрый. Я новичек в программаровании микроконтроллеров и данная программа - это первая написанная мною программа, так что изначально буду благодарен за любую критику, но есть пара вопросов о некоторых местах в прошивке.
Суть работы - опрос поочередно четырех каналов АЦП, сравнение 0-1 и 2-3 и принятие решений. Изначально АЦП у меня работал по флагу, но на макетке мусор доходил до 6 разряда!!! (выравнивание влево, первые два разряда не учитываю) потому пришлось разбираться и переводить на ADC Noise Reduction. Вот тут и появился вопрос. Вот часть прошивки:
Код: Выделить всё
void on_adc_up (void)
{      
   ADMUX = 0x61;
   unsigned char i=0;
   for (i=0; i<5; i++)
   {   
      ADCSRA |= (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0) | (1<<ADIE);
      MCUCR&=~(1<<SM2) | ~(1<<SM1);
      MCUCR|= (1<<SM0) | (1<<SE);
      ADCSR|=1<<ADSC;
      asm("sleep");
      asm("nop"); // ???
      sum_adh += adh;
      _delay_ms(25);
   }
   Up_Solar_ = sum_adh/5;
   sum_adh=0;
}

Обработчик прерывания:
Код: Выделить всё
ISR(ADC_vect)
{
   cli();
   MCUCR &=~(1<<SE);
   ADCSRA &= ~_BV(ADIE);
   adh=ADCH;
   sei();
}


Так вот, без вставки asm("nop") ничего не работало, интуитивно догадался, что где-то теряю, но не понял где.
P.S. При наладке я выводил число сразу на порт, так вот, если выводил в обработчике прерываний - все ОК, если в самой функции - пусто. Объясните пожалуйста почему.

Следующий вопрос - изменение канала АЦП. В программе написаны функции последовательно для каналов 0-3, если в своем канале меняю перед спячкой MUX - ничего не происходит. Мучался всю ночь. Помогло только тогда когда в фунции я переключал на следующий канал. Так и должно быть? Тоесть я сейчас запускаю АЦП нулевого канала, а MUX надо выставить для первого?

Тертий вопрос: в начале мейна у меня идет инициализация устройства по функции Init_(). Без вставок asm("nop") фукция не отрабатывалась и программа висла, не доходя до основного цикла.

Просьба, если не сложно, обьяснить "на пальцах". Интуитивно понимаю, но хочу вникнуть. Заранее спасибо.

P.S. Dj время отладки этой программы убедился в том, что знание асма не помешало-бы.
Вложения
Prog1.rar
Исходник С++, файл для Протеуса, прошивка.
Компилятор WinAVR GCC
(77.58 КиБ) Скачиваний: 3
AlexRu
 
Сообщения: 4
Зарегистрирован: 28 окт 2009, 08:34
Откуда: Киев

Re: Помогите разобраться в нюансах прошивки

Сообщение avr123.nm.ru » 28 окт 2009, 09:25

Вот это сомнительно
Код: Выделить всё
MCUCR &= ~(1<<SM2) | ~(1<<SM1);


наверно так лучше
Код: Выделить всё
MCUCR &= ~((1<<SM2) | (1<<SM1));
Аватара пользователя
avr123.nm.ru
отсылающий читать курс
 
Сообщения: 14195
Зарегистрирован: 06 ноя 2005, 04:18
Откуда: Москва

Re: Помогите разобраться в нюансах прошивки

Сообщение AlexRu » 29 окт 2009, 03:52

Вот это сомнительно

Код: Выделить всё • Развернуть

MCUCR &= ~(1<<SM2) | ~(1<<SM1);


М-да...проверил математически - точно, в моем варианте в итоге на порту ничего не поменяется. Если WinAVR не учитывает этот нюанс, то скорее здесь и проблема. Сейчас попробую, за подсказку спасибо.

Добавлено спустя 2 минуты 17 секунд:
Интересно, а WinAVR поймет такой вариант:
MCUCR &= ~(3<<SM1);

Добавлено спустя 3 минуты 19 секунд:
...или скорее:
MCUCR &= ~(3<<SM2);
AlexRu
 
Сообщения: 4
Зарегистрирован: 28 окт 2009, 08:34
Откуда: Киев

Re: Помогите разобраться в нюансах прошивки

Сообщение boez » 29 окт 2009, 12:42

Это все либо просто неправильно, либо может случайно заработать при правильном раскладе битов в регистре. Правильный вариант - как написал avr123, сначала "или", потом инверсия. Только он работает и независим от расположения битов в регистре.
boez
 
Сообщения: 1981
Зарегистрирован: 27 авг 2008, 10:45
Откуда: Харьков
прог. языки: С/С++


Вернуться в Микроконтроллеры

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

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