2017年2月
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28        

Amazonウィジェット

  • miniPC
  • 最近買った本
  • Raspberry Pi
  • クアッドコプター
  • 書籍ランキング

AdSense

  • 広告
無料ブログはココログ

ARM LPCXpresso

2013年8月14日 (水)

I2C AVRマスター送受信とLPC1114のスレーブ 20バイト連続送受信

i2cのプログラムを使って一連の動作をテスト。

<AVR側 マスター送受信>
最初に20バイトの送信をする。
次に、LPCで一旦受信されたデータを20バイト分AVR側で受信する。
☆結果的に送信したデータと全く同じデータが受信される。
受信したデータはUARTでPCから確認できる。

「i2c_lib-0716-2213.c」をダウンロード

※AVRは、内蔵8MHzで動作させます。



<LPC側 スレーブ>
全部UPするとややこしいので、i2cの処理メインとなるファイルだけ。

「i2cslave_multiByte.c」をダウンロード

このプログラムは、LPCzoneからダウンロードできるサンプルプログラム
lpcxpresso.examples.lpc1114.302
をベースに、今回の目的のために書き換えたもの。

オリジナルのプロジェクトに取り込む際は、
・CMSISを読み込む。
・Driverフォルダに本ファイルを入れる。
・元のi2cslave.cを削除する。
・i2cslave.hの中身を編集する。
  ・BUFSIZE を6→20に変更
  ・PCF8594_ADDR を0xA0→0x40に変更


※尚、このプログラムは100kHzビットレートで動作します。



2013年8月12日 (月)

LPC1114とAVR(ATmega328P)をI2C通信させたときの不具合

LPC1114とAVR(ATmega328P)をI2C通信させようとしたときに、1週間ぐらい悩んだのでそのときの顛末をメモ。
解決後のソースは後日公開。


NXPではLPCzoneでサンプルプログラムやCMSISが公開されている。
コンパイルすれば取りあえず実行はできる。また、用途に合わせて書き換えるのもそれほど難しくはない。Rd,WrBufferという配列にデータを入れたりLEDに出力したりすれば、直ぐに動作が確認できる。lpcxpresso.examples.lpc1114.302をベースにAVRと通信させようとしたのだが、プログラムを少し手直しする必要があった。

LPCをマスターにして、AVRへの送信。AVRからの受信は簡単に実現。
AVRマスターからLPCスレーブへの送信もそれなりに難儀したが実現できた。
しかし、AVRマスターでLPCからデータを受信するパターンだけはできなかった。

一旦、AVRマスター送信+LPCスレーブ受信は動作が確認できているので、その後に続けてCB(R)を送ってLPCスレーブ送信が実行できないかを確認した。

AVRがマスターでLPCがスレーブ
1.最初にAVRがマスター送信で2バイト送る。
2.スタートコンディションを入れる
3.続けてCB(R)を送る。
4.1バイト受信する。LPCは0x01を返すようにセットした。
※ビットレートは100kHz

ところが、いつまでやっても受信データは0xC1のまま。LPC側の送信バッファに何をいれてもだめ。その時の波形はこのようなものだった。

I2c_error_avrmr_lpcst

最初のマスター送信で、0x32、0x31が送られ、その後CB(R)が送られる。
上の画像は0x31が送られた後のCB(R)=0x41。

なぜか勝手にSDAがHiになってしまっている。
これはストップコンディションに該当するのでは??

I2c_error2_avrmr_lpcst

そして上の画像が、肝心のデータ受信バイト部分。
9クロック目でNOACK応答だからHi。最後にストップコンディションとなっている。

しかし、この問題が解決するまではこのように解釈してしまっていた。
「LPCからは0x01が返されるはず。最初の2clk分はHiのままになってしまっていて、受信データが完全におかしい。9clk目はNACKが返っている。データがやり取りできていない」



<<さらに解析>>

ACKの操作をどうやって実行しているのかLPCのソースを追った。

