13 August 2012

PIC16F690でC言語(XC8)を使ってLCDに文字表示

中国のSure Electronicsから個人輸入したLCD(2002 LCD Module)に、PIC16F690を使って文字表示する。

日本国内の電子パーツ屋で購入すると500円~1000円ほどするLCDモジュールが、中国から個人輸入すれば送料込みで4米ドル(300円程度)と割安だ。ただし、説明書などは一切付いていないので、全て自力解決出来る自信が無ければ手を出さないのが吉。(そもそも、個人向け商品ではなく、工場などの生産現場へのパーツの卸売業)


■ 検証環境
・LCD : Sure Electronics 2002 LCD Module (20x2 Character)
・PIC16F690

・Microchip MPLAB X IDE ver 1.30
・Microchip MPLAB XC8 ver 1.01

20120813-lcd-breadboard.jpg
ブレッドボード上に作成したテスト回路

20120813-circuit.png
回路図

コントラスト調整用の半固定抵抗は、SD1602Hのデータシートによれば20kオームのものを用いているが、今回は10kオームしか手元に無かったのでそれを使っている。なお、Voは0.5V程度でちょうどよいコントラストになるようだ。

■ main関数部分


#include <stdio.h>
#include <stdlib.h>
#include<xc.h>

#include "lcd_lib.h"

__CONFIG(CP_OFF & CPD_OFF & BOREN_OFF & MCLRE_OFF & WDTE_OFF & PWRTE_ON & FOSC_INTRCIO);

#ifndef _XTAL_FREQ
/* 例:4MHzの場合、4000000 をセットする */
#define _XTAL_FREQ 4000000
#endif

/* printf関数の出力先のスタブ関数を定義する */
void putch(unsigned char ch){
lcd_putch(ch);
return;
}


int main(int argc, char** argv) {
OSCCON = 0b01100000; /* 内部オシレーター 4MHz */
TRISA = 0b00001000; /* IOポートRA0...RA5を出力モードに(RA3は仕様により入力専用) */
TRISB = 0; /* IOポートRB4...RB7を出力モードに */
TRISC = 0; /* IOポートRC0...RC7を出力モードに */
INTCONbits.PEIE = 0; /* 割り込み機能をOFF */
PORTA = 0; /* RA0...RA5をV-low */
PORTB = 0; /* RB4...RA7をV-low */
PORTC = 0; /* RC0...RC7をV-low */
CM1CON0 = 0; /* コンパレーター1 無効化設定 */
CM2CON0 = 0; /* コンパレーター1 無効化設定 */
ANSEL = 0; /* 全てのA/Dコンバータを無効化 */
ANSELH = 0; /* 全てのA/Dコンバータを無効化 */

__delay_ms(1000);

lcd_init();
lcd_goto(0);
lcd_puts("Initialize LCD ...");

for(unsigned int i=0; i<1000; i++)
{
__delay_ms(1000);
lcd_clear();
lcd_goto(0);
printf("%03d : Test Count", i);
lcd_goto(0x40);
lcd_puts("PIC 16F690");
}

return (EXIT_SUCCESS);
}

■ LCD共通関数

lcd_lib.h

#ifndef LCD_LIB_H
#define LCD_LIB_H

#ifdef __cplusplus
extern "C" {
#endif

void lcd_write(unsigned char c);
void lcd_clear(void);
void lcd_puts(const char * s);
void lcd_putch(char c);
void lcd_goto(unsigned char pos);
void lcd_init(void);

#ifdef __cplusplus
}
#endif

#endif /* LCD_LIB_H */

 

lcd_lib.c

#include <stdio.h>
#include <stdlib.h>
#include <xc.h>

#include "lcd_lib.h"

#ifndef _XTAL_FREQ
/* 例:4MHzの場合、4000000 をセットする */
#define _XTAL_FREQ 4000000
#endif

/* LCD_RS : データ制御ポート */
#define LCD_RS RC4
/* LCD_R/W : Read/Write選択ポート */
#define LCD_RW RC5
/* LCD_E : Eneble信号(この信号をHiにしている間、RS,R/W,Dataの送受信が行われる) */
#define LCD_EN RC6
/* データポート: LCD_DB4=RC0, LCD_DB5=RC1, LCD_DB6=RC2, LCD_DB7=RC3 */
#define LCD_DATA PORTC

/* ENピンの信号を一瞬プルアップしてデータ転送 */
#define LCD_STROBE() ((LCD_EN = 1),(LCD_EN = 0))

/* 4ビットモードでの8ビット分のデータ転送 */
void lcd_write(unsigned char c)
{
__delay_us(40);
LCD_DATA = (LCD_DATA & 0xf0) | ((c >> 4) & 0x0f);
LCD_STROBE();
LCD_DATA = (LCD_DATA & 0xf0) | (c & 0x0f);
LCD_STROBE();
}

/* 画面クリア */
void lcd_clear(void)
{
LCD_RS = 0;
lcd_write(0x1);
__delay_ms(2);
}

/* カーソル位置に文字列を出力 */
void lcd_puts(const char * s)
{
LCD_RS = 1; // write characters
while(*s)
lcd_write(*s++);
}

/* カーソル位置に1文字出力 */
void lcd_putch(char c)
{
LCD_RS = 1; // write characters
lcd_write( c );
}


/* カーソル位置の設定 */
void lcd_goto(unsigned char pos)
{
LCD_RS = 0;
lcd_write(0x80+pos);
}

/* LCDを4ビットモードで初期化 */
void lcd_init()
{
LCD_RS = 0;
LCD_EN = 0;
LCD_RW = 0;

__delay_ms(15); /* 15ミリ秒待つ */
LCD_DATA = 0b00000011; /* 一旦8bitモード設定(初期化) */
LCD_STROBE();
__delay_ms(5);
LCD_STROBE();
__delay_us(200);
LCD_STROBE();
__delay_us(200);
LCD_DATA = 0b00000010; /* 4bitモード設定 */
LCD_STROBE();

lcd_write(0x28); /* 2行表示モードに設定 */
lcd_write(0x0C); /* 表示ON,カーソルOFF,カーソル点滅OFF */
lcd_clear();
lcd_write(0x6); /* エントリーモード:左から右へ、シフト無し */
}

■ 参考にしたWebページ
液晶ディスプレイを使う - まずは表示してみる(4ビット操作) -
PICで気圧計 by 18LF2550 先ずは C言語 で LCD表示!
Hitachi HD44780 LCD controller (LCD制御コマンドがわからない場合は、Wikipediaのこのページで)
液晶表示モジュールを4ビットモードで使ったときの空きピン処理