ブレッドボード上で情報を表示したり簡易的なデバッグをしたりするのに便利なのがキャラクタLCD です。
今回は aitendo で販売されているこちらの LCD を使ってみました。
ちなみに以前秋月電子の LCD を使用した記事がこちらです。使い方はほぼ変わらなかったので詳しいことはこちらをご覧ください。
良い点
主に前述の秋月電子の LCD と比較した話になりますが、この aitendo の LCD のいい点として感じたのは以下のことです。
- 2.54mm ピッチ
- 十分小さいのに表示量が多い (16×2)
- 安い
- 逆さ表示が可能
まずはピッチですが、秋月のはピッチが細かく変換基板がほぼ必須と言えるのに対して、aitendo のは 2.54mm なのでとても使いやすいです。
次に表示量ですが、やはり秋月の 8×2 だと足りないと感じる場面が多い一方、16×2 あるととても使いやすいです。
次に値段の点ですが、秋月のは変換基板込みで 600円に対して aitendo は 300円とかなり安いです。(どちらもバックライト無し)
ちなみに、秋月にもこちらの 2.54mmピッチで 16×2表示の LCD があるのですが、450円します。
最後に逆さ表示が可能という点ですが、こちらは後ろの項目で説明したいと思います。
使い方
aitendo の商品ページに次の配線図があります。
1枚目の配線図にコンデンサが2個ありますが、VOUT のコンデンサは無い方が上手くいきました。(VOUT はオープン)
CAP1 のコンデンサには 1uF のコンデンサを使いました。こちらは必要です。
RESET は VDD に繋げておきます。
2枚目は要するに SHL と DIRC のピンを VDD または GND のどちらかに接続しろということです。
とりあえず SHL は VDD に、DIRC は GND に接続するといいです。
プログラムは最後に載せますが、こんな感じに無事表示させることが出来ました。
2枚目は VOUT に 1uF のコンデンサを繋げた場合で、理由はよく分かりませんが表示が薄くなりました。
ちなみに SHL と DIRC の接続を変えると、以下のように左右と上下が反転します。
最後の写真を 180° 回転させるとこのように逆向きに LCD を使えることが分かります。場合によっては便利かもしれません。
モジュール化
もともと 2.54mmピッチでそのままブレッドボードに挿せるのですが、必要以上に幅を取ってしまうので秋月の LCDモジュールを参考にモジュール化してみました。
外部と接続する必要のあるピンは VDD, GND, SDA, SCL の 4本だけです。
基板は同じく aitendo で丁度良いサイズのユニバーサル基板が売ってたのでこちらを使いました。
材料と完成品の写真です。
完成した後に気付きましたが、反転を切り替えられるようにしておけば、ブレッドボードの左側でも使えて便利だったかもしれません。
プログラム
最後に動作テストプログラムを紹介します。
前述した以前の記事で使用したライブラリを試してみたところ、何の問題もなく使えてしまったので、ここではプログラムを載せるだけにします。
ライブラリの詳細についてはこちらをご覧ください。
今回使用したマイコンは PIC16F18346 です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
#pragma config FEXTOSC = OFF // FEXTOSC External Oscillator mode Selection bits (Oscillator not enabled) #pragma config RSTOSC = HFINT1 // Power-up default value for COSC bits (HFINTOSC (1MHz)) #pragma config CLKOUTEN = OFF // Clock Out Enable bit (CLKOUT function is disabled; I/O or oscillator function on OSC2) #pragma config CSWEN = ON // Clock Switch Enable bit (Writing to NOSC and NDIV is allowed) #pragma config FCMEN = ON // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled) #pragma config MCLRE = ON // Master Clear Enable bit (MCLR/VPP pin function is MCLR; Weak pull-up enabled) #pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled) #pragma config WDTE = OFF // Watchdog Timer Enable bits (WDT disabled; SWDTEN is ignored) #pragma config LPBOREN = OFF // Low-power BOR enable bit (ULPBOR disabled) #pragma config BOREN = ON // Brown-out Reset Enable bits (Brown-out Reset enabled, SBOREN bit ignored) #pragma config BORV = LOW // Brown-out Reset Voltage selection bit (Brown-out voltage (Vbor) set to 2.45V) #pragma config PPS1WAY = ON // PPSLOCK bit One-Way Set Enable bit (The PPSLOCK bit can be cleared and set only once; PPS registers remain locked after one clear/set cycle) #pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable bit (Stack Overflow or Underflow will cause a Reset) #pragma config DEBUG = OFF // Debugger enable bit (Background debugger disabled) #pragma config WRT = OFF // User NVM self-write protection bits (Write protection off) #pragma config LVP = OFF // Low Voltage Programming Enable bit (High Voltage on MCLR/VPP must be used for programming.) #pragma config CP = OFF // User NVM Program Memory Code Protection bit (User NVM code protection disabled) #pragma config CPD = OFF // Data NVM Memory Code Protection bit (Data NVM code protection disabled) #include <xc.h> #include <stdio.h> #include "i2c.h" #include "lcd_i2c.h" #define _XTAL_FREQ 1000000 Init(){ TRISA = 0b00001000; ANSELA = 0; PORTA = 0; TRISB = 0; ANSELB = 0; PORTB = 0; TRISC = 0b00110000; ANSELC = 0; PORTC = 0; } void putch(char c){ lcd_DATA(c); } void main(void) { Init(); I2C_Master_Init(100000); lcd_Init(); printf("Hello World!"); lcd_SetCursor(1,0); printf("0123456789ABCDEF"); while(1); } |
▼I2Cライブラリ
1 2 3 4 5 6 7 8 9 10 |
void I2C_Master_Init(const unsigned long c); void I2C_Master_Wait(); void I2C_Master_Start(); void I2C_Master_RepeatedStart(); void I2C_Master_Stop(); void I2C_Master_Write(unsigned d); unsigned short I2C_Master_Read(unsigned short a); void SendI2C(char adrs, char data); void CmdI2C(char adrs, char reg, char data); void GetDataI2C(char adrs, char* buf, char cnt); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
#include<xc.h> #define _XTAL_FREQ 1000000 void I2C_Master_Init(const unsigned long c){ SSP2CON1 = 0x28; //SSP2 Module as Master SSP2CON2 = 0x00; SSP2CON3 = 0x00; SSP2ADD = (_XTAL_FREQ/(4*c))-1; //Setting Clock Speed SSP2STAT = 0x80; SSP2CLKPPS = 0x14; //PPS Settings SSP2DATPPS = 0x15; // SCL : RC4 RC4PPS = 0x1a; // SDA : RC5 RC5PPS = 0x1b; } void I2C_Master_Wait(){ while ((SSP2STAT & 0x04) || (SSP2CON2 & 0x1F)); //Transmit is in progress } void I2C_Master_Start(){ I2C_Master_Wait(); SSP2CON2bits.SEN = 1; //Initiate start condition } void I2C_Master_RepeatedStart(){ I2C_Master_Wait(); SSP2CON2bits.RSEN = 1; //Initiate repeated start condition } void I2C_Master_Stop(){ I2C_Master_Wait(); SSP2CON2bits.PEN = 1; //Initiate stop condition } void I2C_Master_Write(unsigned d){ I2C_Master_Wait(); SSP2BUF = d; //Write data to SSP2BUF } unsigned short I2C_Master_Read(unsigned short a){ unsigned short temp; I2C_Master_Wait(); SSP2CON2bits.RCEN = 1; I2C_Master_Wait(); temp = SSP2BUF; //Read data from SSP2BUF I2C_Master_Wait(); SSP2CON2bits.ACKDT = a; //Acknowledge bit 1:Not Ack 0:Ack SSP2CON2bits.ACKEN = 1; //Acknowledge sequence return temp; } void SendI2C(char adrs, char data){ I2C_Master_Start(); I2C_Master_Write(adrs<<1); //SlaveAdress + Write I2C_Master_Write(data); //mainly RegisterAdress I2C_Master_Stop(); } void CmdI2C(char adrs, char reg, char data){ I2C_Master_Start(); I2C_Master_Write(adrs<<1); //SlaveAdress + Write I2C_Master_Write(reg); //RegisterAdress I2C_Master_Write(data); I2C_Master_Stop(); } void GetDataI2C(char adrs, char* buf, char cnt){ I2C_Master_Start(); I2C_Master_Write((adrs<<1)+1); //SlaveAdress + Read for(char i=0; i<cnt-1; i++) buf[i] = I2C_Master_Read(0); //ACK buf[cnt-1] = I2C_Master_Read(1); //NACK I2C_Master_Stop(); } |
▼LCDライブラリ
1 2 3 4 |
void lcd_INST(char command); void lcd_DATA(char data); void lcd_Init(); void lcd_SetCursor(char row,char column); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
#include "i2c.h" #include <xc.h> #define _XTAL_FREQ 4000000 //#define CONTRAST 0x20 //for 3.3V #define CONTRAST 0x08 //for 5V const char lcd_DDRAM[4] = {0x00, 0x40, 0x14, 0x54}; void lcd_INST(char command){ I2C_Master_Start(); I2C_Master_Write(0x7C); //SlaveAdress + Write I2C_Master_Write(0x00); //Instruction I2C_Master_Write(command); //data byte I2C_Master_Stop(); __delay_us(30); } void lcd_DATA(char data){ I2C_Master_Start(); I2C_Master_Write(0x7C); //SlaveAdress + Write I2C_Master_Write(0x40); //Data I2C_Master_Write(data); //data byte I2C_Master_Stop(); __delay_us(30); } void lcd_Init(){ __delay_ms(40); lcd_INST(0x38); //Function Set lcd_INST(0x39); //Function Set lcd_INST(0x14); //Internal OSC Frequency lcd_INST(0x70 + (CONTRAST & 0x0f)); //Contrast Set lcd_INST(0x54 + ((CONTRAST & 0xf0)>>4)); //Power/ICON/Contrast control lcd_INST(0x6c); //Follower control __delay_ms(200); lcd_INST(0x38); //Function Set lcd_INST(0x0c); //Display ON/OFF control lcd_INST(0x01); //Clear Display __delay_ms(2); } void lcd_SetCursor(char row, char column){ //行、列は0番目から const char lcd_DDRAM[4] = {0x00, 0x40, 0x14, 0x54}; //各行の先頭アドレス char adrs = lcd_DDRAM[row] + column; //指定位置のアドレス lcd_INST(0x80 + adrs); } |
この記事は以上となります。最後までご覧いただきありがとうございます。