主にAA(Assert Acknoledge)とSI(interrupt)の2つのビットが関係している。AAを1にセットするとACKを返す。

まずステータス値が工程に従ってどのように変化するか図から確認した。スレーブアドレスを受け取ったら0xA8。データを受け取ったら0xB8になる。NOACKを受けたら0xC0

switch文の中身を見ていると、いつも0xC1と変な値になってしまう理由が判明した。結論から言うと、1バイト目の送信には不定データを送っていたのだ。

顛末
1.1回目の割り込みでステータス値は0xA8。その直後にACKを返すためにAAをセット。SICをセットしてSIをクリアし次のバイトの受信を待つ状態にする。ここまでは正常。

2.マスターから1バイト分のクロックが送られてデータが送信完了状態になると、ステータス値は0xB8となる。ここで何故かLPC_I2C->DATにデータを入れている。

要約すると、
スレーブ受信→データ送信後データをセット

完全に手順が逆になっていることが判明した。正しくは、0xB8の処理(AAとSICのセット)の直後にLPC->DATをセットすべきだったのだ。そうしなければ不定データを送信データとしてセットしていることになる。


おかしな箇所はまだある。

ストップコンディションでステータス値が0xC0になった後、NACKを返すためにAACをセットしている。これはACKをスレーブから返さないようにするということ。
そしてSICで割り込みフラグをクリア。

その後AAをセットしている箇所が見当たらないので、二度とACKを返すことはない。

つまり、電源投入してから通信を1回完了すると、これ以降CB(R)を受けてもACKを返すことはない。
ここも相当マズイ。

















2013年8月 6日 (火)

I2C 不具合解析に使った色々なノウハウ

LPC1114のスレーブ送信とAVRのマスター受信が上手くいかなくて、ありとあらゆる方法で対策を行ったが、その際に使用したテクニックを書き残した。

I2Cのトラブル対処方法として、クロックを空うちしてデバイスをリセットする方法を試すときに使ったソースについて解説。
この資料の 「通信中断後のリセット」 マスター側電源投入後に実施推奨。 SDAを開放してからSCLを空打ちする。


<I2Cクロックをソフトで作る方法>

AVRの汎用ポートを直接叩いてI2Cポートとして動作させる。
I2Cの信号ラインを制御するとき、出力ポートでHi・Lowさせると他のデバイスの通信を完全に妨害してしまう。そこで、オープンドレインを保つためにHiを出すときは入力ポート。

AVRがマスターでLowを出すときに限り出力ポートに切り替え、Lowを出力して引っ張るようにしなければならない。 なお、ここではプルアップ抵抗がポートに接続されていることとする。プルアップをつけないでやることはできない。

ポートの操作方法としてはこうなる。
主にAVRstudioで用意されている、BVマクロを使って処理する。

ポートをHighに設定する。
DDRC = 0x00;

ポートをLowに設定する。
DDRC |= _BV(bitSCL);      //出力に設定
PORTC &= ~_BV(bitSCL);    //Lowを出力

デバイスのリセット動作のために作成したコードがこれ。

 //I2Cリセット処理
 DDRC = 0x00;    //input
 //p1 start
 //Low
 DDRC |= _BV(bitSDA);   //output
 PORTC &= ~_BV(bitSDA); //set low
 _delay_us(10);
 
 //p2 SCL 空うち
 for(i=0;i<63;i++){
 //Low
 DDRC |= _BV(bitSCL);   //output and
 PORTC &= ~_BV(bitSCL); //set low
 _delay_us(50);
 PORTC |= _BV(bitSCL); //set high
 //High
 DDRC &= ~_BV(bitSCL); //SCL to high
 _delay_us(50);
 }
 //p3
 DDRC &= ~_BV(bitSDA);   //set high
 _delay_us(10);

ディレイの長さがクロックにしては長すぎるので、
適当に調整されたし。

<<適当なWAITの作成>>
大抵Delay関数を使う。 delay関数を使うときは、必ずこのdefine文を忘れずに。

#define F_CPU 8000000UL

