2013-08-19 6 views
0

저는 NXP LPC1788 마이크로 컨트롤러로 작업 중이며 아날로그 채널 0-7에서 ADC 측정을 수행 할 코드를 작성하려고합니다. 지금 당장 가지고있는 코드는 다음과 같습니다.NXP LPC17xx ADC에 대한 작업 코드를 작성한 사람이 있습니까?

uint16_t getADCChannelValue(uint8_t adcChannel) 
{ 
    uint16_t adc_value; 

    ADC_ChannelCmd(LPC_ADC, adcChannel, ENABLE); 
    ADC_StartCmd(LPC_ADC, ADC_START_NOW); 

    // Wait for measurement to complete. 
    while (!(ADC_ChannelGetStatus(LPC_ADC, adcChannel, ADC_DATA_DONE))); 

    adc_value = ADC_ChannelGetData(LPC_ADC, adcChannel); 
    ADC_ChannelCmd(LPC_ADC, adcChannel, DISABLE); 

    // With delay - code works. Without delay - channel 0 is correct, 
    // channels 1-7 have values close to channel 0 (~2150) (incorrect). 
    //OS_Delay(1); 

    return adc_value; 
} 

지연으로 코드가 작동하는 것처럼 보이지만 거기에 임의의 지연을 원하지 않습니다. 나는 몇 시간 동안 코드를 가지고 놀았으며 어떤 이유로 든 오버런 플래그는 지연이있을 때 설정된다. 즉, 함수가 올바른 값을 출력 할 때 오버런에 대해 불평한다.

난 단지 아날로그 채널 0에 전압을인가하고있어 이것은 내가 지연이 포함 된 경우 얻을 출력 :

Channel 0 = 2151 
Channel 1 = 35 
Channel 2 = 33 
Channel 3 = 34 
Channel 4 = 32 
Channel 5 = 34 
Channel 6 = 32 
Channel 7 = 31 

을 그리고 포함되지 않은 경우 :

Channel 0 = 2150 
Channel 1 = 2151 
Channel 2 = 2151 
Channel 3 = 2150 
Channel 4 = 2150 
Channel 5 = 2150 
Channel 6 = 2149 
Channel 7 = 2150 

사람을 가지고 임의의 지연없이 최대한 빨리 모든 ADC 채널을 실행하고 값을 기록 할 수있는 코드를 작성 했습니까?

답변

1

태그, "버스트 모드"를 사용해야한다고 생각합니다. 다음은 ADC 초기 설정 코드입니다.

