さて、前回までで使いたいLCDの表示用関数がおおよそできたんだけど、プログラムのほとんどの領域をそれで占めていて、無茶苦茶見づらい…
なので、LCDの表示用関数を別プログラムに分けて、メインプログラムはそれだけに集中できるようにしたい。
まずは現状のソースファイルを別ファイル名で保存。
ヘッダーファイルも作らないといけないので一緒にコピーしておく。
端末でこんな感じのコマンドを打てばコピーできる。
エディタで開いて別ファイル名で保存でもいいかも…
cp lcdtest.c LCD_Ctrl.c
cp lcdtest.c LCD_Ctrl.h
さて、ヘッダーファイルの方から
正直あんまり書き方わからないから適当…間違っているかも…
けど一応コンパイルは通る(笑)
#pragma once
#ifndef MY_LCD_Ctrl_H
#define GPIO16 16 // E
#define GPIO17 17 // RS
#define GPIO18 18 // RW
#define GPIO19 19 // DB4
#define GPIO20 20 // DB5
#define GPIO21 21 // DB6
#define GPIO22 22 // DB7
#define LCD_E GPIO16
#define LCD_RS GPIO17
#define LCD_RW GPIO18
#define LCD_DB0 GPIO19
#define LCD_DB1 GPIO20
#define LCD_DB2 GPIO21
#define LCD_DB3 GPIO22
#define LCD_DB4 GPIO19
#define LCD_DB5 GPIO20
#define LCD_DB6 GPIO21
#define LCD_DB7 GPIO22
void LCD_GPIOPin_Mode_Set(void); //GPIO Pin mode set
void LCD_GPIOPin_AllOff(void); //GPIO Pin output all off
void LCD_DataEntCmd(void); // DataEntryCommand
void LCD_Clear(void); // 表示クリア
void LCD_Cur_home(void); // カーソルホーム
void LCD_Ent_Mode_Set(int,int); // エントリーモードセット
void LCD_Disp_Cnt(int,int,int); // 表示オン/オフコントロール(DispOFF=0,CursorOFF=0,BlinkOFF=0)
void LCD_Shift_Set(int,int); // カーソル/表示シフト(DispShiftOFF=0,CursorShiftOFF=0)
void LCD_Funk_Set(int,int,int); // ファンクションセット(IFData:4bit=0,Nunber2=1/1=0,Font5x10:1/5x7:0)
void LCD_DD_Adr_Set(int); // DD RAM アドレスセット(DD RAM Address)
void LCD_Initialize(void); // LCD 初期化用
void LCD_DataWrite(char); // 一文字書込み(Write Data)
void LCD_StrDataWrite(char*); // 文字列書込み(最大20文字まで)
void LCD_DataBufWrite(); //ディスプレイバッファから表示
void LCD_DataBuf(char*,int,int,int);//ディスプレイバッファに文字列書込み
// ディスプレイバッファ用配列変数
char DispBuf[2][20]; //ディスプレイバッファ
char DispData[2][20]; //ディスプレイ表示中データ
#endif
//-------------------LCD_Ctrl.hここまで-------------------
変数ってこんなところで宣言していいのかなぁ…うーん
次はLCD制御用のプログラム
// ヘッダーファイル
#include <wiringPi.h>
#include "LCD_Ctrl.h"
//ディスプレイバッファ制御
//ディスプレイバッファから表示
void LCD_DataBufWrite() {
int i; int k; // i:処理中文字場所,k:処理中行
k = 0;
for (i=0;i<20;i++) {
if(DispBuf[k][i] != DispData[k][i]) {
LCD_DD_Adr_Set(0x00 + i);
LCD_DataWrite(DispBuf[k][i]);
DispData[k][i] = DispBuf[k][i];
}
}
k = 1;
for (i=0;i<20;i++) {
if(DispBuf[k][i] != DispData[k][i]) {
LCD_DD_Adr_Set(0x40 + i);
LCD_DataWrite(DispBuf[k][i]);
DispData[k][i] = DispBuf[k][i];
}
}
LCD_GPIOPin_AllOff(); // Output data all off
}
//バッファに文字列書込み
// 引数1:書込み文字列へのポインタ
// 引数2:書き込む位置
// 引数3:文字列長
// 引数4:書込む行
void LCD_DataBuf(char *strData, int Pos, int Len, int Col) {
int i; int j = 0;
int flag=0;
//引数チェック
if (Pos > 19) Pos = 19;
if (Len > 20) {
Len = 20;
} else if ((Len + Pos) > 20) {
Len = 20 - (Pos);
}
//ディスプレイバッファに書き込み
for (i=Pos ; i < Pos+Len; i++){
DispBuf[Col][i] = strData[j];
j++;
}
//改行コードまたはヌルがあった場合はそれ以降をスペースで埋める
for (i=Pos ; i < Pos+Len; i++){
if (DispBuf[Col][i] == '\n' || DispBuf[Col][i] == '\0') flag =1;
if (flag == 1) DispBuf[Col][i] = ' ';
}
}
//DispDataWrite
void LCD_DataEntCmd(void) {
delay(1);
digitalWrite(LCD_E,1);
delay(1);
digitalWrite(LCD_E,0);
delay(0);
}
//GPIO Pin mode set
void LCD_GPIOPin_Mode_Set(void) {
pinMode(GPIO16, OUTPUT);
pinMode(GPIO17, OUTPUT);
pinMode(GPIO18, OUTPUT);
pinMode(GPIO19, OUTPUT);
pinMode(GPIO20, OUTPUT);
pinMode(GPIO21, OUTPUT);
pinMode(GPIO22, OUTPUT);
}
//GPIO Pin output all off
void LCD_GPIOPin_AllOff(void) {
digitalWrite(LCD_E,0);
digitalWrite(LCD_RS,0);
digitalWrite(LCD_RW,0);
digitalWrite(LCD_DB4,0);
digitalWrite(LCD_DB5,0);
digitalWrite(LCD_DB6,0);
digitalWrite(LCD_DB7,0);
}
//表示クリア
void LCD_Clear(void) {
digitalWrite(LCD_RS,0);
digitalWrite(LCD_RW,0);
digitalWrite(LCD_DB7,0);
digitalWrite(LCD_DB6,0);
digitalWrite(LCD_DB5,0);
digitalWrite(LCD_DB4,0);
LCD_DataEntCmd();
digitalWrite(LCD_DB3,0);
digitalWrite(LCD_DB2,0);
digitalWrite(LCD_DB1,0);
digitalWrite(LCD_DB0,1);
LCD_DataEntCmd();
}
//カーソルホーム
void LCD_Cur_home(void) {
digitalWrite(LCD_RS,0);
digitalWrite(LCD_RW,0);
digitalWrite(LCD_DB7,0);
digitalWrite(LCD_DB6,0);
digitalWrite(LCD_DB5,0);
digitalWrite(LCD_DB4,0);
LCD_DataEntCmd();
digitalWrite(LCD_DB3,0);
digitalWrite(LCD_DB2,0);
digitalWrite(LCD_DB1,1);
digitalWrite(LCD_DB0,0);
LCD_DataEntCmd();
}
//エントリーモードセット
void LCD_Ent_Mode_Set(int LCD_ID_in,int LCD_S_in) {
int LCD_ID = 0;
int LCD_S = 0;
if (LCD_ID_in != 0) LCD_ID=1;
if (LCD_S_in != 0) LCD_S=1;
digitalWrite(LCD_RS,0);
digitalWrite(LCD_RW,0);
digitalWrite(LCD_DB7,0);
digitalWrite(LCD_DB6,0);
digitalWrite(LCD_DB5,0);
digitalWrite(LCD_DB4,0);
LCD_DataEntCmd();
digitalWrite(LCD_DB3,0);
digitalWrite(LCD_DB2,1);
digitalWrite(LCD_DB1,LCD_ID);
digitalWrite(LCD_DB0,LCD_S);
LCD_DataEntCmd();
}
//表示オン/オフコントロール(DispOFF=0,CursorOFF=0,BlinkOFF=0)
void LCD_Disp_Cnt(int DispON_in,int CursorON_in,int BlinkON_in) {
int DispON = 0;
int CursorON = 0;
int BlinkON = 0;
if (DispON_in != 0) DispON =1;
if (CursorON_in != 0) CursorON = 1;
if (BlinkON_in != 0) BlinkON = 1;
digitalWrite(LCD_RS,0);
digitalWrite(LCD_RW,0);
digitalWrite(LCD_DB7,0);
digitalWrite(LCD_DB6,0);
digitalWrite(LCD_DB5,0);
digitalWrite(LCD_DB4,0);
LCD_DataEntCmd();
digitalWrite(LCD_DB3,1);
digitalWrite(LCD_DB2,DispON);
digitalWrite(LCD_DB1,CursorON);
digitalWrite(LCD_DB0,BlinkON);
LCD_DataEntCmd();
}
//カーソル/表示シフト(DispShiftOFF=0,CursorShiftOFF=0)
void LCD_Shift_Set(int DispShiftON_in,int CursorShiftON_in) {
int DispShiftON = 0;
int CursorShiftON = 0;
if (DispShiftON_in != 0) DispShiftON=1;
if (CursorShiftON_in != 0) CursorShiftON=1;
digitalWrite(LCD_RS,0);
digitalWrite(LCD_RW,0);
digitalWrite(LCD_DB7,0);
digitalWrite(LCD_DB6,0);
digitalWrite(LCD_DB5,0);
digitalWrite(LCD_DB4,1);
LCD_DataEntCmd();
digitalWrite(LCD_DB3,DispShiftON);
digitalWrite(LCD_DB2,CursorShiftON);
digitalWrite(LCD_DB1,0);
digitalWrite(LCD_DB0,0);
LCD_DataEntCmd();
}
//ファンクションセット(IFData:4bit=0,Nunber2=1/1=0,Font5x10:1/5x7:0)
void LCD_Funk_Set(int IFData_in,int LCD_Nunber_in,int LCD_Font_in) {
int IFData = 0;
int LCD_Nunber = 0;
int LCD_Font = 0;
if (IFData_in != 0) IFData =1;
if (LCD_Nunber_in != 0) LCD_Nunber = 1;
if (LCD_Font_in != 0) LCD_Font = 1;
digitalWrite(LCD_RS,0);
digitalWrite(LCD_RW,0);
digitalWrite(LCD_DB7,0);
digitalWrite(LCD_DB6,0);
digitalWrite(LCD_DB5,1);
digitalWrite(LCD_DB4,IFData);
LCD_DataEntCmd();
digitalWrite(LCD_DB3,LCD_Nunber);
digitalWrite(LCD_DB2,LCD_Font);
digitalWrite(LCD_DB1,0);
digitalWrite(LCD_DB0,0);
LCD_DataEntCmd();
}
//CG RAM アドレスセット…使わないので書かない
//DD RAM アドレスセット(DD RAM Address)
void LCD_DD_Adr_Set(int DD_Adr_in) {
int i=0;
int CalcData = 2;
int DD_Adr[8] = {0,0,0,0,0,0,0,0};
for(i=0; DD_Adr_in > 0; i++){
DD_Adr[i] = DD_Adr_in % CalcData;
DD_Adr_in = (DD_Adr_in - DD_Adr[i]) / CalcData;
}
digitalWrite(LCD_RS,0);
digitalWrite(LCD_RW,0);
digitalWrite(LCD_DB7,1);
digitalWrite(LCD_DB6,DD_Adr[6]);
digitalWrite(LCD_DB5,DD_Adr[5]);
digitalWrite(LCD_DB4,DD_Adr[4]);
LCD_DataEntCmd();
digitalWrite(LCD_DB3,DD_Adr[3]);
digitalWrite(LCD_DB2,DD_Adr[2]);
digitalWrite(LCD_DB1,DD_Adr[1]);
digitalWrite(LCD_DB0,DD_Adr[0]);
LCD_DataEntCmd();
}
//LCD 初期化用
void LCD_Initialize(void) {
LCD_GPIOPin_Mode_Set();
LCD_GPIOPin_AllOff();
delay(100);
//ini1(ここら辺だけコマンドの処理が長いみたいなので、タイマーは長めにしてみた)
digitalWrite(LCD_DB7,0);
digitalWrite(LCD_DB6,0);
digitalWrite(LCD_DB5,1);
digitalWrite(LCD_DB4,1);
LCD_DataEntCmd();
delay(100);
LCD_DataEntCmd();
delay(100);
LCD_DataEntCmd();
//init2
digitalWrite(LCD_DB7,0);
digitalWrite(LCD_DB6,0);
digitalWrite(LCD_DB5,1);
digitalWrite(LCD_DB4,0);
LCD_DataEntCmd();
LCD_Funk_Set(0,1,0); //init3(ファンクションセット:4bitIF,2行表示,5x7フォント)
LCD_Disp_Cnt(0,0,0); //init4(表示オンオフコントロール:表示オフ,カーソルオフ,ブリンクオフ)
LCD_Clear(); //init5(表示クリア)
LCD_Ent_Mode_Set(1,0); //init6(エントリーモードセット:表示シフトしない)
//初期化はここまで
LCD_Disp_Cnt(1,0,0); //表示オン(これ忘れると何やっても表示されない)
LCD_GPIOPin_AllOff(); //GPIOピン出力オールオフ
}
//一文字書込み(Write Data)
void LCD_DataWrite(char Data_in) {
int i=0;
int CalcData = 2;
int Data[8] = {0,0,0,0,0,0,0,0};
//ビットに展開
for(i=0; Data_in > 0; i++){
Data[i] = Data_in % CalcData;
Data_in = (Data_in - Data[i]) / CalcData;
}
digitalWrite(LCD_RS,1);
digitalWrite(LCD_RW,0);
digitalWrite(LCD_DB7,Data[7]);
digitalWrite(LCD_DB6,Data[6]);
digitalWrite(LCD_DB5,Data[5]);
digitalWrite(LCD_DB4,Data[4]);
LCD_DataEntCmd();
digitalWrite(LCD_DB3,Data[3]);
digitalWrite(LCD_DB2,Data[2]);
digitalWrite(LCD_DB1,Data[1]);
digitalWrite(LCD_DB0,Data[0]);
LCD_DataEntCmd();
}
// 文字列書込み(最大20文字まで)
// 1行目に文字列書込み(改行コードまで書込み)
void LCD_StrDataWrite(char *strData) {
int i=0;
for (i=0;i<0x13 && strData[i] != '\n' && strData[i] != '\0';i++) {
LCD_DD_Adr_Set(0x00+i);
LCD_DataWrite(strData[i]);
}
LCD_GPIOPin_AllOff(); // 全出力OFF
}
//-------------------LCD_Ctrl.cここまで-------------------
これで、LCD用のプログラムを分離できたはず。
こうなると、メインプログラムがどうなるかっていうと。
// ヘッダーファイル
#include <stdio.h>
#include <time.h>
#include <wiringPi.h>
#include "LCD_Ctrl.h"
int main(void) {
/* プログラムはここに記載する */
int i;
time_t timer;
struct tm *date;
// Initialize WiringPi
if(wiringPiSetupGpio() == -1) return 1;
//Initialize LCD
LCD_Initialize();
while(i<500){
timer = time(NULL);
date = localtime(&timer);
LCD_DataBuf(asctime(date),0,20,0);
LCD_DataBufWrite();
delay(10);
i++;
}
return 0;
}
こんな感じになるから、分かりやすくなる…かな?
コンパイルの仕方が少し変わって、
gcc -Wall -o lcdtest lcdtest.c LCD_Ctrl.c -lwiringPi
作ったLCD制御用のプログラムも一緒に書いてあげないといけないみたい。
これで、メインプログラムが減って管理がしやすくなったから
今度こそ、当初の目的、syslogの内容を表示させるプログラムを作っていこうと思う。