2014年10月26日日曜日

AQM0802A を FRDM-KL25Z + CodeWarrior 環境で使用する


このエントリーをはてなブックマークに追加
秋月で I2C接続小型LCDモジュールピッチ変換キット (AQM0802A-RN-GBW ピッチ変換基板付き)を購入して、FRDM-KL25Z と接続して表示してみました。



紆余曲折ありつつ、最終的にはなんとか表示できたので、ハマったところのメモを残しておきます。
  • CodeWarrior (Processor Expert) の設定で入力する I2C スレーブアドレスは 0x7C ではなく 0x3E
    • 0x3E は 0x7C >> 1。アドレス部と Read/Write 部を独立して扱っているので、シフトしておく必要があります。
  • 初期設定例だと表示されない
    • コントラストの設定(初期化手順 4 番目)を例の 0x70 から 0x7f に変更すると見えるようになりました。
    • 供給している電源電圧の問題かもしれません。電源入力には FRDM-KL25Z の 5V 出力端子からの電圧を TA48033S で 3.3V にして使用しました。
  • 初期化コマンド間で Wait する
    • 長い時間が指定されている Wait の時間は 26.3uS ということで、特に気にしないで連続でコマンドを発行しても発行にかかる時間で Wait 時間がまかなえるかと思ったのですが、たまに通信に失敗することがありました。他の原因かもしれませんが、とりあえずコマンドの間に長めの Wait(1ms) を入れることで安定しました。

また、Control Byte の Co が若干わかりにくかったのですが、表示したい文字列を送る場合は 0 にして、それ以外の場合はコマンド1つ毎に STOP コンディションを発生させれ Co は 0 でも 1 でも良い、という扱いで良さそうです。コマンド間で Wait も必要なようですし。
仕様書には「データを複数送る場合 Co = 1 で、」とありますが、これは間違いですね。少なくとも Co = 0 にして文字列を送ることはできました。


以下にコードをベタ貼りしておきます。
(※ I2CMasterHelper_***、BusyWait は別の場所で定義した関数なので、このままでは使えませんが、参考程度に。)

#include "AQM0802A.h"
#include "I2CMasterHelper.h"
#include "PE_Types.h"
#include "PE_Error.h"
#include <stdio.h>
#include <string.h>

// co = 0 : Last Control byte to be sent. Only a stream of data bytes is allowed to follow.
// co = 1 : Another Control byte will follow the data byte (unless a STOP condition is received)
// rs = 0 : Send Command
// rs = 1 : Send Data
static byte ControlByte(bool co, bool rs){
 return (co << 7) | (rs << 6);
}

static void SendCommand(byte cmd){
 byte data[2];
 data[0] = ControlByte(FALSE, FALSE);
 data[1] = cmd;
 I2CMasterHelper_SendBlock(data, 2, LDD_I2C_SEND_STOP);
 I2CMasterHelper_WaitSendComplete();
 BusyWaitMS(1);
}

void AQM0802A_Init(){
 // 0x0011_1000 : DL = 1 : 8bit-bus mode, N = 1 : 2-line display mode, DH = 0 : font size is 5 x 8, IS = 0 : normal instruction 
 SendCommand(0x38);
 // IS = 1
 SendCommand(0x39);
 // Internal OSC frequency : 1/4 bias
 SendCommand(0x14);
 // Contrast Set : 000
 SendCommand(0x7f);
 // Power/ICON/Contrast control : ICON display off, Booster circuit on, contrast 10
 SendCommand(0x56);
 // Follower control : follower circuit on, follower amplified ratio = 100
 SendCommand(0x6C);
 
 // wait 200ms for power stable
 BusyWaitMS(200);
 
 SendCommand(0x38);
 // Display on, cursor off, cursor blink off
 SendCommand(0x0C);
 // Clear display
 SendCommand(0x01);
 
 // TODO: wait 1.08ms
 BusyWaitMS(2);
}

// first line address is  0x00 ~ 0x07
// second line address is 0x40 ~ 0x47 
void AQM0802A_DisplayChr(byte addr, char ch){
 // Test for now;
 byte data[4];
 
 // Set Address
 data[0] = ControlByte(TRUE, FALSE);
 data[1] = 0x80 | addr; // the first bit is always 1.
 // Set Character
 data[2] = ControlByte(FALSE, TRUE);
 data[3] = ch;
 I2CMasterHelper_SendBlock(data, 4, LDD_I2C_SEND_STOP);
 I2CMasterHelper_WaitSendComplete();
}

void AQM0802A_DisplayStr(bool secondline, char* str){
 byte data[11];
 
 byte length = strlen(str);
 if(length > 8){
  length = 8;
 }
 
 // Set Address
 data[0] = ControlByte(TRUE, FALSE);
 data[1] = 0x80 | ((secondline == TRUE)?0x40:0x00); // the first bit is always 1.
 // Set data
 data[2] = ControlByte(FALSE, TRUE);
 memcpy(data + 3, str, length);
 I2CMasterHelper_SendBlock(data, length + 3, LDD_I2C_SEND_STOP);
 I2CMasterHelper_WaitSendComplete();
}

void AQM0802A_ClearDisplay(){
 SendCommand(0x01);
}

0 件のコメント:

コメントを投稿