ADCを使ってみる。

出来た事

1.ADCプロジェクトの作成 & 確認


予定では、I2Cを使ってEEPROMにアクセスしたい!
と思ってたんですけど,
仕様書見てもよくわかんないし、長いしで先にADCをやることにしました。
(今アマゾンに頼んでる本にI2Cのこと書いて有りそうだし。。)

基本的なLPC1343のADCの使い方!!

さて今回のコンセプトですが
1.ADC0を使う
2.出てきた答えはprintfで表示して確認する。
です。

printfを使うのでprojectはSemihostingを選択することに注意です。
CでもC++でもなくSemihosting C projectです

 一応エレキジャックさんのHello worldへのリンクはっときます

確認したコードは以下

#ifdef __USE_CMSIS
#include "LPC13xx.h"
#endif

#include
#include


__CRP const unsigned int CRP_WORD = CRP_NO_CRP ;

#include

int main(void) {
LPC_SYSCON->PDRUNCFG &= ~(0x1<<4); // See data sheet
LPC_SYSCON->SYSAHBCLKCTRL |= (0x1<<13); // See data sheet
LPC_IOCON->JTAG_TDI_PIO0_11 &= ~0x8F; // PIO0_11=Analog input
//ちょっと検討したら 0x8Fじゃなく0x9Fの方が良いことが判明。下で説明//

LPC_IOCON->JTAG_TDI_PIO0_11 |= 0x02; // PIO0_11=ADC0

LPC_ADC->CR |=0x00000001; // ADC0=on
//Clkdiv This time clk=4MHz (max=4.5MHz)
LPC_ADC->CR = *1; //修正2012.2.17
printf("%d\n",(LPC_ADC->DR0 & 0x0000FFC0)>>6);
LPC_ADC->CR &= 0xF8FFFFFF; //stop ADC now
}
return 0 ;
}

で、実験した回路がコレ
可変抵抗(ボリューム)がなかったので単純に抵抗で1/2分圧しただけです。


それで結果がコンソールに出たのがコレ

ADCが10bit精度で抵抗で1/2分圧してるだけなんで
値は512になって欲しかったんですが、ちょっとずれてますね。

確認のためにテスタで電圧を測ってみると
AD0 1.697V
3V3 3.149V
計算すると552になりますが表示は561か。。

ま、そんなもんなのかな。。


コードの解説です。
基本はNXPのSampleコードから持ってきてます。
(リンク先のLPC1343 Sample Projectから入手できます。)


LPC_SYSCON->PDRUNCFG &= ~(0x1<<4); // See data sheet
LPC_SYSCON->SYSAHBCLKCTRL |= (0x1<<13); // See data sheet

この2行はユーザマニュアルに書いてあるまんまです。
ココからダウンロード



LPC_IOCON->JTAG_TDI_PIO0_11 &= ~0x8F; // PIO0_11=Analog input
LPC_IOCON->JTAG_TDI_PIO0_11 |= 0x02; // PIO0_11=ADC0

こいつもPIN設定で書いてあるまんまなんですが
ただ、ピンのファンクションだけを変えればよいのではなく
Analog inputにしなければいけないところが注意です。


ここで、気づいてしまった。
なんだかNXPのサンプルコードはPIN設定がPull upになってますね。。。

LPC_IOCON->JTAG_TDI_PIO0_11 &= ~0x8F; // PIO0_11=Analog input

この記載を

LPC_IOCON->JTAG_TDI_PIO0_11 &= ~0x9F; // PIO0_11=Analog input

とするとプルアップが取れます。

すると。。。


コンソールのデータが期待値である512に
そして電圧も
AD0 1.573V
3V3 3.145V

サンプルコードはちょっとイカンかったようですね。

2012/2/14追記
よーくサンプルコードを見直してみると下の方に以下の記載がありました。

LPC_IOCON->JTAG_TDI_PIO0_11 = 0x02; // Select AD0 pin function

コレだと問題ないです。

なんで2種類の書き方してるのかはわからないんですが・・


気を取り直して次!

LPC_ADC->CR |=0x00000001; // ADC0=on
//Clkdiv This time clk=4MHz (max=4.5MHz)
LPC_ADC->CR = ((SystemCoreClock/LPC_SYSCON->SYSAHBCLKDIV)/4000000-1)<<8;

上の行はADCのオンオフコントロールです
次の行ですが、最初よくわからんかったですが
仕様書を見て理解しました。(20.5項)

ADCのクロックは4.5MHz以下にしなければならなくて
System clock(72MHz) / (CLKDIV+1)で計算されます。

で今回は4MHzになるようにしてみたということです。


最後!

LPC_ADC->CR |=0x01000000; //ADC Start now
while(LPC_ADC->DR0 & 0x80000000 );
printf("%d\n",(LPC_ADC->DR0 & 0x0000FFC0)>>6);
LPC_ADC->CR &= 0xF8FFFFFF; //stop ADC now


コレも仕様書をみるとわかるのですが

1行目はADCをStartさせる。
2行目は AD0のAD変換が完了するとDR0レジスタ31bitが1になります。それをチェック!
そしてprintfでコンソールに出力
一度ADCをとめます。



苦労話。。。(スルーOK)

実はADC、出来るのに2日以上かかってるんですよね。

ADCはエレキジャックさんのところで、
ざっと目次を見てもなかったので、自分でやりました。

サンプルコードを見るとなんだかややこしくって。。
バーストモードとか
LPC1343にある8個のADC全部をコントロールできるようにしてたりとか
とにかくサンプルコードは何でも出来る全部入りみたいな感じで。。

C言語もよくわかってない自分としては敷居高かったんです。

で、仕様書見てサンプルコード見てごちゃごちゃ自分で作ってると
LPC_IOCON->JTAG_TDI_PIO0_11 &= ~0x8F;
を入れてなかったんですね。
(PINの機能をADCにはセットしたがAnalog inputにしていなかった。。)

それでも、なぜだか値がでるんですよ。おかしな値が。。
それで余計にわからなくなって。。。

最終的に一つ一つサンプルコードと仕様書を追っていって
何とかできたんですが
振り返ってみるとたったコレだけに時間かかりすぎ!!!

まぁ開発ってのはそんなモンですけどね。。

*1:SystemCoreClock/LPC_SYSCON->SYSAHBCLKDIV)/4000000-1)<<8; printf("Hello World\n"); while(1) { LPC_ADC->CR |=0x01000000; //ADC Start now while(!(LPC_ADC->DR0 & 0x80000000