前回はひさびさのマイコン工作の開始という事でPIC16F88で割り込みを学びました。
ACモーターのフィードバック制御まであとはLCD表示とA/D変換を学ぶのみです。
んで今回は難易度がグッと上がるLCDを表示させるという挑戦をします。
ちなみにこんな感じでLCD表示させる事に成功〜!!!!
今みたらLCD デ ユミ ムゲンダイってなってますね。 本当はユミ→ユメです。
使ったものはLCDパネルのSC1602です。ちなみにバックライトがついてるのもを秋月で500円でゲット
ピンの配置
まず最初の感想は、こんなたいそうな物本当に表示させれるようになるんかいな?と正直思いました。
ネットでは結構情報もあるのですが、いまいち良くわかりませんでした。
しかし根気よく他サイトを読み込んでいくと・・・
なんとなーくやりかたがわかってきたのです。
PICでLCD表示させるということ
さてどのようにPICでLCDを表示させるかですが、もちろんのことPICのI/Oポートからの出力の切り替えによって文字データや数字データを出力します。
その取り決めはすでに決まっていて、私たちが自由に決める事はほぼありません。
そうです、表示させる取り決めや手順などは、あらかじめ決められていてその通りにプログラミングすればいいだけなんです。
難しいのは開発環境やプログラミング言語の違いで若干迷うというだけで基本的な方法は一緒です。
私の場合は王道のMPLAB X IDEの開発環境でC言語でプログラムしています。
大いに参考になったサイトはディスプレイ表示の基本を解説している ここ
PIC16F84Aを用いていますが、参考になるプログラムソースを公開している ここ 実際私はここのプログラムを少しいじらせてもらい、使っています。
PICでLCD表示する時に難渋する事
間違いなくムズイのはLCDパネルの初期化です。
まずLCDパネルを使うようにするにはPICのプログム上でPICを表示させる為に”初期化”させないと使えません。
その初期化がややこしくて、電源立ち上げ後数msecまってLCDのDB4−DB8にこのビットを送ってそのあと数ミリsec待って・・・めんどくさいんです。
でもこの世の中便利でそのような手順のソースコードをまとめてくれて、そのソースをインクルード(読み込む)するだけで簡単に使えるように公開してくれる先人達がいます。
ありがたーく使わせてもらいます。
ちなみにそのソースはこちらです。このソースはC言語でPIC16F84A用です。
試しにこのプログラムでPIC16F88でLCD表示させようと試みましたができませんでした。残念。最初にはまって嫌になりました・・・
しかしちょこっとプログラムを改造するだけでPIC16F88でも文字を表示させる事に成功しました!!!
回路図
LCD表示の方法は4ビットモードで。
クロックは便利な内部クロック1MHz
LCDは秋月で買った500円のSC1602を使用しました。
ソースの使い方
LCDの表示はなんだか難しそうですが、そうでもありません。
難しいプログラムは先人たちがソース化してくれており、私の様の相乗り精神満載の人が簡単に使えるようにしてくれています。
私の使命はその使い方を皆様に教授いたします。
とりあえずでしがMPLABXを使います。 知らないあいだにバージョンが3.4に上がっとります。
まず新規作成でプロジェクトをつくります。もちろんデバイスはPIC16F88を選んで、コンパイラーはXC8を選んでおきます。
MPLABXのざっくりした使い方はこちら
そして後のプログラムの解説の最後でダウンロードできるファイルをプロジェクトの中のヘッダーファイルとソースファイル下にドラッグ&ドロップさせます。赤線のところね。
そんでもってコンパイルするだけで、最初の映像のようにLCDを表示させる事が可能です。
メインプログラムを書き換えれば自由自在にLCDを使ったPIC電子工作の完成という手筈になります。
下記にプログラムの解説とLCD表示のワンポイントアドバイスを書いてます。
プログラムの解説
#include “lcd.h”をインクルードしているのでlcd.cの関数が使えます。
ちなみに
// LCD初期化
lcd_init();
で初期化を行い
// LCD画面クリア
lcd_cls();
画面のクリアは上記関数で行います。
文字を入力したい時は
// LCDに文字列出力
lcd_locate( 0, 0 );//これは文字の表示位置の設定です。(0,0)最初の0のところで1行目か2行目を設定1なら2行目です。
そんで次の0のところで何文字目から文字を表示させるかを決めます。SC1602は16文字表示なので0−15を入れる事になります。
lcd_puts( “Hello world” );
文字は上記で表示させます。半角英数と半角カタカナが表示させる事ができます。
また
#include<stdio.h>
#include<stdlib.h>
#pragma jis
の3つをインクルードした上で、メインプログム上で
////////////printf関数の出力先のスタブ関数を定義する////////////
void putch(unsigned char ch){
lcd_putc(ch);
}
を定義しておくと、なんとC言語でおなじみのpringf関数が使えます。かなり便利です。
結局のところ
lcd_locate( 0, 0 );
で文字位置を決めて
printf(“モジヲニュウリョク”);
で文字をLCDに表示させれるようになります。
メインプログラムでLCDに表示させる為に使う関数は上記2つで事足ります。
すごくないですか?
本当ならもっと面倒なんですよ。
あとPICのどのピンをLCDに割り当てるかなどの細かい設定は実際のプログラム中に書いています。
今回作成したプログラムですがダウンロードできるようにしておきまますね。以外とPIC16F88を利用したLCD表示を解説しているサイトがないので・・・
ダウンロードは右クリックで”名前をつけてダウンロード”でゲットしてね。
2017年2月20日 なんと外部発振でLCDを動かすと挙動がおかしくなることが判明しました。原因はlcd.cの中でstrobe(E)の信号を送る前と送ったあとの待ち時間が短い事に原因がある事が判明しました。なので修正する事でHSの外部発振でも使用可能になりました。千九!!
まずメインプログラムのソースです pic16f88deLCD
そしてLCDの初期化や書き込みなどのソースコード lcdkaizou
そんでそのソースの関数を使えるようにするヘッダーファイル lcd
この3つのファイルをダウンロードしてMPLAB X IEDでコンパイルするだけで使えます。
メインファイルを書き換えるだけで他の用途にも改造できるでしょう。
ファイトん!!
下記に全てのプログラムを載せておきまーす。
pic16f88delcd.c
/* * Author: kazurock #include <xc.h> // CONFIG2 /* ピン配列はこんな感じにしました。LCDを使うには4ビットモードで4つのピンを使います。ですのでRB4-RB7をLCDのDB4-DB7へ、RA6をLCD RS RA7をLCD Enableに設定しました。 ////////////printf関数の出力先のスタブ関数を定義する printfを利用するならこの記述がいります。//////////// void main( void ) PORTA = 0b00000000;// // LCD初期化 // LCD画面クリア // LCDに文字列出力 lcd_locate( 1, 0 ); __delay_ms(1000); //メインループ突入 //printfでLCDに文字列出力 lcd_locate( 1, 0 ); __delay_ms(1000); // LCD画面クリア
//カウントダウンを表示 本当はfor分などを使うとスッキリするのですが、勉強の為、たくさん書いてます。 // LCDに文字列出力 // LCDに文字列出力 // LCDに文字列出力 // LCDに文字列出力 // LCDに文字列出力 // LCDに文字列出力 // LCDに文字列出力 // LCDに文字列出力 // LCDに文字列出力 // LCDに文字列出力 } |
LCDのヘッダーファイル
lcd.h
このヘッダーファイルで定義された関数を使って文字を表示させます。
lcd_locate( 1, 7 );で2行目の8文字目から文字を入力指定
lcd_puts( “0” );で0を入力
#ifndef LCD_H #define LCD_H#ifdef __cplusplus extern “C” { #endif void lcd_init( void );void lcd_cls( void ); void lcd_locate( unsigned char x, unsigned char y ); void lcd_putc( char c ); void lcd_puts( const char *p );#ifdef __cplusplus } #endif#endif /* LCD_H */ |
LCDの初期化や書き込みなどをまとめたソースコード
lcd.c
もともとがPIC16F84A用のソースコードなのでそのままではLCD表示できません。
なので少し手を加えて書き直しました。っと言ってもほぼそのまま使っています。
手を加えたところだけ赤で書き直しております。
PIC16F88では初期化に時間がかかるみたいで、だいたいwait時間を決められた時間より5倍程度伸ばすとうまくいきます。
あと4ビットモードで使う為#define LCD_DATA_IS_HIGH //で partB上位を使うか下位を使うか決めます。HIGHのところをLOWなど他の言葉に入れ替えるとPORTB の下位から出力するようになります。
#include <htc.h> #include “lcd.h” #define _XTAL_FREQ 1000000 // __delay_ms()用クロック定義 (1MHz駆動) //—————————– // PIC-LCDのピンアサイン //—————————– #define LCD_RS PORTAbits.RA6//define関数でLCD_RSにRA6を指定 //#define LCD_RW PORTAbits.RA1 // 未使用 ちなみにLCDパネルのLCD_RWはグランドに落としておかいとLCDがうまく表示してくれません。 #define LCD_ENABLE PORTAbits.RA7//define関数でLCD_RSにRA7を指定 #define LCD_DATA PORTB #define LCD_DATA_IS_HIGH // PortBの上位4bitをLCDのDB4-7に接続// 内部関数のプロトタイプ宣言 static void lcd_write_cmd( unsigned char data ); static void lcd_write_databus( unsigned char data );//**************************************************************************************** // Function : lcd_init // Description: LCD初期化処理(4bitモード) //****************************************************************************************void lcd_init( void ) {//——————- // 制御ピンの初期化 //——————- LCD_RS = 0; LCD_ENABLE = 0; #ifdef LCD_DATA_IS_HIGH LCD_DATA = (LCD_DATA & 0x0f); #else LCD_DATA = (LCD_DATA & 0xf0); #endif__delay_ms( 500 ); // ウェイト500msにしてみる 300ms以上じゃないとうまくいかないよ //——————- // LCD初期化処理 //——————- lcd_write_databus( 0x03 ); __delay_ms( 20 ); // 4.1mSec以上ウェイトlcd_write_databus( 0x03 ); __delay_us( 500 ); // 100uSec以上ウェイトlcd_write_databus( 0x03 );// モードの指定 lcd_write_databus( 0x02 ); // 4bitモードに変更する __delay_ms( 2 ); // 40uSec以上ウェイト//——————– // 画面のクリア //——————– lcd_write_cmd( 0x28 ); // ファンクションセット(2行表示、5*7dot) __delay_ms( 2 );// Display off lcd_write_cmd( 0x08 ); // ディスプレイ・カーソルの設定(カーソル非表示) __delay_ms( 2 );lcd_write_cmd( 0x01 ); // clear display __delay_ms( 2 );lcd_write_cmd( 0x06 ); // エントリモード(1:右にスクロール、0:シフトなし) __delay_ms( 2 ); // lcd_write_cmd( 0x0F ); // ディスプレイ・カーソルの設定(ディスプレイ:ON, カーソル:ON , カーソル点滅:ON) writeData = 0x40 * x + y; // 表示位置を決定(2行目に出すときは,3bit目を立てる) lcd_write_databus( (c & 0xf0) >> 4 ); lcd_write_databus( (data & 0xf0) >> 4 ); // 書き込むべきデータをセット // Enableをactiveする
__delay_us( 230 ); //Enableを0にするまでに 220nSec以上→230μSec以上必要 // Enableをinactiveにする __delay_us(1);//10nsec以上必要
// データをALL0でクリアしておく } |
むちゃくちゃたくさん書きましたが、理解すると驚くほど簡単にLCD表示が可能になりPIC電子工作のリミッターをさらに上昇させる事になるでしょう。
あきらめずに頑張っていきましょう。