2017-12-18 30 views
2

コンパイラとしてCCSを使用するPIC16F18855マイクロを使用していますが、ADCを動作させようとしています。 CCSによって供給される機能で始まる、私が書いた:これは、(10ビットの読み取りのためのランダム9と18の間の)ピンの実際の電圧とは完全に独立した読み取りと、奇妙な行動しPIC16F18855 ADCレジスタが期待通りに動作しません(C、CCSコンパイラ)

#device ADC=10 
... 
setup_adc_ports(sAN21); 
setup_adc(ADC_CLOCK_DIV_8); 
set_adc_channel(21); 
... 
fprintf(HOST, "%ld", read_adc()); //I have RS232 implemented elsewhere 

Cがコンパイルしたアセンブリを同僚が見て、read_adc()の組み込み関数を使ってADCを読み込もうとするとコンパイラが間違ったレジスタに書き込んでいると私に伝えます。具体的には、変換を開始するためにADGOビットを書き込む必要があるときは、存在しないADCON0より前のレジスタに書き込みます。これを回避するには

は、私が設定してADCを読み取るための私自身の機能を実装してみました:私は直後fprintf(HOST, "0x%x", ADC_CON_0);を呼び出す場合

#byte ADC_CON_0 = getenv("SFR:ADCON0") 
#byte ADC_CON_1 = getenv("SFR:ADCON1") 
#byte ADC_CON_2 = getenv("SFR:ADCON2") 
#byte ADC_CON_3 = getenv("SFR:ADCON3") 
#byte ADC_CLK = getenv("SFR:ADCLK") 
#byte ADC_RES_H = getenv("SFR:ADRESH") 
#byte ADC_RES_L = getenv("SFR:ADRESL") 
#byte AN_SEL_C = getenv("SFR:ANSELC") 
#byte ADC_PCH = getenv("SFR:ADPCH") 

void adc_setup(void){ 
    //setting the mode and clock 
    ADC_CON_0 = 0x84; //turn on ADC and right justify it 
    ADC_CON_1 = 0x00; 
    ADC_CON_2 = 0x00; 
    ADC_CON_3 = 0x00; 
    ADC_CLK = 0x03; //gives Fosc/8, for 1us T_AD with 8MHz clock 

    //setting the input channel and telling the pin to be analogue 
    AN_SEL_C = 0x20; //set pin C5 to analogue input 
    ADC_PCH = 0x15; //0x15 = 21, analogue channel 21 is pin C5 
} 

int16 read_adc_custom_implementation(void){ 
    ADC_CON_0 |= 0x01;      //set ADGO bit to start conversion 
    while(ADC_CON_0 & 0x01){}    //wait till conversion is finished (indicated by hardware reset of ADGO bit) 
    return make16(ADC_RES_H, ADC_RES_L); //read the result registers and return them combined into a 16bit integer 
} 

私のコードを持つ2つの大きな問題があります。お電話adc_setup();私は0x84を受け取ったときに0x80を取得します。つまり、10ビットのADC値は、右揃えではなく、2 8ビットレジスタ内で左揃えになります。なぜ私はそれが正しく書かれていないのか分かりません。私がチェックした他のすべてのレジスタ(ADCON1-3とADCLK)は正しいです。

read_adc_custom_implementation();と呼ぶと、whileループで永遠に待機し、ADGOビットがリセットされないことを示します。

adc_setupread_adc_custom_implementationの実装が機能しない理由は誰にも分かりますか?あるいは、なぜCCSの提供された機能が動作しないのかを知っていれば、代わりにそれらを使うことができれば嬉しいです。

PIC16F18855 datasheet、ADCON0、私はuser from the CCS forumsの助けを借りて、問題の解決策を見つけたページ357

+0

'read_adc()'はどのような型を返しますか? 'read_adc()'の定義を投稿してください。 – chux

+0

CCSマニュアル:#DEVICE ADC =指令に応じて、8ビットまたは16ビットのいずれかの整数。 #device adc = 10そのint16を使用しているためです。 – Escape

+0

'long'に' l'の代わりに 'fprintf(HOST、"%d "、(int)read_adc());' – chux

答えて

0

です。

私が遭遇したバグは、シリコンのバグです.ADGOビットを設定して次のクロックサイクルで読み出すと、ADCは決してADGOビットをリセットしません。これは私のwhileループが永遠に待つことを意味します。このバグの詳細はerrataにあります。私は実際にこれを手で読んでいましたが、私のプロジェクトで何が起きていたのかは、文書に記載されているものと同じではないため、私には当てはまらないと誤解していました。

回避策は、それをADGOビットを設定し、検査の間に単一のクロック・サイクルの遅延、即ち、を含むことがある:

int16 read_adc_custom_implementation(void){ 
    ADC_CON_0 |= 0x01;      //set ADGO bit to start conversion 
    delay_cycles(1);      //workaround 
    while(ADC_CON_0 & 0x01){}    //wait till conversion is finished (indicated by hardware reset of ADGO bit) 
    return make16(ADC_RES_H, ADC_RES_L); //read the result registers and return them combined into a 16bit integer 
} 

この回避策は、バージョン5.069以降でCCSに組み込まread_adc()関数に含まれていますしかし私は18655をサポートするコンパイラの最初のバージョンであった5.065を使用していました。私は最初に回避策を試してみましたが、私の問題の1つを解決しましたが、まだ多くのバグに遭遇しました。 代わりに、私は5.075に更新し、組み込まれたread_adc()関数を使用しました。すべてが完全に動作するようになりました。

短い話ですが、同じ問題がある場合は、コンパイラを更新してください。

関連する問題