void adcHandlerInit() 
{ 
    // Clear all bits of the analog pin registers except for the filter disable 
    // bit. 
    *((uint32_t *)(LPC_IOCON_BASE + ((BRD_ADC_CH_PORT_0 * 32 
          + BRD_ADC_CH_PIN_23)*sizeof(uint32_t)))) = 1 << 8; 
    *((uint32_t *)(LPC_IOCON_BASE + ((BRD_ADC_CH_PORT_0 * 32 
          + BRD_ADC_CH_PIN_24)*sizeof(uint32_t)))) = 1 << 8; 
    *((uint32_t *)(LPC_IOCON_BASE + ((BRD_ADC_CH_PORT_0 * 32 
          + BRD_ADC_CH_PIN_25)*sizeof(uint32_t)))) = 1 << 8; 
    *((uint32_t *)(LPC_IOCON_BASE + ((BRD_ADC_CH_PORT_0 * 32 
          + BRD_ADC_CH_PIN_26)*sizeof(uint32_t)))) = 1 << 8; 
    *((uint32_t *)(LPC_IOCON_BASE + ((BRD_ADC_CH_PORT_1 * 32 
          + BRD_ADC_CH_PIN_30)*sizeof(uint32_t)))) = 1 << 8; 
    *((uint32_t *)(LPC_IOCON_BASE + ((BRD_ADC_CH_PORT_1 * 32 
          + BRD_ADC_CH_PIN_31)*sizeof(uint32_t)))) = 1 << 8; 
    *((uint32_t *)(LPC_IOCON_BASE + ((BRD_ADC_CH_PORT_0 * 32 
          + BRD_ADC_CH_PIN_12)*sizeof(uint32_t)))) = 1 << 8; 
    *((uint32_t *)(LPC_IOCON_BASE + ((BRD_ADC_CH_PORT_0 * 32 
          + BRD_ADC_CH_PIN_13)*sizeof(uint32_t)))) = 1 << 8; 

    PINSEL_ConfigPin(BRD_ADC_CH_PORT_0, BRD_ADC_CH_PIN_23, BRD_ADC_CH_FUNC_NO_1); 
    PINSEL_ConfigPin(BRD_ADC_CH_PORT_0, BRD_ADC_CH_PIN_24, BRD_ADC_CH_FUNC_NO_1); 
    PINSEL_ConfigPin(BRD_ADC_CH_PORT_0, BRD_ADC_CH_PIN_25, BRD_ADC_CH_FUNC_NO_1); 
    PINSEL_ConfigPin(BRD_ADC_CH_PORT_0, BRD_ADC_CH_PIN_26, BRD_ADC_CH_FUNC_NO_1); 
    PINSEL_ConfigPin(BRD_ADC_CH_PORT_1, BRD_ADC_CH_PIN_30, BRD_ADC_CH_FUNC_NO_3); 
    PINSEL_ConfigPin(BRD_ADC_CH_PORT_1, BRD_ADC_CH_PIN_31, BRD_ADC_CH_FUNC_NO_3); 
    PINSEL_ConfigPin(BRD_ADC_CH_PORT_0, BRD_ADC_CH_PIN_12, BRD_ADC_CH_FUNC_NO_3); 
    PINSEL_ConfigPin(BRD_ADC_CH_PORT_0, BRD_ADC_CH_PIN_13, BRD_ADC_CH_FUNC_NO_3); 

    /* Configuration for ADC : 
    * ADC conversion rate = 400Khz 
    */ 
    ADC_Init(LPC_ADC, 400000); 

    ADC_IntConfig(LPC_ADC, BRD_ADC_INTR_0, DISABLE); 
    ADC_IntConfig(LPC_ADC, BRD_ADC_INTR_1, DISABLE); 
    ADC_IntConfig(LPC_ADC, BRD_ADC_INTR_2, DISABLE); 
    ADC_IntConfig(LPC_ADC, BRD_ADC_INTR_3, DISABLE); 
    ADC_IntConfig(LPC_ADC, BRD_ADC_INTR_4, DISABLE); 
    ADC_IntConfig(LPC_ADC, BRD_ADC_INTR_5, DISABLE); 
    ADC_IntConfig(LPC_ADC, BRD_ADC_INTR_6, DISABLE); 
    ADC_IntConfig(LPC_ADC, BRD_ADC_INTR_7, DISABLE); 

    // Start burst mode. 
    ADC_ChannelCmd(LPC_ADC, ADC_CHANNEL_0, ENABLE); 
    ADC_ChannelCmd(LPC_ADC, ADC_CHANNEL_1, ENABLE); 
    ADC_ChannelCmd(LPC_ADC, ADC_CHANNEL_2, ENABLE); 
    ADC_ChannelCmd(LPC_ADC, ADC_CHANNEL_3, ENABLE); 
    ADC_ChannelCmd(LPC_ADC, ADC_CHANNEL_4, ENABLE); 
    ADC_ChannelCmd(LPC_ADC, ADC_CHANNEL_5, ENABLE); 
    ADC_ChannelCmd(LPC_ADC, ADC_CHANNEL_6, ENABLE); 
    ADC_ChannelCmd(LPC_ADC, ADC_CHANNEL_7, ENABLE); 
    ADC_StartCmd(LPC_ADC, ADC_START_CONTINUOUS); 
    ADC_BurstCmd(LPC_ADC, ENABLE); 
} 

하단의 부품이 중요합니다. 마이크로 컨트롤러가 모든 ADC 채널에서 반복 측정을 수행하게합니다. 그 후 다음을 사용하여 채널 전압 값을 얻을 수 있습니다.

uint16_t getADCChannelValue(uint8_t adcChannel) 
{ 
    return (uint16_t)ADC_ChannelGetData(LPC_ADC, adcChannel); 
} 

이 정보는 도움이 될 것입니다. 그러나 버스트 모드를 사용하지 않고이를 수행하는 방법을 보는 것이 좋을 것입니다. 따라서 버스트 모드에 의존하지 않는 정답을 가진 사람은 나 대신에 받아 들여지는 대답을 받아야합니다.

+0

고맙습니다. 이것은 잘 작동합니다. – Tagc

0

동일한 유형의 동일한 컨트롤러와 동일한 생산 배치에서 각 컨트롤러가 서로 다른 동작을하는 것으로 나타났습니다.

나는 때때로 0

이 문제는 채널을 활성화하고 cmd를 시작 사이에 지연을 추가하여 해결 된 잘못된 측정을하고있다 채널 문제가 있습니다. 이 지연은 1us였습니다.

여전히이 지연은 각 컨트롤러마다 향상되지 않습니다. 이제는 4us입니다. 그러나 희망없는 해결책은 아닙니다.

un16 adcMeasureChannelBlocked(un8 channel) 
{ 
un16 value; 

// Enable channel 
ADC_ChannelCmd(LP_ADC_PERHIPHERAL, channel, ENABLE); 

// Reset delay timer 
adcTimeOutTimer = timingGetTicks(); 
while(!(timingHasElapsed(&adcTimeOutTimer, TIMING_TIME_US(4)))); 

// Start measurement 
ADC_StartCmd(LP_ADC_PERHIPHERAL, ADC_START_NOW); 

// Reset timeout timer 
adcTimeOutTimer = timingGetTicks(); 

// Wait until done 
while(!ADC_ChannelGetDoneStatus(LP_ADC_PERHIPHERAL, channel, &value)); 
{ 
    if (timingHasElapsed(&adcTimeOutTimer, TIMING_TIME_MS(2))) 
    { 
     bmsStatusEvent(STATUS_EVT_SET,ERROR_HW_ADC_DATA); 
    } 
} 

// Disable channel 
ADC_ChannelCmd(LP_ADC_PERHIPHERAL, channel, DISABLE); 

return value; 
}