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=ADC0LPC_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