_delay_us(10);
とやれば10usのディレイが挿入される。

最適化レベルによって時間の長さが変わったりするので、最適化レベルを0にしてforループでwaitを作ったほうがかえって簡単なこともある。

2013年8月 2日 (金)

I2Cのトラブルシューティング 通信における様々なトラブル事例

トラブルシューティングリストを作成。

これがまず第一前提。
・通信するデバイス同士のGNDがつながっているか確認すること。
・プルアップ抵抗がついているか。
・電源電圧は適切か? AVRは5VでARMは3.3Vということは良くある。

I2C通信プロトコル自体の仕様を確認したいときは、下記のようなHPが参考になった。

ここの図は見やすい。
やまねこのマイコン実験室

I2Cで失敗する。対処法 スレーブアドレス後にNACKが返ってくる症状

この資料の 「通信中断後のリセット」 マスター側電源投入後に実施推奨。 SDAを開放してからSCLを空打ちする。 セイコーのI2C読み込み式リアルタイムクロック


何か不具合があったら、まずはわかりやすいところ。ハードウェアから順番に確認していく。GNDの配線忘れは、ブレッドボードで実験しているときに結構やってしまいがち。マイコン専用のブレッドボードエリアを用意しておいて、一度配線したらいじらないようにするなどの対策が有効。

プルアップ抵抗は周波数が高くなる場合は10kΩより小さくする場合がある。オシロを使って抵抗値を確認したほうがよい。100kHzでやっている分には10kΩでも5kΩでも変わりはない。

オシロを使って波形を見ることは大事ではあるが、それ以上に、表示されている波形の意味を正しく理解できるようにI2Cの仕様を理解しなければならない。ACK、NACK。ACK応答とNACK応答。この辺りが少し注意が要る。

ソフトについてのデバッグ。
つまずいたら、正常に動くところまで動かしてストップさせてみる。LPCならデバッガで任意のところにブレークが掛けられる。そのときにステータス値が正しいか。これに対応する処理が正しくコーディングされているかを確認する。

デバッガが使えないマイコンについては、while(1)とLEDを駆使すれば、時間はかかるものの処理1ステップごとにデバッグできなくはない。マイコン内部の状態を知るための手段をまず用意することが、かえって近道になる。





2013年7月25日 (木)

LPCXpresso LPC1114のI2Cを使う。LPCのマスター送信。

先にサンプルソース

<AVR側のスレーブ受信>
I2Cで受信したデータをUSARTで送信。
「i2c_slave_tameAwithARM.c」をダウンロード

確認デバイスはATmega328, 内蔵8MHz,clk1/8divはdisable。
注意:書き込みツールのコネクタを抜かないとI2Cが動かない。


<LPC側のマスター送信>
送信バッファにデータを用意し、20バイトを連続送信。

--------------------------

<LPC側マスター送信プログラム 変更が必要な箇所>
このソースについては著作権やらが関わるかもしれないので、編集が必要な箇所だけ順に記載します。

driverフォルダの、i2c.hというソース。
PCF8594_ADDR というdefineが送信先スレーブアドレス。紛らわしいのでプロジェクト内で名前を変えてしまってもよい。値は0x40を設定する。

おなじくdriverのi2c.cというソース。
I2CInitという関数の中にReset registersという箇所がある。ここでI2Cのビットレートを設定している。下記のレジスタを設定する。

  LPC_I2C->SCLL   = 240;
  LPC_I2C->SCLH   = 240;

これでビットレートが100kHzに設定される。

最後に、i2c_main.cでSLA(R)の部分をコメントアウトしてSLA(W)、スレーブへの送信処理だけにする。とりあえずこれだけでも通信は走るはず。

データを変更したければI2CMasterBuffer[ ]に入れる値を変えればよい。

2013年7月22日 (月)

LPCXpresso LPC1114でシリアル通信をする。

シリアル通信といえばI2C、SPI、UARTと色々あるが、RS232Cのレベル変換ICとPC接続用のコネクタがあれば直ぐに動作確認ができる点でUARTが一番難易度が低いように思う。ここではUARTの使い方をメモ。

