PSoC5LP I2C LCDをつないでみる

投稿日 2014/01/14

CQ出版の「基板付き体験編 ARM PSoCで作るMyスペシャル・マイコン」を購入し、付属基板のPSoC5LPをさっそく試してみました。

 

本に掲載されているLチカからRTOSを使用したUSBUARTまで試したあと、これからいろいろ実験するには、どうしても表示器としてキャラクタLCDがほしいので、I2C LCDのACM1602NIをつないでみました。

PSoC5LP_I2CLCD2.jpg

I2C LCDをつなぐには、PSoCが提供するI2CコンポーネントとI2C LCDコンポーネントを使う方法と、
I2Cコンポーネントのみ使用し、 I2C LCDコンポーネントは使わずソフトでコントロールする方法がありますが、今回は後者を使いました。

 

したがって、

 

使用するコンポーネントはI2Cコンポーネントのみです。
実際にはピンコンポーネントのSDA_1, SCL_1も使いますが、I2Cコンポーネントにすでに接続済になっています。
(I2C LCDコンポーネントは使いません)

 

このソフトコントロールの方法は、PSoC3で一度使っていますので、ソフトはほぼそのまま再利用しました。(「PSoC3 I2C LCDをつないでみる」を参照ください)

 

LCDを制御するには適当なディレイを入れる必要がありますが、cydelay()を使用せず、本に記載されている割り込みでTickをカウントする方式のディレイハンドラを使用しました。Delay()関数です。

 

開発環境はPSoC Creator 3.0です。

 

まずI2C Masterコンポーネントを組み込みます。名前はI2C_1です。

 

SCL_1にピンP12[0]、SDA_1にピンP12[1]を設定しておきます。

シールバッテリ簡易充電回路

PSoC5LP_I2CLCD1.jpg

クロック関係は、本の記載どおり66MHzにしています。

 

PSoC5LPボードには、40ピンソケットをCN1, CN2に半田付けしておきました。私の場合は拡張基板を使わないので、ソケットは上面に取り付けました。

 

配線は、Vdd(3.3V), Vss(GND)と、LCDのバックライトに3.3Vをつないでおきます。
SCLはピンP12[0]、SDAはピンP12[1]につなぎます。
SCL, SDAには10KΩのプルアップ抵抗をつないでおきます。

 

ソフトコントロールですので、LCDの制御はすべてソフトで行っています。

 

ACM1602NIのスペックに記載されている初期化方法通りで初期化します。

 

あとは通常のLCDと同じような制御を行います。

 

関数はI2CコンポーネントのGenerated Source I2C_1.cに含まれている関数を呼んでいます。

 

Delay()はほとんど1msにしていますが、面倒なのでチューニングしていません。これでも表示が遅いとは感じませんでした。


 

以下、参考ソースです。
// I2C LCD(ACM1602NI) Test
// Soft Control vertion
// JF1VRR 2014/01/14 V1.00A

 

//main.c
#include <project.h>

 

#define SLAVE_ADDRESS 0x50 //Slave(Right Justified)

 

volatile uint32 gTick = 0;

 

CY_ISR(SysTick_Handler){

gTick++;

}

 

void Delay(uint32 tick_delay){

uint32 tick_entry = gTick;
while(gTick - tick_entry < tick_delay);

}

 

void I2C_LCD_WriteCommand(char8 command){

I2C_1_MasterSendStart(SLAVE_ADDRESS, 0);
Delay(1);
I2C_1_MasterWriteByte(0x00);
Delay(1);
I2C_1_MasterWriteByte(command);
Delay(1);
I2C_1_MasterSendStop();
Delay(1);

}

 

void I2C_LCD_WriteChar(char8 databyte){

I2C_1_MasterSendStart(SLAVE_ADDRESS, 0);
Delay(1);
I2C_1_MasterWriteByte(0x80);
Delay(1);
I2C_1_MasterWriteByte(databyte);
Delay(1);
I2C_1_MasterSendStop();
Delay(1);

}

 

void I2C_LCD_SetPosition(uint8 col, uint8 row){ 

uint8 pos;

row != 0? (pos = 0xC0 + col) : (pos = 0x80 + col);
I2C_LCD_WriteCommand(pos);
Delay(1);

}

 

void I2C_LCD_WriteString(uint8 col, uint8 row, char *str){
I2C_LCD_SetPosition(col, row);
I2C_1_MasterSendStart(SLAVE_ADDRESS, 0);

while(*str){ 

I2C_1_MasterWriteByte(0x80); 
Delay(1);
I2C_1_MasterWriteByte(*str++);
Delay(1);


I2C_1_MasterSendStop();
Delay(1);
}

 

void I2C_LCD_ClearAll(void){

I2C_LCD_WriteCommand(0x01); //Clear Display

}

 

void I2C_LCD_ClearLine1(void){

I2C_LCD_WriteString(0, 0, " " ); //16 Space

}

 

void I2C_LCD_ClearLine2(void){

I2C_LCD_WriteString(0, 1, " " ); //16 Space

}

 

void I2C_LCD_Init(void){

I2C_LCD_WriteCommand(0x01); //Clear Display
Delay(3);
I2C_LCD_WriteCommand(0x38); //Function Set 8bit, 2line
Delay(1);
I2C_LCD_WriteCommand(0x0c); //Disp Cont Disp On, Cursor off, Blink off
Delay(1);
I2C_LCD_WriteCommand(0x06); //Entry Mode Set
Delay(1);

}

 

int main(){
uint8 i;

CyIntSetSysVector(15, (cyisraddress)SysTick_Handler);
SysTick_Config(BCLK__BUS_CLK__HZ/1000);
CYGlobalIntEnable;
I2C_1_Start();
I2C_LCD_Init();

for ( ;; ){
I2C_LCD_WriteString(0, 0, "12345ABCDEabcdef" );
for(i = 0; i < 16; i++){

I2C_LCD_SetPosition(i, 1);
I2C_LCD_WriteChar('*');
Delay(500);

}
Delay(2000);
I2C_LCD_ClearLine1();
I2C_LCD_WriteString(0, 0, "!#$%&'()-+=~|<>?" );
Delay(2000);
I2C_LCD_ClearAll();
}
}



 

(JF1VRR)