ADC変換により、変換の開始時にPICのアナログ入力ピンが接地されるのはなぜですか?

Aug 23 2020

MPLAB X IDE v5.35PIC16LF19176を使用

PIC ADCアナログ入力を数回使用しましたが、変換すると常に適切な結果が得られます。スコープで入力を見ると混乱します。

スコープチャネル1は、センサーの電源に接続されています。

スコープチャネル2は、アナログマルチプレクサを介して間接的にセンサー出力ワイヤに接続されます。マルチプレクサはその時点でチャネル5に永続的に切り替えられ、有効になっています(テスト中に制御信号は変更されません)。スコープはR5抵抗器の上部に取り付けられており、その時点でセンサー出力と並列になっているため、センサーに7k87抵抗器がロードされます。左側のマルチプレクサは、信号MUX5_A(テストポイントTP1)を介して3V励起をセンサーに「もたらし」、センサーは信号MUX5_B(TP2)を介して右側のマルチプレクサを介して出力を返します。

付属のアクティブセンサーには3本のワイヤーがあります。電源+ 3V。GND; そして出力0..3V。センサー出力は、ADC変換に使用されるPICアナログ入力に接続されています。センサーの電源は、専用のDC / DCレギュレーターを介してPICによってオン/オフされます。

センサーの電源を入れた後、PICADC変換を開始します。GOビットがセットされると(変換開始)、入力ピンは約10ミリ秒の間接地されます。次に、入力が「解放」され、センサーが適切な値を示します。変換はさらに17ミリ秒の間アクティブであり、適切な結果を返すように見えます。

ご参考までに、私はコードをデバッグして、さまざまな遅延を設定しようとしました。接地効果は、変換が開始されたときのみです。

添付の写真は、2つの連続した変換(平均を計算しています)を示しています。どちらも不要なピンの接地から始まります。

センサーの出力をこのストレスにさらしたくありません。誰かが私に言うことができます、なぜPIC入力ピンがこのように接地されているのですか?


ADC変換は実際にはMPLABによって生成されました。

adc_result_t ADCC_GetSingleConversion(adcc_channel_t channel)
{
// select the A/D channel
ADPCH = channel;

// Turn on the ADC module
ADCON0bits.ADON = 1;

//Disable the continuous mode.
ADCON0bits.ADCONT = 0;    

// Start the conversion
ADCON0bits.ADGO = 1;
// Now the scope shows signal gets grounded...

// Wait for the conversion to finish
while (ADCON0bits.ADGO)
{
    // in the middle of this conversion, signal goes back up...
}
    
// Conversion finished, return the result
return ((adc_result_t)((ADRESH << 8) + ADRESL));
}

ADC初期化ルーチンを確認すると便利な場合があります。

/**
 * ADC is initialized to highest possible accuracy at the cost of slowness (conversion time 37 msec)
 * During the initialization the GIE must be disabled
 * 
 * We are set to:
 * - basic mode
 * - clock source FOSC/ADCLK
 * - clock FOSC/128
 * - result is aligned to right
 * - reference voltage used is VDD of the processor
 * 
 */
void ADCC_Initialize(void)
{
PMD2bits.ADCMD = MODULE_POWER_ON;

// ADC Interrupt disable, clear all its flags:
{
    PIE1bits.ADTIE = DISABLED;             
    PIE1bits.ADIE = DISABLED;
    PIR1bits.ADTIF = 0;
    PIR1bits.ADIF = 0;
}

// set the ADCC to the options selected in the User Interface
// ADLTH 0; 
ADLTHL = 0x00;
// ADLTH 0; 
ADLTHH = 0x00;
// ADUTH 0; 
ADUTHL = 0x00;
// ADUTH 0; 
ADUTHH = 0x00;
// ADSTPT 0; 
ADSTPTL = 0x00;
// ADSTPT 0; 
ADSTPTH = 0x00;
// ADACC 0; 
ADACCU = 0x00;
// ADRPT 31; 
ADRPT = 0x1F;
// ADPCH ANC3; 
ADPCH = ADC_pin_U_BAT_HALF;   // Input channel switched to RC3
// ADACQ 255; 
ADACQL = 0xFF;
// ADACQ 31; 
ADACQH = 0x1F;
// ADCAP Additional uC disabled; 
ADCAP = 0x00;
// ADPRE 255; 
ADPREL = 0xFF;
// ADPRE 31; 
ADPREH = 0x1F;
// ADDSEN disabled; ADGPOL digital_low; ADIPEN disabled; ADPPOL Vss; 
ADCON1 = 0x00;
// ADCRS 0; ADMD Basic_mode; ADACLR disabled; ADPSIS RES; 
ADCON2 = 0x00;
// ADCALC First derivative of Single measurement; ADTMD disabled; ADSOI ADGO not cleared; 
ADCON3 = 0x00;
// ADMATH registers not updated; 
ADSTAT = 0x00;
// ADPREF VDD; 
ADREF = 0x00;   // Vref = Vdd (because external DC/DC RT9013-3V3 accuracy is +-2%, internal Vref +-4% => Vdd is more accurate than internal Vref)
// ADACT disabled; 
ADACT = 0x00;
// ADCS FOSC/128; 
ADCLK = 0x3F;   // slowest setting, but most accurate // conversion took about 37 msec
// ADGO stop; ADFM right justified; ADON disabled; ADCS FOSC/ADCLK; ADCONT disabled; 
ADCON0 = 0x04;
}

回答

3 Dan1138 Aug 24 2020 at 05:02

あなたの質問に対する答えはありますが、あなたがあなたの投稿にどのような詳細を入れたか、そしてもっと重要なことにあなたがあなたの投稿に何を入れなかったかは、正しい答えを見つけることを本当の挑戦にしました。

まず、dsPICを使用することはできません。dsPICは8ビットコントローラーの1つである必要があります。ほとんどの場合、容量性分圧器(CVD)機能をサポートするADC機能ブロックを備えたPIC18FxxQxxタイプの1つです。

次に、MPLABによって生成されたと主張するADCコードのカットアンドペーストジョブはがらくたです。初期化により、CVD機能を使用してタッチ/近接センシングモードで使用するようにADCが設定されます。この機能は、実際には、ADPREレジスタをゼロ以外の値に設定することにより、変換が開始される前の特定の期間、ADC入力ピンをVSSに接続します。

最後に、ADC変換クロック周期を設定するために投稿したコードは、考えられるすべての点で間違っていますが、それでも変換結果が生成される可能性があります。

ADC機能ブロックを説明しているデータシートの一部を理解しましたか?

EmbeddedGuy Aug 24 2020 at 17:38

@ Dan1138が示唆したように、問題は、CVDが誤ってアクティブ化された状態でADCを初期化することでした。マイクロチップのマニュアルには、次のようにも記載されています。(アナログ入力)ピンにデバイスが接続されている場合は、プリチャージを使用しないでください。

解決策は、両方のプリチャージレジスタを0に設定することでした。

// ADPRE 0; 
ADPREL = 0x00; // was incorrectly 0xFF
// ADPRE 0; 
ADPREH = 0x00; // was incorrectly 0x1F

これによりADC変換が修正され、スコープの図に示すように、ピンは接地されなくなりました。