実はこのテーマについては、エレキジャックさんのページに掲載されている。このリンクからUARTのコーディングについて書かれているページに飛ぶが、その前の下準備としてCMSISという空のプロジェクトを読み込む作業がある。

CMSISとはペリフェラルへのアクセスをするためのAPIを定義したもので、これをダウンロードしてプロジェクトとして読み込む必要がある。その方法が、"LPCXpresso で UART シリアル通信 (6)"で紹介されているので参考されたし。


手順どおりコードを打ち込んだが、コンパイルが通らなかった。

Linker CRP Enabled, but no CRP_WORD provided within application

こんなエラーが出て止まる。リンカが悪さをしているようだと思い、Cコンパイラの設定云々を調べて見た。しかし、そもそもCPRという単語自体探し当てられず。この単語をネット検索した。XPressoのベンダーであるcode_redのHPに載っていた。


このようなコードを追加してやればコンパイルが通ると書いてあった。

#include <NXP/crp.h>
__CRP const unsigned int CRP_WORD = CRP_NO_CRP ;

ハードウェア面でのつまずきポイント

XPRESSO基板の電源ラインを使ってシリアルのコネクタを配線したら、変換icの電源が供給されず、これで通信できなかった。

フリーソフト「あくのりっち」では、正常に電源が入っていればCTSが点灯するのでわかるはず。





2013年7月19日 (金)

LPC1114のI2Cを使う 仕様書を読み込む

ユーザーマニュアル(UM10398.pdf)を読んでいて気づいたのだが、AVRの仕様書とそっくり。通信の各工程ごとにステータスレジスタが返す値はAVRのときと同じだった。図も似ている。AVRで四苦八苦したことは無駄にならなかった。

15.7.5.1 Selecting the appropriate I2C data rate and duty cycle ここにクロックを設定するための式と、各レジスタに設定すべき値が載っている。クロックのDutyを設定するらしい。

15.8 I2C oparating modes ここからマスター・スレーブの送受信のモードについて、時系列の図で説明されている。

15.11 Details of I2C operating modes ここからマスター・スレーブのモードに分けて、より詳しい処理内容が書かれている。Table233.に略記号の説明あり。

マスター送信モードのところを見てみると、送信開始やモードのイニシャライズはI2C0CONSETというレジスタにビットを立てて行うらしい。AVRでいうところのTWCRにあたるレジスタと理解できる。その後に続く記述も大体AVRと内容が似ている。

15.11 Software example の項に、処理の流れが文章化されている。一から処理を書くときは、これをソースにコメントとして貼り付けてコーディングしていけば上手くいきそう。

ここに行けば日本語マニュアルも用意されている。
細かな文章はこちらで読みながら、ステータス値や図を英語の仕様書でウインドウを並べてみれば丁度よい感じ。
http://www.nxp-lpc.com/images/LPC111x_UM_Rev.00.15_Japanese.pdf





2013年7月 9日 (火)

LPCXpressoのプロジェクト管理

ARMはAVRとは比べ物にならないくらい大規模で複雑。
毎回ペリフェラルやクロックの設定をするのは大変なので、サンプルプロジェクトをコピーし、それをベースとして必要な処理を記述していく。


サンプルプロジェクトの読み込み方法は、

1.左のペインのStartHereから。
  Import Projectを押す。

Ws000061

2.unpackedの欄に、解凍済みのexampleフォルダを指定する。

Ws000067



3.ExistingProjectsを選ぶ。
ワークスペースに追加したい、つまりコンパイルに使いたいプロジェクトにチェックを入れてFinishを押す。

Ws000063


4.
左上のペインが こんな画面になれば、作業準備は完了する。

Ws000064



<<実践編>>

サンプルプロジェクトをコピーすると、当然プロジェクト名を変更したくなる。しかしフォルダ名を直接リネームすると、Xpressoから読めなくなってしまうなどの不都合が生じる。

