2013-08-19 31 views
0

我正在使用恩智浦LPC1788微控制器,并且我正在尝试编写能让我在模拟通道0-7上执行ADC测量的代码。我现在所拥有的代码是:是否有人为恩智浦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; 
} 
相关问题