2013-04-04 6 views
0

Я изо всех сил пытаюсь заставить АЦП работать с моим устройством. Я использую dsPIC33FJ128GP802 и попытался начать медленно с ручной выборки и преобразования.ADC dsPIC33 issue

Мой код опубликован ниже, я установил каждый регистр для АЦП и затем попытался пробовать только один раз, чтобы получить напряжение от датчика, который я подключил. Значение, которое я должен видеть, составляет около 0,7 В, но то, что я получаю, находится в области -17408 (10111100 00000000). Это может возрасти примерно до -2000, но значение не должно быть отрицательным в первую очередь.

#include <p33Fxxxx.h> 

_FOSCSEL(FNOSC_FRCPLL) // select internal 7.37MHz osc with PPL 
_FOSC(OSCIOFNC_OFF & POSCMD_XT) // no clock output, external OSC disabled 
_FWDT(FWDTEN_OFF) // disable the watchdog timer 
_FPOR(FPWRT_PWR1) // Turn off the power-up timers. 

int ADCValue; 

void DELAY(unsigned ms) { 
    unsigned j; 
    unsigned i; 
    for (j = 0; j < ms; j++) { 
     for (i = 0; i < 0x1F40; i++); 
    } 
} 

int main(void) { 

    // set up clock to 80MHz 
    PLLFBD = 41; // sets M = 41+2 = 43 
    CLKDIVbits.PLLPRE = 0; // sets N1 = 2 
    CLKDIVbits.PLLPOST = 0; // sets N2 = 2 
    while (!OSCCONbits.LOCK); // wait for PLL ready 

    AD1CON1 = 0; // set everything to zero to start with. 
    AD1CON1bits.ADON = 0; // turn ADC off. 
    AD1CON1bits.ADSIDL = 0; // continue module operation in idle mode. 
    AD1CON1bits.ADDMABM = 1; // DMA buffers are written in the order of conversion. 
    AD1CON1bits.AD12B = 0; // set to 10bit mode. 
    AD1CON1bits.FORM = 3; // set data output to signed fractional. 
    AD1CON1bits.SSRC = 0; // manual conversion. clearing sample bit manually. 
    AD1CON1bits.SIMSAM = 1; // collect samples from channels 0, 1, 2, 3 simultaneously. 
    AD1CON1bits.ASAM = 0; // manual sample. samples when SAMP bit is set. 
    AD1CON1bits.SAMP = 0; // sample enable bit. 
    AD1CON1bits.DONE = 0; // ADC conversion status bit. 

    AD1CON2 = 0; // set everything to zero to start with. 
    AD1CON2bits.VCFG = 0; // converter voltage ref. set to AVdd and AVss. 
    AD1CON2bits.CSCNA = 0; // input scan select bit. set to do not scan. 
    AD1CON2bits.CHPS = 0; // channel select bits. set to just channel 0; 
    AD1CON2bits.BUFS = 0; // buffer fill status (invalid as BUFM is 0); 
    AD1CON2bits.SMPI = 0; // ADC interrupt is generated after every sample/conversion. 
    AD1CON2bits.BUFM = 0; // buffer fill mode. set to always start filling from start address. 
    AD1CON2bits.ALTS = 0; // Alternate input sample mode. set to always uses channel input from sample A. 

    AD1CON3 = 0; // set everything to zero to start with. 
    AD1CON3bits.ADRC = 0; // ADC conversion clock derived from system clock. 
    AD1CON3bits.SAMC = 0; // auto sample time bits, TAD, set to 0. 
    AD1CON3bits.ADCS = 0; // ADC conversion clock set to 0. 1 * TCY = TAD. 

    AD1CON4 = 0; // set everything to zero to start with. 
    AD1CON4bits.DMABL = 0; // allocates 1 word of buffer to each analogue input. 

    AD1CHS123 = 0; // everything set to zero as not using channels 1, 2, or 3. 

    AD1CHS0 = 0; // set everything to zero to start with. 
    AD1CHS0bits.CH0NB = 0; // channel 0 negative input, set by CH0NA. sample B. 
    AD1CHS0bits.CH0SB = 0; // channel 0 positive input, set by CH0SA. sample B. 
    AD1CHS0bits.CH0NA = 0; // channel 0 negative input, for sample A. set to VREFL. 
    AD1CHS0bits.CH0SA = 0; // channel 0 positive input is AN0. 

    AD1CSSL = 0; // input scan register set to zero as not using it. 

    AD1PCFGL = 0; // port configuration, set to analogue mode, ADC samples voltage. 

    AD1CON1bits.ADON = 1; // turn on ADC 

    AD1CON1bits.SAMP = 1; // Start sampling 
    DELAY(1); // Wait for sampling time (1ms) 
    AD1CON1bits.SAMP = 0; // Start the conversion 
    while (!AD1CON1bits.DONE); // Wait for the conversion to complete 
    ADCValue = ADC1BUF0; // Read the conversion result 

    while (1); 

} 

У меня датчик приведенный в действие, используя те же рельсы ПИК использует, и у меня есть выход датчика к AN0 (контакт 2), как я установить его в коде. PIC подключен к стандартным Vss и Vdd (контакты 8 и 13), аналоговые выводы питания AVdd и AVss (контакты 28 и 27) и конденсатор емкостью 33 мкФ через Vcap и Vss (контакты 20 и 19). Есть ли что-нибудь еще, что мне нужно сделать с помощью аппаратных средств? Я немного запутался с регистром AD1CHS0bits.CH0NA, так как не знаю, должен ли я подключать почву к VREFL или что делать в этом случае.

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

+0

Если вы не считаете, что значение должно быть отрицательным, не используйте 'int'. Ваш битовый шаблон, интерпретируемый как 'unsigned int', равен 48128. – unwind

+1

@unwind: если комментарии в коде точны, то формат вывода данных является фиксированным форматом фиксированной точки. Выходное значение в буфере преобразования находится в диапазоне от -1,0 до +1,0, представляющий диапазон напряжения от опорного низкого уровня, чтобы ссылаться на высоком уровне. Если ОП только обеспечивают 0В для опорного минимума, то он, вероятно, должен использовать беззнаковый дробный формат, а также использовать беззнаковый тип данных в коде C. В его нынешнем виде -17408 можно разделить на 32768 на диапазон от -1,0 до 1,0, а затем масштабирование, которое линейно для AVss-AVdd (я предполагаю, что 3V3) дает значение 0,77. Использование 3V дает 0,7 В. – tinman

+0

На какое напряжение вы управляете ПОС? – tinman

ответ

1

Если значение не должно быть отрицательным, чтобы начать с, то вы не должны использовать этот параметр:

AD1CON1bits.FORM = 3; // set data output to signed fractional. 

Если бы я бы ожидать, что ваша ценность будет (оцениваемой с использованием Python):

int((2**10) *  # 10-bit operation 
    (0.7/3.3)  # 0.7 volts on a 3.3 volt system 
    - (2**9)  # Center at VDD/2 because of signed operation 
    ) << 6   # Fractional output left-shifted the 10-bit up by 6 to fill 16-bits 
= -18816 

Что звучит о том, что выводит ваш код.

Вместо этого используйте:

AD1CON1bits.FORM = 0; // set data output to integer. 

Используя эти настройки, наряду с 10-битным режимом, я бы ожидать, что ваша ценность будет

int((2**10) *  # 10-bit operation 
    (0.7/3.3))  # 0.7 volts on a 3.3 volt system 
= 217