ではどうするか。
1.Xpressoで名前を変えたいプロジェクトを一旦開く。
2.プロジェクトのフォルダアイコン上で右クリック
3.長ーいポップアップメニューが出てくるので、Renameを選ぶ。
4.名前を入力する。

他の、自作プロジェクトについても同じ。Windows上からフォルダをコピーしたりプロジェクト名を変えたりすると、Xpressoから読めなくなる。ソースの追加廃止も同じで、勝手に消すとXpressoからはまだあるように表示され、コンパイルすると、その消したファイルにアクセスできない。とエラーがかえされる。追加しなおすのも非常に手間がかかる。

このため、プロジェクトやファイルをコピーするときは必ずXpresso上から操作すること。
何か操作をする際は、対象とするプロジェクトを一旦開く。という操作が必要。

ここが非常に特殊で、扱いづらいところ。


----------------------------------------------------------

LPCに関する本は少ないですね。

完全版 世界の定番ARMマイコン 超入門キット STM32ディスカバリ: デバッガ搭載&はんだづけ不要!Cortex-M3をホントに始められる (トライアルシリーズ)

        島田 義人,永原 柊 CQ出版 2011-11-16
        売り上げランキング : 233417
by ヨメレバ

2013年2月16日 (土)

LPCXPresso LPC1114のクロック周波数 設定方法の詳細

LPCXPressoのLPC1114におけるクロック周波数の変更方法。

☆ユーザーマニュアル(UM10398.pdf)をダウンロードし、これを見ながら参照されたし。

Table.46にPLL configuration exampleという表があり、ここでLPCに設定できるクロックの例が書いてある。この例に沿ってレジスタを書き込めば、所望のクロックでCPUを動かせる。



クロックの設定は、CMSISのフォルダのsrcに入っている、system_LPC11xx.cで行っている。今使っているのはCMSISv1p30_LPC11xxで、プルダウンでsrcのフォルダを探すと見つかる。

中身の結論を先に言うと、サンプルプログラムのデフォルトでは最速の48MHzが設定されている。このクロックはXpresso基板上の12MHzのクリスタルを逓倍して作りだしている。

クロック信号の経路としては、このブロック図の赤線のようになる。丸で囲ったレジスタが設定のキーポイントになる。

Lpc1114clocksrc_2


そしてデフォルトのソース(system_LPC11xx.c)内では、下記のようになっている。

#define SYSPLLCLKSEL_Val      0x00000001
#define SYSPLL_SETUP          1
#define SYSPLLCTRL_Val        0x00000023
#define MAINCLKSEL_Val        0x00000003

一つずつ解析していくと、

・SYSPLLCLKSEL を1にすると、System oscillatorつまり外付けクロックをセレクトする。
 尚、内蔵オシレータを使う場合はIRC oscillatorなので0x0を設定。

・SYSPLL_SETUP でPLLを使用するをセレクトしている。

・SYSPLLCTRL   は少し複雑。

  まず、SYSPLLCTRLの0~4ビット目までの5ビットはMSEL。
  そして6,5ビット目の2ビットはPSELとなっている。
  今の0x00000023は、ビットに直して考えると下5ビットが3なので、MSELには3が。
  その次の2ビットは01だからPSELは1が入っていることになる。

Lpc

 わかりにくいので図にしてみた。サンプルソースには、いきなり16進数でレジスタに値を入れたりしているので理解しづらい。しかし、こうしてビットに分けて一つずつ噛み砕いていくと、何をやっているかがつかめる。また良くある書式で[0:4]というのがある。マイコンの仕様書では何の断りもなく使われていたりするけれど、0~4bit目という意味。



24MHzに設定したければ、先ほどのPLL configuration exampleの表から必要な値を選んでビットを設定すればよい。この表の上から3段目がそう。

Ws000053

表から、
MSEL bits = b'00001
PSEL bits = b'10


とあることから、下記のように設定すればOK。

