Обсуждаем контроллеры компании Atmel.
Ответить

последовательный опрос двух каналов внутреннего ацп atmega 8

Пн июн 19, 2023 23:13:27

Здравствуйте добрые люди! помогите исправить ошибку в С-кодировке. не работает опрос двух каналов внутреннего ацп в атмеге. на оба индикатора выводица только результат оцифровки одного канала mux5. вот сами функции
Спойлер//--- Функция оцифровки напряжения внутреним ацп MUX5 ---
unsigned int ADCV_Conv(unsigned char ch_ADC) //(переменная "канал ацп")
{
unsigned int adcv_value = 0; //сброс регистра хранения результата оцифровки напряжения
unsigned char set_ADMUX = ADMUX; //переменная для выбора канала АЦП
ADMUX |= ((0<<MUX3)|(1<<MUX2)|(0<<MUX1)|(1<<MUX0)); //выбор канала АЦП MUX5
_delay_us(10); //пауза 10мкс
for(unsigned char i=0;i<measure;i++) //цикл суммирования результатов оцифровки 64 замеров
{
ADCSRA |= (1<<ADSC); //запуск АЦП
while((ADCSRA &(1<<ADSC))); //ожидание окончания преобразования
adcv_value += ADCW; //adcv_value=adcv_value+ADCW прибавим к сумме значений предыдущих измерений значение очередного измерения
}
return(unsigned int)adcv_value >> 6; //выйдем из функции и вернём среднее значение (из регистров результата ADCL и ADCH АЦП)
} //оцифровки 64 замеров в переменную типа (unsigned int)

//--- Функция оцифровки тока внутреним ацп MUX4 ---
unsigned int ADCI_Conv(unsigned char ch_ADC) //(переменная "канал ацп")
{
unsigned int adcv_value = 0; //сброс регистра хранения результата оцифровки напряжения
unsigned char set_ADMUX = ADMUX; //переменная для выбора канала АЦП
ADMUX |= ((0<<MUX3)|(1<<MUX2)|(0<<MUX1)|(0<<MUX0)); //выбор канала АЦП MUX4
_delay_us(10); //пауза 10мкс
for(unsigned char i=0;i<measure;i++) //цикл суммирования результатов оцифровки 64 замеров
{
ADCSRA |= (1<<ADSC); //запуск АЦП
while((ADCSRA &(1<<ADSC))); //ожидание окончания преобразования
adcv_value += ADCW; //adcv_value=adcv_value+ADCW прибавим к сумме значений предыдущих измерений значение очередного измерения
}
return(unsigned int)adcv_value >> 7; //выйдем из функции и вернём 1/2 среднего значения (из регистров результата ADCL и ADCH АЦП)
} //оцифровки 64 замеров в переменную типа (unsigned int)

а вот цикл
Спойлерwhile(1)
{
Display1_ADC = ADCV_Conv(5); //считаем значение канала MUX5
ledprint_1(Display1_ADC); //отправим считанное значение в функцию вывода на индикатор вольтметра
_delay_ms(200); //пауза 0,2с
//Display2_ADC = ADCI_Conv(Read_3201()); //считаем значение регистра SPDR
Display2_ADC = ADCI_Conv(4); //считаем значение канала MUX4
ledprint_2(Display2_ADC); //отправим считанное значение в функцию вывода на индикатор амперметра
_delay_ms(200); //пауза 0,2с
}

Re: последовательный опрос двух каналов внутреннего ацп atme

Вт июн 20, 2023 00:45:56

У вас проблема простая:
Код:
ADMUX |= ((0 << MUX3) | (1 << MUX2) | (0 << MUX1) | (0 << MUX0));
если при измерении напряжения в бите MUX0 была 1, то "логическим или" она не сбросится.
Можно сделать так:
Код:
unsigned char set_ADMUX = ADMUX; //переменная для выбора канала АЦП
set_ADMUX &= ((1 << REFS1) | (1 << REFS0)); // оставить только Vref
set_ADMUX |= ch_ADC; //выбор канала АЦП ch_ADC
ADMUX = set_ADMUX;
в обеих функциях измерения.
Можно функции ADCV_Conv и ADCI_Conv заменить на одну:
Код:
#define EXTRA_BITS 6
#if EXTRA_BITS > 6
#error EXTRA_BITS > 6
#endif
#define MEASUREMENTS (1 << EXTRA_BITS)

//--- Функция оцифровки ацп канал ch_ADC ---
unsigned int ADC_Conv(unsigned char ch_ADC) //(переменная "канал ацп")
{
    unsigned int adcv_value = 0; //сброс регистра хранения результата оцифровки напряжения
    unsigned char set_ADMUX = ADMUX; //переменная для выбора канала АЦП
    set_ADMUX &= ((1 << REFS1) | (1 << REFS0)); // оставить только Vref
    set_ADMUX |= ch_ADC; //выбор канала АЦП ch_ADC
    ADMUX = set_ADMUX;
    _delay_us(10); //пауза 10мкс
    for (unsigned char i = 0; i < MEASUREMENTS; i++) //цикл суммирования результатов оцифровки 64 замеров
    {
        ADCSRA |= (1 << ADSC); //запуск АЦП
        while ((ADCSRA & (1 << ADSC)))
            ; //ожидание окончания преобразования
        adcv_value += ADCW; //adcv_value=adcv_value+ADCW прибавим к сумме значений предыдущих измерений значение очередного измерения
    }
    return (unsigned int)adcv_value >> EXTRA_BITS; //выйдем из функции и вернём среднее значение (из регистров результата ADCL и ADCH АЦП)
} //оцифровки 64 замеров в переменную типа (unsigned int)
Почему-то, при измерении тока вы возвращаете только 1/2 среднего значения, но это легко исправить:
Код:
while (1) {
    Display1_ADC = ADC_Conv(5); //считаем значение канала 5
    ledprint_1(Display1_ADC); //отправим считанное значение в функцию вывода на индикатор вольтметра
    _delay_ms(200); //пауза 0,2с
    //Display2_ADC = ADCI_Conv(Read_3201()); //считаем значение регистра SPDR
    Display2_ADC = ADC_Conv(4) >> 1; // 1/2 среднего значения
    ledprint_2(Display2_ADC); //отправим считанное значение в функцию вывода на индикатор амперметра
    _delay_ms(200); //пауза 0,2с
}

Re: последовательный опрос двух каналов внутреннего ацп atme

Вт июн 20, 2023 14:32:32

Eleprekra благодарствую вам добрый человек :beer: вставил вашу кодировку, а свою ахинею закоментировал. всё заработало как надо. деление /128 в канале тока нужно для правильногоо отображения предела 50а. в канале mux5 верхний предел 99,9в, поэтому там просто усреднение /64
СпойлерИзображение

сегодня после каторги попробую пустить в красную верёвочку полсотни ампер и откалибровать дивайс
СпойлерИзображение
Ответить