boban 0 20 июля, 2005 Опубликовано 20 июля, 2005 · Жалоба Всем привет! Первый раз работаю с ATmega8 в режиме чтения нескольких аналоговых сигналов. Пишу в IARе... Аналоговые входы: РС5 (28-я нога), РС3 (26-я нога), РС2 (25-я нога). Кварц 11.0592 MHz // инициализация АЦП ADMUX = 0x03; // REFS1=REFS0=0 Uопорн на AREF // MUX3..0=0011 вход на ножке PC3 ADCSR = 0x8F; // ADEN=1 ADC enable // ADSC=0 запуск позже; // ADIE=1 ADC interrupt enable // ADPS2..0=111 Fosc/128 = 86,4кГц Запускаю преобразование таймером каждые 10мс: ADCSR_Bit6 = 1; // ADSC=1 старт АЦП И вот собственно обработчик прерывания: //Обработчик прерывания по завершению преобразования в АЦП #pragma vector = ADC_vect __interrupt void OnADCConversionComplete () { unsigned int tmp, tmpH; tmp = (unsigned int) ADCL; tmpH = (unsigned int) ADCH; tmpH = tmpH << 8; tmp = tmp + tmpH; tmp = tmp >> 2; // получаем результат в младших 8 битах if (ADMUX == 0x03) { U26 = (unsigned char) tmp; // в U26 - напряжение на 26-й ноге ADMUX = 0x05; } else { if (ADMUX == 0x05) { U28 = (unsigned char) tmp; // в U28 - напряжение на 28-й ноге ADMUX = 0x02; } else { if (ADMUX == 0x02) { U25 = (unsigned char) tmp; // в U25 - напряжение на 25-й ноге ADMUX = 0x03; } } } ADCSR_Bit6 = 0; // ADSC=0 запрет АЦП } Вроде все просто, но есть подозрение, что что-то не так... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
subver 0 20 июля, 2005 Опубликовано 20 июля, 2005 · Жалоба Вместо: tmp = (unsigned int) ADCL; tmpH = (unsigned int) ADCH; tmpH = tmpH << 8; tmp = tmp + tmpH; tmp = tmp >> 2; // получаем результат в младших 8 битах я бы сделал так: tmp = (unsigned int) ADCL; tmpH = (unsigned int) ADCH; tmp+=tmpH*0x100; tmp>>=2; Хотя вроде можно к ADC обратится как 16-разрядному регистру, поэтому первые 3 операции можно исключить. Все вышесказанное верно, если у вас не включен режим выравнивания результата влево. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 20 июля, 2005 Опубликовано 20 июля, 2005 · Жалоба IAR действительно позволяет ADC сразу считать. unsigned int tmp=ADC; А вот так, например, у меня от таймера перебирает каналы: #pragma vector=TIMER0_OVF_vect __interrupt void TIMER0() { static unsigned char adc_chanel=0; unsigned int value=ADC; switch(adc_chanel) { case 0: U0=value; adc_chanel++; break; case 1: U1=value; adc_chanel++; break; case 2: U2=value; adc_chanel++; break; case 3: U3=value; adc_chanel=6; break; case 6: U6=value; adc_chanel++; break; case 7: U7=value; adc_chanel=0; break; } //Запустим следующее преобразование ADMUX=adc_chanel; ADCSR|=(1<<ADSC); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться