Работа с двумя аналоговыми датчиками, ATmega16

avr atmega

Я хочу работать с двумя аналоговыми датчиками, подключенными к ATmega16. Первый - это датчик температуры (LM35), подключенный к PA0. Светодиод должен гореть, когда температура становится высокой. Второй - это фоторезистор, и он подключен к PA1. Я хочу включить светодиод при слабом освещении. Я искал решение по всему Интернету, но не смог найти ничего похожего на мою ситуацию. Все они говорят только об одном - вы не можете считывать показания двух аналоговых датчиков одновременно.

У меня есть этот код, который работает только для одного датчика:

#define F_CPU 1600000UL
#include <avr/io.h>

void ADC_Init() {
    DDRA = 0x0;
    ADCSRA = 0x87;
    ADMUX = 0x40;
}

uint16_t ADC_Read(uint8_t channel) {
    ADMUX = (ADMUX & 0xF0) | (channel & 0x0F);
    ADCSRA |= (1 << ADSC);
    while (ADCSRA & (1 << ADSC)) ;
    return ADC;
}

int main(void) {
    ADC_Init();
    DDRB = 0xFF;
    while (1) {
        uint8_t value;
        value = ADC_Read(0);
        if (value > 70) {
            PORTB |= (1<<0);
        } else {
            PORTB &= ~(1<<0);
        }
    }
}

Можете ли вы как-то помочь мне изменить этот код, дать мне совет, как я могу это сделать, или какой-нибудь пример?

, 👍0

Обсуждение

Что происходит, когда вы меняете ADC_Read(0) на ADC_Read(1)?, @devnull

@devnull это работает только для одного датчика одновременно. Если я использую ADC_Read(1), это будет работать для второго датчика. Я попытался настроить его с помощью цикла переключения, в первом случае ADC_Read(0), во втором ADC_Read(1), но это не сработает., @cerouno

Хорошо. Поскольку MCU не может выполнять * любые * две вещи программно одновременно, вы можете считывать данные из канала 0 в одну переменную, считывать данные из канала 1 в другую переменную, а затем решать, что делать со светодиодами в соответствии с двумя значениями. Вы также можете отредактировать свой вопрос, чтобы показать этот второй код, который вы упомянули, поскольку ваш тест показывает, что аппаратная часть / АЦП уже работает для двух датчиков., @devnull

Я переформатировал код для удобства чтения и, делая это, взял на себя смелость добавить закрывающую фигурную скобку, которая отсутствовала в ADC_Init()., @Edgar Bonet

Я голосую за закрытие этого вопроса, потому что пользователя не было здесь больше года, поэтому шансы на то, что этот вопрос будет принят, очень малы., @VE7JRO


1 ответ


0

Я только что просмотрел спецификацию ATmega16, так что, возможно, отнеситесь к этому ответу с недоверием.

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

Взгляните на описание регистра ADMUX в техническом описании

Прямо сейчас вы устанавливаете мультиплексирование один раз во время выполнения функции init(), а затем никогда не меняете его. В вашем новом коде вам нужно будет изменить значение в регистре во время выполнения (в дополнение к любой другой требуемой конфигурации / обслуживанию), что должно произойти в вашем основном цикле ()

Описание высокого уровня:

int main()
{
    system_init();
    
    while (1)
    {
        set ADMUX to read from PA0
        read ADC

        set ADMUX to read from PA1
        read ADC

        do stuff
    }

}
,

Я понимаю, что вы имеете в виду, но если я сделаю это в основном цикле, он не будет работать бесконечно, и канал будет изменен только один раз. Как я могу постоянно переключаться между этими двумя датчиками?, @cerouno

@cerouno Если вы поместите приведенный выше код в свой цикл while (1), он будет выполняться бесконечно. Я отредактирую псевдокод выше, чтобы показать это., @mooshoomatt

Если вы внимательно прочитаете техническое описание, то обнаружите тот факт, что вы должны выбросить первое чтение после операции переключения входа., @gbg