#define SYSPLLCLKSEL_Val      0x00000001
#define SYSPLL_SETUP          1
#define SYSPLLCTRL_Val       
0x00000041
#define MAINCLKSEL_Val        0x00000003



尚、クロックは内臓の12MHzの倍数にしか設定できない。細かな刻みに設定したければクリスタルをつないで、そのクリスタルの周波数倍にする形で設定しなければならない。





--------------------------------------------------------------------

Linux搭載のARMマイコンボード
簡単にWebサーバーが構築できるらしい。

誰でもできる! Raspberry Piで楽しもう (日経BPパソコンベストムック)

        日経Linux 日経BP社 2013-06-29
        売り上げランキング : 1290
by ヨメレバ

LPC1114のXPressoとりあえずの使い方。デバッグ、ブレークポイントの設定方法など。

LPC1114のXPresso基板をとりあえず動かすための手順を説明。XPresso基板を買ったらXPresso基板と英語サイトへのアドレスが書いた紙切れしか入っていない。本当に動かすだけならUSBを挿すとLEDチカチカが実行される。そこからどうやってやりたいことを実現するか。

1.まずはこのZIPファイルを落としてくる。
 ” lpcxpresso.examples.lpc1114.302 ”

ここに行くとダウンロードできる。Attributesという青い四角の下にある、小さーい文字のリンクがそのファイル。
http://www.element14.com/community/solutions/5332


2.XPressoを立ち上げて、左下にあるStartHereペインから、ImportProjectを押す。
 下の画像の、上から二番目のアイコン。

Ws000068


3.押したら、下のような画面が出てくる(クリックで拡大できます。)
 RootDirectoryの欄の右のBrowsから”lpcxpresso.examples.lpc1114.302”のフォルダを選んでNEXTを押す。

Ws000067


4.すると下のような画面が出る。最初は全てのプロジェクトが選択されていて、Finishを押すと全てがロードされてしまってXPressoの操作が重くなる。そこで、Deselect ALLを押して選択を全解除してから、必要なプロジェクトだけ選んでからFinishを押すのがよい。プロジェクトの選択は、プロジェクト名の左端にあるチェックボックスを押す。

Ws000069


<コンパイルの仕方>
メインメニュー→Project→Build All またはBuild Allボタンを押す。


<デバッグの仕方、プログラムの実行>
基板をUSBでつないだ状態で、緑の虫マークがついたボタンを押す。コンパイルが通ればそのまま基板にプログラムが書き込まれる。ほどなくしてソースのメイン関数一行目などにカーソルが来て停止する。

ここからStepIntoボタンやStepOverでデバッグができる。再生(Run)ボタンを押せばスタート。四角(STOP)ボタンを押すとデバッガとの通信が終了して、デバッグモードが解除される。

デバッグの操作は他のIDEとほとんど同じ。ただXPresso環境はUSBをつないだだけで、プログラム実行中のレジスタの内容も実機でみることができる。あまり動作は速くないが、割り込みハンドラへのジャンプの様子も逐一みることができるので面白い。


<ブレークポイントの設定方法>

どこにも載っていなかったのでついでにメモ。
下のようなソース画面の左端に、青い帯のようなエリアがある。ここをダブルクリックすると小さい青丸のマークが追加される。幅が小さいので非常に押しにくい。改善して欲しい所。

Ws000066


<ペリフェラルやレジスタの値を見るには?>
メニューからDisplayなどとやるのかと思ったら、メインメニューからは見つけられなかった。実は左にあるProjectペインの横に、タブが並んでいて、これを押すとペリフェラルの画面が出るようになっている。ちょっと不親切。

Arm_xpressoperiph

ペリフェラルのチェックボックスを押すと、その中身が何故か一番下のペインに表示される。

Ws000072

レジスタの設定値が一目でわかって見やすいし、Valueのところをダブルクリックで書き換えることができる。LPCXpressoならこれらの操作が実機で実行しながらできる。レジスタをいじり放題なので、モジュールの色々な挙動を試すことができるだろう。