今回はI2C編です。さっそく始めます。下記の順で前準備して下さい。
- IDE起動
- PIC24FJ64GA002用のプロジェクト、”I2C_test”を作成
- MCC起動
今回の目標は、”I2C接続小型キャラクタLCDモジュール 16×2行 3.3V/5V(秋月電子さんで購入)に文字を表示する” です。それに向けて設定を進めます。PIC24FJ64GA002にはI2Cインターフェイスが2つ(I2C1、I2C2)有りますが、今回はI2C1を使う事にします。
- Device Resourcesの欄からI2Cを探し、黒い三角をクリック。表示されるリストからI2C1を選択
- Project Resourcesの欄に、”I2C1″が追加され、右側に設定画面が表示されます。
- 中央のHardware Settingsの画面
- ここで、I2Cの設定を行います。
- MasterやSlave。有効無効。通信周波数を設定出来ますが、今回は変更無しで進めます。
- 一番右のピン配置画面にI2C1で使用ピン、17,18が水色で表示されています。
- 今回は何も設定しないで Genarate ボタンを押してコードを作成しました。
- 中央のHardware Settingsの画面
次は、文字表示用ソフトの製作に入ります。
秋月さんのサンプルはArduino
秋月さんのHPのサンプルソフトをそのまま main.c にコピーして使おうと思ったのですが、残念な事にサンプルはArduino用でした。でも複雑なプログラムでは無いので容易にPIC用にコンバート出来ます。
main.c
/**
Section: Included Files
*/
#include "mcc_generated_files/mcc.h"
#define FCY 4000000UL
#include <libpic30.h>
#define LCD_ADRS 0x3E
char moji[] ="AQM1602XA-RN-GBW";
void writeCommand(uint8_t t_command)
{
uint8_t data[2];
I2C1_MESSAGE_STATUS pstatus;
data[0] = 0x00;
data[1] = t_command;
I2C1_MasterWrite(data, 2, LCD_ADRS, &pstatus);
__delay_ms(10);
}
void writeData(uint8_t t_data)
{
uint8_t data[2];
I2C1_MESSAGE_STATUS pstatus;
data[0] = 0x40;
data[1] = t_data;
I2C1_MasterWrite(data, 2, LCD_ADRS, &pstatus);
__delay_ms(1);
}
void CGRAM(){
int BAR[] = {0, 0x10, 0x18, 0x1c, 0x1e,0x1f};
int j,i;
writeCommand(0x40); // set CG RAM ADRESS
for(j= 0; j < 6; j++)
for( i = 0; i < 8; i++)
writeData(BAR[j]);
}
void init_LCD()
{
__delay_ms(100);
writeCommand(0x38); // FUNCTION SET
__delay_ms(20);
writeCommand(0x39); // IS=1
__delay_ms(20);
writeCommand(0x14); // INT OSC FREQUENCY
__delay_ms(20);
writeCommand(0x7A); // CONTRAST SET 0,1,2,3
__delay_ms(20);
writeCommand(0x54); // CONTRAST SET 4,5
__delay_ms(20);
writeCommand(0x6C); // F0LLOWER CONTROL
__delay_ms(20);
writeCommand(0x38); // IS=0
__delay_ms(20);
writeCommand(0x0C); // Display ON
__delay_ms(20);
writeCommand(0x01); // Clear Display
__delay_ms(20);
writeCommand(0x06); // Entry Mode
__delay_ms(20);
}
/*
Main application
*/
int main(void)
{
int i,j;
// initialize the device
SYSTEM_Initialize();
I2C1_Initialize();
init_LCD();
CGRAM();
writeCommand(0x02); // Retern Home
for( i = 0; i < 16; i++) writeData(moji[i]);
for( j = 0; j < 16; j++)
for( i = 0; i < 5; i++)
{
writeCommand(0x40+0x80+j); // ADRESS SET
writeData(i+1);
__delay_ms(10);
}
for( j = 0; j < 16; j++)
for( i = 0; i < 5; i++)
{
writeCommand(0x40+0x80+15-j); // ADRESS SET
writeData(4-i);
__delay_ms(15);
}
while (1)
{
// Add your application code
}
return 1;
}
/**
End of File
*/
- なるべく原型を残して変換しています。
- Arduinoの delay()関数をXC16の__delay_ms()で代用しています。
- 6行: define FCY 4000000UL
- FCYの宣言。 今回は4MHzなのでそれを指定。
- 7行: #include
- __delay_ms()はこのライブラリーに入っている様です。
- 6行: define FCY 4000000UL
- 4行目のヘッダーファイルの読み込みですが本来は、”system.h” でした。これではI2C関係の関数を呼び出す時にエラーが生じ、”mcc.h”に変更しています。”mcc.h”を読むと、今後は”system.h”になる ようなコメントが有りましたがどうなんでしょう。
これでコンパイルをかけると問題無く通りました。もちろん、main.c 以外のソースは変更していません。
ハードの準備
ハードを作る時点で、ピン変換基板の付いていないLCDをオーダーした事が分かりました。仕方なく秋月さんHPで変換基板の回路を元に自分で製作する事にしました。2.54ピッチの小さな基板にLCDの9本のピンを2列に互い違いに挿入してプルアップ抵抗以外の配線をLCDコネクター側にしました。プルアップ抵抗は本体側で配線します。最後にLCDから通信用の4本の線を出して配線終わりです。絶対、変換基板が付いたLCDがおすすめです。
PICとの接続は非常に簡単。
- 回路右のAQM1602XAがLCDです。LCDとの配線は下記の2ピンを接続したのみです。
- PICの17番ピンとLCDのSCL
- PICの18番ピンとLCDのSDA
- コネクター側に配線出来なかったプルアップ抵抗(10kx2)を本体側に配線しています。
- 後で気付いたのですが、PICにはプルアップ機能が有りそれを使えばこれらの抵抗は必要有りませんでした。
実行してもLCDに文字が出ない
コンパイルもPICへの書き込みも問題無く出来たのですが、LCDに全く文字が出ません。配線もコード変換も間違っていない事を確認しました。もう一度ソースを見ると、void init_LCD()関数 57,59行に、”// CONTRAST SET 0,1,2,3….” なるコメントが有りました。ここで明るさの調整をすると思いますが、調整の仕方が分かりません。でも秋月さんのHPに下記の資料が有りました。
- LCDの明るさはC5,4,3,2,1,0を利用して64段階で調整出来る
- 初期設定時に明るさを設定している例がある。
- これと void init_LCD() で書き込んでいる値とを比較すると以下の様になりました。
N | void init_LCD()での書き込みデータ | 資料のデータ |
---|---|---|
1 | 0x38 | 0x38 |
2 | 0x39 | 0x39 |
3 | 0x14 | 0x14 |
4 | 0x7A | 0x73 |
5 | 0x54 | 0x56 |
6 | 0x6C | 0x6C |
7 | 0x38 | 0x38 |
8 | 0x0C | 0x01 |
9 | 0x01 | 0x0C |
10 | 0x06 |
4番目、5番目がLCDの明るさを設定している箇所です。4番目の下位4ビット、5番目の下位2ビットがC5,4,3,2,1,0に当たります。ちなみに、ソフトのデータより資料のデータの方がC5,4,3,2,1,0の値が大きい事が分かります。そこで、資料の値を使って init_LCD() を実行しました。
- 変更箇所
- 57行: writeCommand(0x7A); → writeCommand(0x73);
- 59行: writeCommand(0x54); → writeCommand(0x56);
今度は問題無く実行出来ました。文字が表示されました。
次回は
今回は本題のI2C設定の説明よりLCDのデバッグに時間がかかってしまいました。LCDの表示には手こずりましたが、I2Cの設定は簡単に出来る事が分かりました。MCC様々です。次回ですが、今回文字を表示する事が出来る様になったのでRTCCを使って時計を作るのはどうでしょうか。できればの話ですが