数字程度の簡単な表示であれば 7 セグメント LED で十分かもしれませんが、アルファベットを表示したり表示する文字が多い場合には、7 セグメント LED で頑張ろうとすると余計に苦労することになります。こういったケースでは、16桁×2行表示程度の LCD を用いると便利です。
起動してみたところ。画面に"Hello."と表示するだけ。ここを基点にセンサを接続したり色々遊べそう。
LCD ユニットに対してデータを送るには、決められた手順でポートを操作します。簡単に書けば;
これらの手順は別段、何かのクロックに同期する必要などないので、お手軽にプログラムを書くことができます。
また、手順 2. では 8 本のポートに 8 ビット分のデータをセットしていますが、これだとデータ線が 8 本も必要になりますが、PIC のように入出力ポートが少ないデバイスを使用する場合、使用するポート数はできるだけ節約したいものです。TC1602 には、4 ビットのデータを 2 回に分けて送受信できるモードが用意されているので、これを使わない手はありません。データ送信の操作を余分に行う分、プログラムが複雑になり、また処理時間を要しますが、これはデータ送信部分を関数化して対処します。また処理時間については、高々ミリ秒オーダーの話ですので、リアルタイム性能を要求されない範囲においては、問題になるようなことはありません。
#include <pic.h>
#define MHz 000000
#define _XTAL_FREQ (10MHz)
__CONFIG (
FOSC_HS // High Speed Crystal/Resonator
& WDTE_OFF // Watchdog Timer: OFF
& PWRTE_OFF // Power-up Timer: OFF
& CP_OFF // Code Protection: OFF
);
/************************************************************************
LCD 制御用関数群
************************************************************************/
// LCD と PIC との接続ポートのマッピング
#define LCD_PORT_RS RB0
#define LCD_PORT_E RB1
#define LCD_PORT_DB4 RB4
#define LCD_PORT_DB5 RB5
#define LCD_PORT_DB6 RB6
#define LCD_PORT_DB7 RB7
// LCD に 4 ビット分のデータを送信する
static void LcdPut4b (char RS, char data)
{
LCD_PORT_E = 0; // Enable Off
LCD_PORT_RS = RS; // Control Register
LCD_PORT_DB4 = data & 1;
LCD_PORT_DB5 = (data >> 1) & 1;
LCD_PORT_DB6 = (data >> 2) & 1;
LCD_PORT_DB7 = (data >> 3) & 1;
LCD_PORT_E = 1; // Enable On
NOP (); // Wait
LCD_PORT_E = 0; // Enable Off
}
// 1 バイトのデータを 2 回に分けて送信する
static void LcdPut (char RS, char data)
{
LcdPut4b (RS, data >> 4); // 先ず上位 4 ビットを送信
LcdPut4b (RS, data ); // 次に下位 4 ビットを送信
}
#define LCD_PUT_CTRL 0
#define LCD_PUT_DATA 1
// 1 バイトの制御データを送信する
static void LcdCtrl (char ctrl) { LcdPut (LCD_PUT_CTRL, ctrl); }
// 1 バイトの文字データを送信する
static void LcdData (char data) { LcdPut (LCD_PUT_DATA, data); }
// 液晶の初期化
static void LcdInitialize (void)
{
// 電源投入後、しばらく待つ
__delay_ms (15);
// LCD の初期状態がわからないので、強制的に 8bit 通信モードにするオマジナイ
LcdPut4b (LCD_PUT_CTRL, 0b0011); __delay_ms (5);
LcdPut4b (LCD_PUT_CTRL, 0b0011); __delay_us (100);
LcdPut4b (LCD_PUT_CTRL, 0b0011); __delay_ms (5);
// これで確実に 4bit 通信モードに設定できる
LcdPut4b (LCD_PUT_CTRL, 0b0010); __delay_us (40);
// 2lines, 5x8dots
LcdCtrl (0b00101000); __delay_us (40);
// Display On, Cursor On, Blink On
LcdCtrl (0b00001111); __delay_us (40);
// Clear Display
LcdCtrl (0b00000001); __delay_ms (5);
// Entry Mode
LcdCtrl (0b00000110); __delay_us (40);
// カーソル位置を設定
LcdCtrl (0b10000000); __delay_us (40);
}
/************************************************************************
LCD 制御用関数群
************************************************************************/
// PIC の初期化
static void Initialize (void)
{
TRISB = 0; //とりあえず全部のポートをデジタル出力に
}
// main
void main (void)
{
Initialize ();
LcdInitialize ();
// テスト文字列表示
LcdData ('H'); __delay_us (40);
LcdData ('e'); __delay_us (40);
LcdData ('l'); __delay_us (40);
LcdData ('l'); __delay_us (40);
LcdData ('o'); __delay_us (40);
LcdData ('.'); __delay_us (40);
while (1);
}
Hello."と表示します