2015年07月05日 | 公開。 |
ロジックアナライザでArduinoの信号を観察した例として、秋月電子のAQM1248Aという安価で小型の、128×48ピクセルのグラフィックLCDモジュールを、Arduinoで動かした時の話を書きます。話の過程で、LCDの制御に関するやや詳しい説明が出てきますが、それは本題ではないので、概略だけ理解してくだされば結構です。
このAQM1248Aは、SPI接続のLCDで、SPIインターフェースの信号線の内、MISOを除いた、/CS、SCK、MOSI、SSの3本の信号線と、SPIインターフェースで送信されている情報がコマンドなのかデータなのかを区別するRS信号の計4本の信号線で制御します。表1に、AQM1248Aの電源線および信号線の説明を示します。
電源線/信号線の名称 | 説明 |
---|---|
VDD | 電源線。2.4~3.6Vの電圧を印加する。 |
/CS | チップセレクト信号。AQM1248にコマンドやデータを送信する場合、Lに固定する。(SPIインターフェースの信号線のひとつ) |
/RESET | リセット信号。Lにすると、AQM1248Aに内蔵されている制御ICにリセットがかかる。このリセット信号を使わなくても、パワーオンリセットがかかるらしいので、明示的にリセットする必要がなければ、プルアップ抵抗でHに固定しても良い。 |
RS | SDIの信号線で送られている情報がコマンドなのか、データなのかを区別する。RSがHならデータ、RSがLならコマンドを送信中。 |
SCLK | SDIの信号線で送られるシリアルデータと同期したクロック信号。(SPIインターフェースのSCK信号) |
SDI | AQM1248Aに送信するデータを載せる、シリアル信号線。SCLKの信号線に同期してデータを送信する。(SPIインターフェースのMOSI信号) |
GND | グラウンド。 |
表2以外にも、チャージポンプ用のコンデンサを接続するピンや、LCDのバイアス電圧が出てくるピンがあるのですが、AQM1248Aの制御には関係ないので省略しています。
基本的にAQM1248AはSPIインターフェースを使って制御しますから(ただし、若干拡張されている)、この記事は、SPI信号をロジックアナライザで解析する方法の参考になると思います。
今回は、AQM1248Aをとりあえず動かしてみるという事で、次の写真の様なビットパターンを表示するテストを行いました。
上の写真の様なビットパターンを一度表示しただけでは、信号の観察に不便なので、ビットパターンの表示と画面の消去を交互に行うようにしました。
テスト回路の回路図を図5に示します。AQM1248を3.3Vで駆動するため、Arduinoからの5Vの信号線のレベル変換を、抵抗分圧で行っています。本来はレベル変換用のICを使う方が好ましいのですが、手持ちの部品で簡単に動作試験をしたかったので、抵抗分圧にしました。また、Arduinoとしては、Arduino Duemilanove互換のSeeeduino V3を利用しました。
なお、AQM1248は1.27mmピッチのピンが出ており、そのままではブレッドボードでの試験に使えないため、ピッチ変換キットを利用しています。このピッチ変換キットについている基板は、単にピンのピッチを2.54mmピッチに変換するだけではなく、チャージポンプ用のコンデンサや、/CSピンと/RESETピンに接続するプルアップ抵抗も搭載しているので、試作回路製作時の配線を大幅に簡略化できます。
余談になりますが、Seeeduino V3は、スイッチの設定で出力電圧を5Vから3.3Vに変更できますが、ATmega328Pを3.3Vで16MHz駆動すると、メーカーの保証範囲外になりますので、あえて5Vで出力してからレベル変換を行っています。
テスト回路の写真を次に示します。この写真に示す様に、テスト回路はブレッドボード上に組みました。
次に、Arduino上につけたヘッダシールド周辺の写真を示します。LCDの制御信号を観察するため、Arduinoの9、10、11、13ピンの信号を、ヘッダシールドのピンヘッダからロジックアナライザに接続しています。Arduinoのピンの信号を直接観察しているため、分圧前の信号を観察している事になります。
この記事の本題にはあまり関係ないですが、この記事を参考にご自分で追試される方がいらっしゃるかも知れないので、LCDの動作試験に使ったArduinoのスケッチを紹介しておきます。スケッチの具体的な内容については、別の機会に紹介する事になると思いますので、ここでは説明しない事にします。
なお、下のスケッチは、Arduino IDE 1.6.4で利用しました。Arduino IDE 1.0.Xでは、SPIライブラリの仕様が古いため、動作しませんのでご注意ください。
#include <SPI.h>
#define DI_PIN 9
#define CS_PIN 10
#define RATE 10000000L
void LcdCommand(uint8_t cmd)
{
SPI.beginTransaction(SPISettings(RATE,MSBFIRST,SPI_MODE3));
digitalWrite(CS_PIN,LOW);
digitalWrite(DI_PIN,LOW);
SPI.transfer(cmd);
digitalWrite(CS_PIN,HIGH);
SPI.endTransaction();
} // LcdCommand
void LcdData(uint8_t dat)
{
SPI.beginTransaction(SPISettings(RATE,MSBFIRST,SPI_MODE3));
digitalWrite(CS_PIN,LOW);
digitalWrite(DI_PIN,HIGH);
SPI.transfer(dat);
digitalWrite(CS_PIN,HIGH);
SPI.endTransaction();
} // LcdCommand
void InitializeLcd()
{
LcdCommand(0xae);
LcdCommand(0xa0);
LcdCommand(0xc8);
LcdCommand(0xa3);
LcdCommand(0x2c);
delay(2);
LcdCommand(0x2e);
delay(2);
LcdCommand(0x2f);
LcdCommand(0x23);
LcdCommand(0x81);
LcdCommand(0x1c);
LcdCommand(0xa4);
LcdCommand(0x40);
LcdCommand(0xa6);
LcdCommand(0xaf);
} // InitializeLCD
void setup() {
pinMode(DI_PIN, OUTPUT);
pinMode(CS_PIN, OUTPUT);
digitalWrite(CS_PIN,HIGH);
SPI.begin();
InitializeLcd();
}
void loop() {
for(int page=0; page<6; page++) {
LcdCommand(0xb0+page);
LcdCommand(0x10);
LcdCommand(0x00);
for(int x=0; x<128; x++) {
LcdData(0);
} // for x
} // for page
delay(1000);
for(int page=0; page<6; page++) {
LcdCommand(0xb0+page);
LcdCommand(0x10);
LcdCommand(0x00);
for(int x=0; x<128; x++) {
LcdData(x);
} // for x
} // for page
delay(1000);
}
前置きが色々と長くなりましたが、次のページでは、今回紹介した動作テスト回路を用いて、LCDの制御信号をロジックアナライザで観察します。