
PSoC5LP I2C LCDをつないでみる
投稿日 2014/01/14
CQ出版の「基板付き体験編 ARM PSoCで作るMyスペシャル・マイコン」を購入し、付属基板のPSoC5LPをさっそく試してみました。
本に掲載されているLチカからRTOSを使用したUSBUARTまで試したあと、これからいろいろ実験するには、どうしても表示器としてキャラクタLCDがほしいので、I2C LCDのACM1602NIをつないでみました。

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]を設定しておきます。
シールバッテリ簡易充電回路

クロック関係は、本の記載どおり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)