0

NXP LPC1788 マイクロコントローラーを使用しており、アナログ チャンネル 0 ~ 7 で 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 チャネルを実行して、任意の遅延なしでできるだけ早く値を記録できるようにするコードを書いた人はいますか?

4

2 に答える 2

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);
}

これはあなたを助けるはずです。ただし、バーストモードを使用せずにこれを行う方法が見られるとよいので、バーストモードに依存しない正解を持っている他の人には、私の代わりに受け入れられた答えが与えられる必要があります.

于 2013-08-19T14:07:12.300 に答える
0

同じタイプの同じ生産バッチの異なるコントローラーでは、各コントローラーの動作が異なることに気付きました。

また、チャネル 0 が間違った測定を行うことがあるという問題もあります。

この問題は、チャネルの有効化とコマンドの開始の間に遅延を追加することで解決されました。この遅延は 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;
}
于 2015-08-10T12:40:11.400 に答える