ご無沙汰してます。
今回ですが、STM32とバックライト付きI2C制御キャラク ターディスプレイ「ACM0802C-NLW-BBW-IIC」を組み合わせて様々な文字列をディスプレイに表示させてみたので、その過程を書いていきたいと思います。
やってて色々とハマりました。
ACM0802C-NLW-BBW-IICについて
秋月電子通商 で販売されている、バックライト付きの8文字x2列キャラク ターディスプレイ(I2C制御タイプ)です。
通販コード:P-13519
akizukidenshi.com
だいたいこの手のディスプレイって本来のインターフェースは8bitパラレルだったり4bitパラレルだったりするのですが、接続線が多いと煩わしいので、ディスプレイの更新速度ではやや不利になるものの今回はI2C制御タイプにしました。
最初から怪しい匂いが・・・
このディスプレイですが、データシート上にI2C通信に関する詳細な記述がありません。
秋月の商品ページには「データシートの8ページに記載がある」旨問い合わせに回答されていますが、本当に手順しか記載がなく命令レジスタ 等の記載は皆無です。
上記データシートを見ていると、4ページ目に「Contoroller IC: RW1063-0A or compatible」と記載があります。
つまり「RW1063-0A」なるディスプレイ制御ICのデータシートを入手する必要がありそうです。
RW1063-0Aデータシート入手
「これはどうしたものかなー」と思いつつRW1063-0AというICのデータシートを探していたら、同じく秋月電子通商 販売の「ACM2004D-FLW-FBW-IIC」というI2C制御キャラク ターディスプレイのページにRW1063-0Aのデータシートと思しきものが添付されていました。
通販コード:P-17381
akizukidenshi.com
これをもとに他のWebサイトでの実装例なんかも見つつ実際に文字列を表示させていきたいと思います。
追伸、「ACM2004D-FLW-FBW-IIC」のページにはArduino のサンプルスケッチを入手することもできます。一度に表示できる文字数もACM2004D-FLW-FBW-IICのほうが多いですからこれからディスプレイを使いたい人はこちらから始めるほうが難易度は低いかもしれません。
デバイス アドレスについて
ACM0802C-NLW-BBW-IICですが、コネクタの4番、5番ピンをプルアップまたはプルダウンすることでアドレスを4通りに設定できます。(ACM0802C-NLW-BBW-IICデータシート6ページに記載)
RW1063-0Aのデータシート28ページより抜粋
上図のSA0、SA1がそのアドレスに相当します。つまりデバイス アドレスは16進数(2進数)で
0x78 (0b01111000):SA1 = 0, SA0 = 0
0x7A (0b01111010):SA1 = 0, SA0 = 1
0x7C (0b01111100):SA1 = 1, SA0 = 0
0x7E (0b01111110):SA1 = 1, SA0 = 1
の4通りです。
デバイス アドレスの後に送るレジスタ アドレスは2通りです(RW1063-0Aデータシート28ページに詳細記載)。
0x00 (0b00000000):ディスプレイに何かしらの設定を送るとき
0x40 (0b01000000):ディスプレイの特定箇所の文字を設定するとき
RW1063-0Aデータシート中の"Control byte"中にあるA0ビットの違いで設定します。
設定データ
設定データについてはRW1063-0Aデータシート17ページに記載があります。
ここに記載された値をレジスタ アドレス0x00の後に送ることでディスプレイのオンオフや表示の消去などができます。
RW1063-0Aのデータシート17ページより抜粋
I2Cで制御する場合はRSやRWビットは無視します。(つまり、「Read Busy Flag and Address」の命令はI2C制御時はできません。)
AUDIYはこの命令のうち「Set DDRAM Address」にハマりました。 後ほど説明します。
文字データ
一般的な半角文字はRW1063-0A内部のROMに格納されていて、少なくともカタカナ以外はレジスタ アドレス0x40のあとに対応するASCIIコードを送るだけでその文字が表示されます。
e-words.jp
例えば、小文字のaを表示させたい場合は0x40のあとに0x61(10進数97)を送ればよいです。
プログラミングでうまいことやれば文字列をそのまま表示できそうです。
初期化
起動後のデバイス の初期化ですが、RW1063-0Aデータシートの32ページに手順が記載されています。
RW1063-0Aのデータシート32ページより抜粋
待ち時間まで指定されていますね・・・
文字列の表示について
実際にSTM32マイコン でI2C制御ディスプレイを動かすブログ記事があったので参考にしましたが、制御ICが違うためか見事にハマりました。
lawn-tech.jp
デバイス アドレスを送る
レジスタ アドレス(0x40)を送る
表示したい文字を送る
を繰り返せば文字列が表示できるようなコードに見えますが、実際にやってみても冒頭の1文字しか表示されません。
改めてRW1063-0Aのデータシートを読んでいくと、文字列表示にとても重要なことが12~14ページに記載されていました。
詳しくはデータシートを読んでいただくとして、ざっくり言うと「文字を表示したい場所をDDRAM Addressで指定しなさい」ということです。
今回使用するACM0802C-NLW-BBW-IICは8文字、2列のディスプレイなので、初期化終了時点で1列目のアドレスは0x00 ~ 0x07、2列目のアドレスは0x40 ~ 0x47とのことです。
このアドレスの変更をRW1063-0Aデータシート17ページに記載の「Set DDRAM Address」で行うということです。
つまり順序を書くと
レジスタ アドレス0x00にSet DDRAM Address命令(0b1xxxxxxx)命令を送って表示位置を指定
レジスタ アドレス0x40に表示したい文字を送る
の2つを繰り返すことで文字列表示が実現できます。
実現した動画は以下のとおりです。
ライブラリ関数の実装
いくつかのI2Cの送信について関数を作ったので解説します。
といっても設定や文字列表示に関する関数は3つです。
設定書き込み関数ACMWriteInstruction()
レジスタ アドレス0x00に対し代入されたデータを送信します。
/* Write Instruction */
uint8_t ACMWriteInstruction (I2C_HandleTypeDef * hi2c , uint16_t AD , uint8_t data ) {
uint8_t buf [ 2 ] = {INST_C0_0, data}; // 0x00, data
uint8_t status = HAL_I2C_Master_Transmit (hi2c, AD, buf, 2 , 1000 );
return status == HAL_OK;
}
文字書き込み関数ACMPrintChar()
現在指定されているDDRAMアドレスに対し文字*strを書き込みます
やっていることはACMWriteInstruction()関数とほぼ変わりません。
/* Print Single Character to the ACM0802C-NLW-BLW-I2C. */
uint8_t ACMPrintChar (I2C_HandleTypeDef * hi2c , uint16_t AD , const char * cdata ) {
uint8_t buf [ 2 ] = {WRITE_C0_0, * cdata}; // 0x40, *cdata
uint8_t status = HAL_I2C_Master_Transmit (hi2c, AD, buf, 2 , 1000 );
HAL_Delay ( 10 );
return status == HAL_OK;
}
※DDRAM Addressの更新は行いませんので注意してください。
文字列書き込み関数ACMPrintStr()
ディスプレイに対し入力引数LNで指定した行に文字列*strを入力します。 関数内部で行指定、文字数計算およびその文字数だけACMPrintChar()関数の繰り返しを行います。
/* Print 1-Line String (under 40 characters) to the ACM0802C-NLW-BLW-I2C. */
void ACMPrintStr (I2C_HandleTypeDef * hi2c , uint16_t AD , uint8_t LN , const char * str ) {
uint8_t LNx = DDRAM_LN1;
uint8_t str_len = 0 ;
uint8_t i = 0 ;
const char * startstr = str;
if (LN == 1 ) {
LNx = DDRAM_LN1; // DDRAM Address: 0x80
} else {
LNx = DDRAM_LN2; // DDRAM Address: 0xC0
}
str_len = strlen (str); // Count String Length.
if (str_len > 40 ) {
str_len = 40 ; // String Length must be under 40 per Line.
}
/* Print Characters in the string */
for (i = 0 ; i < str_len; i ++ ) {
ACMWriteInstruction (hi2c, AD, (LNx | i)); // Specify the DDRAM Address
ACMPrintChar (hi2c, AD, str); // Write the character the DDRAM.
str ++ ;
}
str = startstr; // Return *str pointer to start address.
}
その他にもディスプレイの初期化関数や、ディスプレイに設定されたI2Cデバイス アドレスを検索する関数を実装しています。
github.com
動かしてみる
上記リンク先の関数を組み合わせて文字列を流すプログラムを実装してみました。
流れとしては
CheckACMDeviceAddress()関数でI2Cデバイス アドレスの取得
InitACM()関数でRW1063-0Aの初期化
ACMPrintStr();で文字列を書き込み
ディスプレイの表示を開始
1秒ごとに文字列を左にシフト
文字列全てをシフトし終えたら最初の状態で表示し直す
5と6を繰り返す
という手順です。
まとめ
ということで秋月電子通商 で販売されているACM0802C-NLW-BBW-IICを使って文字列を表示させてみました。
まとめとしては
データシートの情報が不足している
DDRAMのアドレスの更新が文字列表示のカギ
ACM2004D-FLW-FBW-IICから始めるほうがオススメ
です。
今回作成したドライバ(HAL使用)はGitHub にアップロードしています。
MITライセンス(2条項BSDライセンス )で公開していますのでご自由にお使いいただければと思います。
github.com
また何か進捗があればブログを更新したいと思います。