Atmel AVR ADMUX Регистр не принимает назначенное значение - PullRequest
0 голосов
/ 30 января 2019

У меня есть следующие перечисления и структуры:

typedef enum reference{
    AREF = 0, //External on AREF pin
    AVCC = true << REFS0, //Analogue supply voltage
    I11 = true << REFS1, //Internal 1.1V reference
    I256 = true << REFS1 | true <<REFS0 //Internal 2.56 reference
} Reference;

typedef enum channel{
    ADC0 = 0,
    ADC1 = true << MUX0,
    ADC2 = true << MUX1,
    ADC3 = true << MUX0 | true << MUX1,
    ADC4 = true << MUX2,
    ADC5 = true << MUX2 | true << MUX0,
    ADC6 = true << MUX2 | true << MUX1,
    ADC7 = true << MUX2 | true << MUX1 | true << MUX0
    //If higher channels are needed continue using MUXn for n = 0-> 4 in a binary count.
} Channel;

typedef enum leftadjust{
    LADisabled = 0,
    LAEnabled = true << ADLAR
} LeftAdjust;

//Enums for ADCSRA
typedef enum adcenable{
    ADCDisabled = 0,
    ADCEnabled = true << ADEN
} ADCEnable;

typedef enum adcautotriggerenable{
    AutoTriggerDisabled = 0,
    AutoTriggerEnabled = true << ADATE
} ADCAutoTriggerEnable;

typedef enum adcinterruptenable{
    ADCIntteruptDisabled = 0,
    ADCInterruptEnabled = true << ADIE,
} ADCInterruptEnable;

typedef enum adcclockdivider{
    CDHalf = 0,
    CDQuarter = true << ADPS1,
    CDEighth = true << ADPS1 | true << ADPS0,
    CDSixteenth = true << ADPS2,
    CDThirtySecond = true << ADPS2 | true << ADPS0,
    CDSixtyFourth = true << ADPS2 | true << ADPS1,
    CDOneTwoEighth = true << ADPS2 | true << ADPS1| true << ADPS0
} ADCClockDivider;

///structs
typedef struct ADCSettings{
    Reference ref;
    LeftAdjust leftAdjust;
    Channel channel;
    ADCAutoTriggerEnable autoTrigger;
    ADCInterruptEnable interruptEnable;
    ADCClockDivider clockDivider;
    } ADCSettings;

Эта функция конструктора:

ADCSettings* NewADCSettings()
{
    return (ADCSettings*)malloc(sizeof(ADCSettings));
}

, а затем эта функция для настройки моего АЦП:

void InitialiseADC(ADCSettings* settings)
{
    /*
        13CCs for a conversion. 50ns/cc therefore 0 clock division conversion time is 13 * 50ns =650ns.
        for 50us; 50us/950ns = 77.
        We have 16,32,64 and 128, 64 gives a time of 61us which is in range.
    */
    ADMUX = (settings->ref | settings ->leftAdjust | settings->channel);
    //ADMUX = true << REFS0 | true << MUX1 | true << MUX0; //REFSn sets voltage ref source, MUXn sets channel

    DIDR0 = true << ADC3D; //DIDR is digital input disable (makes a pin analogue)
    ADCSRA = true << ADEN | settings ->autoTrigger | settings ->interruptEnable | settings ->leftAdjust | settings->clockDivider;
    //ADCSRA = true << ADEN | true << ADPS2 | true << ADPS1; //ADPS1 & ADPS2 gives 64 scale

}

Как вы можете видеть, я нахожусь в процессе рефакторинга, чтобы попытаться сделать из него хорошую библиотечную функцию, а не просто настроить ее так, как мне нужно в этот раз.Закомментированные строки работали просто отлично.

Когда я запускаю это, я считаю, что ADMUX должно быть присвоено 67, но вместо этого он принимает значение 64, которое, если я не ошибаюсь, простоREFS0 получение набора и ни MUX0, ни MUX1.

Регистр 8-битный, поэтому он должен иметь возможность хранить значение до 255.

Вот мой main.c для полноты:

#include "misc/utilities.h"
#include <avr/io.h>
#include <util/delay.h>
#include <stdbool.h>
#include "USART/USART.h"
#include "ADC/ADC.h"

int main()
{
    ADCSettings* settings = NewADCSettings();
    settings->autoTrigger = false;
    settings->channel=ADC3;
    settings->clockDivider=CDSixtyFourth;
    settings->interruptEnable=false;
    settings->leftAdjust=false;
    settings->ref=AVCC;
    InitialiseADC(settings);
    while (true) 
    {
        int adcReading = GetADCConversion();
        Tx_Line(IntToString(adcReading));
        _delay_ms(100);
    }
}

Библиотека USART и библиотека Utilities использовались ранее, поэтому я почти уверен, что они в порядке.

Есть идеи, где я ошибаюсь?

1 Ответ

0 голосов
/ 31 января 2019

Оказывается, что с моей настройкой АЦП не было никаких проблем.

Проблемы с регистрами, похоже, были просто задержкой в ​​симуляторе, обновляющем значение в окне наблюдения.

Причина, по которой я не получал значения, заключалась в том, что я забыл запустить мою команду InitialiseUART() из библиотеки.

Мораль истории, убедитесь, что вы инициализировали все свои периферийные устройства.


Другие советы из комментариев:

  1. Не используйте динамическое назначение памяти для маленьких УК.
  2. Не полагайтесь на числовые значения перечислений, используйте #define
...