Аналоговый вход.
- Войдите на сайт для отправки комментариев
Ср, 29/01/2020 - 23:16
Пытаюсь побороть ATTiny26L. С цифровыми выходами более-менее разобрался, а с аналоговым входом не получается. Задача- измерить напряжение на входе АС9 (у ATTiny26L аналоговых входов 10 штук, в отличие от Атмеги8).
Вот урезанная версия кода для измерения напряжение на входе АС9 (выдрано на просторах интернета, номер входа подкорректировал под свой случай):
int main() { ADCSRA |= (1 << ADEN) // Включаем АЦП | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // устанавливаем предделитель преобразователя на 128 ADMUX |= (0 << REFS1) | (1 << REFS0) // выставляем опорное напряжение Vcc | (1 << MUX0) | (0 << MUX1) | (0 << MUX2) | (1 << MUX3); // снимать сигнал будем с входа AC9 while (1) { do { ADCSRA |= (1 << ADSC); // Начинаем преобразование } while ((ADCSRA & (1 << ADIF)) == 0); // пока не будет выставлен флаг об окончании преобразования int data = (ADCL | ADCH << 8); // Считываем полученное значение } }
Без аналогового входа всё работает, вот пример кода для отображения на индикаторе числа от 000 до 999 (аналоговая часть закомментирована, если разкомментировать, выводится число 423 независимо от напряжения на входе, причём с потухшим сегментом от порта РА3) :
#include <util/delay.h> unsigned char Dig[10]; byte Disp1, Disp2, Disp3; int Disp; int qwer; int main() { DDRB = 56;// B00111000 - назначаю выходами порты PB3, PB4, PB5 DDRA = 255;// назначаю выходами все порты A PORTB = 0; PORTA = 255; /* ADCSRA |= (1 << ADEN) // Включаем АЦП | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // устанавливаем предделитель преобразователя на 128 ADMUX |= (0 << REFS1) | (1 << REFS0) // выставляем опорное напряжение Vcc | (1 << MUX0) | (0 << MUX1) | (0 << MUX2) | (1 << MUX3); // снимать сигнал будем с входа AC9 */ _delay_ms(2000);// Dig_init(); while (1) { // qwer ++; if (qwer > 20) { Disp ++; qwer = 0; } /* do { ADCSRA |= (1 << ADSC); // Начинаем преобразование } while ((ADCSRA & (1 << ADIF)) == 0); // пока не будет выставлен флаг об окончании преобразования int data = (ADCL | ADCH << 8); // Считываем полученное значение */ Display (Disp); } } // Функция выделяет цифры из трехзначного числа Number void Display (int Number) { int Num1, Num2, Num3; Num1 = Num2 = 0; while (Number >= 100) { Number -= 100; Num1++; } while (Number >= 10) { Number -= 10; Num2++; } Num3 = Number; // динамическая индикация трёх разрядов на семисегментном индикаторе. PORTB |= _BV(5); PORTB |= _BV(4); PORTB &= ~_BV(3);// младший разряд PORTA = Dig[Num3]; _delay_ms(1); PORTB |= _BV(5); PORTB &= ~_BV(4);// средний разряд PORTB |= _BV(3); PORTA = Dig[Num2]; _delay_ms(1); PORTB &= ~_BV(5);// старший разряд PORTB |= _BV(4); PORTB |= _BV(3); PORTA = Dig[Num1]; _delay_ms(1); } void Dig_init() { Dig[0] = (250); // схема с общим катодом, комбинации для символов 0...9 Dig[1] = (34); Dig[2] = (185); Dig[3] = (171); Dig[4] = (99); Dig[5] = (203); Dig[6] = (219); Dig[7] = (162); Dig[8] = (251); Dig[9] = (235); }
Что я делаю не так?
Для начала было пы неплохо внятно изложить проблему.
- Полный код с проблемой
- Что ожидается при запуске
- Что получается при запуске
Полный код с проблемой:
Что ожидается при запуске: На семисегментном индикаторе должно отображаться число от 0 до 511 в зависимости от напряжение на входе АС9.
Что получается при запуске: На семисегментном индикаторе отображается число 511 независимо от напряжение на входе АС9. Сегмент от порта РА3 (он же AREF) не отображается.
Если закомментировать строки 16...20 и 34...38, работают все сегменты и отображается число от 000 до 999 последовательно (то есть всё работает как должно).
В 19 строке для опорного выбираетс АREF, а не Vcc как в комментарии написано. Для Vcc оба бита должны быть 0
Блин, как просто всё оказалось!!! А я пять дней голову ломаю. Спасибо огромное! У меня мелькала догадка, когда понял, что потухший сегмент связан с AREF. Но я не развил её в нужном направлении...
И тогда ещё вопрос: можно ли заменить
на что-то вроде
Пожалуйста.
Можно. Но потом разбираться или менять что-то будет намного менее удобдно.