ホーム

電子工作

腕ロボット

二足歩行ロボット

無線コントローラ

工作機械

電子工作動画

自作ソフト(C言語)

Webページ作成

Javascriptゲーム

FLASHとは!

自学自習のテキスト

その他

PIC18F14K50で液晶モニタSD1602(2016年12月〜2017年1月)
 左が液晶モニタで、上がSD1602、下がSC1602です。

 電子工作をごちゃごちゃやっていると、その折々の状況を見たいことがあります。そういう時このような 超小型液晶モニタは便利です。

以前、H8マイコンを使っていた時、SC1602という液晶モニタ(左下)を使いました。

 今回はPICマイコンでの液晶モニタです。

H8マイコンとPICマイコンとは使い方が全然違いますので、液晶モニタに対してもそれなりの相手を しなければなりません。

 SD1602とSC1602の違いは、SDの方は12個の端子が左下に1列に並んでいることで、これによって ブレッドボードに直に挿せます。SCのほうは左に12個の端子が6個ずつ2列になっているので、 リードを出さないとブレッドボードに挿すことが出来ません。

 はんだ付けの手間を省くためにブレッドボードを使っているので、今回はSD1602(左上)を使います。

左の一番下の画像が実際にLCDに文字を表示した例です。
PIC18F45k50ボードを使っています。






 以前にH8マイコンでSC1602を使ったときは核心の部分でRIKIYAさんのプログラムをほぼコピペ でした。

 このLCDは4ビットモードがあるので、この4ビットモードでPICとつなぎます。
PICはピンの数が少ないので、この4ビットモードを使えば必要なピンの数が節約できます。
つまり、文字データのためのピンが4個、制御のためのピンが2個でPICのピンは合計6個で済みます。

 今回はSD1602のマニュアルを見て自力でプログラム作成をしようと思いました。

SD1602は、インターフェースICがHD44780コンパチブルです(SC1602もそうですが)。 秋月電子のページにあったマニュアルを印刷しました。しかし求める情報は何も書いておらず、別のサイトから HD44780の詳しいマニュアルを印刷しました。

このマニュアル通りにプログラムを組んだのですが全然表示されません。

 このマニュアルには、「条件さえ整えば初期化は内部で自動的に行っています。」と書いてあるのですが、 殆ど手動で行う必要があるようです。

 またマニュアルには、「Eから信号を意識的に送る」ということは一言も書いてなかった。
 ただ波形のタイミングチャートがありそこにはEからの信号が表示されていました。

実際には、LCDにコマンドとか文字データを送る時には、コマンドとか文字データをセットしてから Eから1を送ると信号がLCDに初めて送られて220ns待ってからEから0を送るとLCDがそれを きちんと認識します。

 やむを得ずネットを調べてこのページを参考にしてやっとこさ 表示できました。

 そのマニュアルにはEからの これはこのサイトから取ったLCD設定の画像です。

この設定を参考にして、僕の場合はPORTCの0からの4ビットをデータ用に、5ビット、6ビット目を 制御のために使いました。

次の関数類はそのサイトに載っていたものです。この関数を参考にしてプログラムを作りました。これらの 関数群のあとに僕のプログラムを載せます。
まずLCD初期化関数です。
void lcd_init(void)
{
 __delay_ms(20);
 lcd8(0x03);
 __delay_ms(4);
 lcd8(0x03);
 __delay_ms(4);
 lcd8(0x03);//8bit mode
 __delay_ms(4);
 lcd8(0x02);//4bit mode
 __delay_ms(4);
 lcd4(0x08);//2行表示モード
 __delay_ms(4);
 lcd4(0x0c);//表示設定
 __delay_ms(4);
 lcd4(0x06);//entry mode
 __delay_ms(4);
 lcd4(0x01);//cler
 __delay_ms(20);
}
次に8ビット転送関数です。
void lcd8(unsigned char a)
{
 LCD_E=0;
 LCD=a;
 LCD_RS=0;
 LCD_E=1;
 __delay_us(20);
 LCD_E=0;
}
4ビット転送関数です。
void lcd4(unsigned char data)//not use RS(control mode)
{
 unsigned char buf=0x00;
 buf=(data>>4);
 LCD=buf;
 LCD_E=1;
 __delay_us(20);
 LCD_E=0;
 __delay_us(20);//上位4bitと下位4bitの間のwait
 buf=data;
 LCD=buf;
 LCD_E=1;
 __delay_us(20);
 LCD_E=0;
 __delay_us(20);
}
表示関数です。
void lcd_dsp(unsigned char *str,int line)
{
 unsigned char *ad=0; 
 LCD_RS=0;
 if(line==1)lcd4(0x80);/*1行目*/
 else lcd4(0xc0); /*2行目*/
 __delay_ms(2);
 ad=str;
 while(*ad)
 {
  char_dsp(*ad);
  ad++;
 }
}

void char_dsp(unsigned char cha)//use RS
{
 unsigned char buf=0x00;
 buf=(cha>>4);
 LCD=buf;
 LCD_RS=1;
 LCD_E=1;
 __delay_us(20);
 LCD_E=0;
 LCD_RS=0;
 __delay_us(20);//上位4bitと下位4bitの間
 buf=cha;
 LCD=buf;
 LCD_RS=1;
 LCD_E=1;
 __delay_us(20);
 LCD_E=0;
 LCD_RS=0;
 __delay_us(20);
}
 
//  LCDに文字を表示
//  Notes: 4MHz内部クロック
//         PORTC(3)  :  LCD(DB7)14    PORTC(4) 6  :  LCD_EN 6
//         PORTC(2)  :  LCD(DB6)13    GND         :  LCD_RW 5
//         PORTC(1)  :  LCD(DB5)12    PORTC(5) 5  :  LCD_RS 4
//         PORTC(0)  :  LCD(DB4)11    CONTRAST ADJ:  LCD_Vo 3
//         +5v       :  LCD(Vdd) 2
//         GND       :  LCD(Vss) 1
//    Target: PIC18F14K50
#include                  
#define _XTAL_FREQ 4000000    
#define LCD     LATC
#define LCD_E   LATCbits.LATC4
#define LCD_RS  LATCbits.LATC5
#define CTRL   0
#define MOJI   1

#pragma config FOSC = IRC        //  内部クロック
#pragma config USBDIV = OFF, CPUDIV = NOCLKDIV
#pragma config IESO  = OFF, FCMEN = OFF, PLLEN  = ON
#pragma config BORV  = 30,  BOREN = OFF, PWRTEN = OFF
#pragma config WDTPS = 32768, WDTEN = OFF
#pragma config MCLRE = OFF, HFOFST = OFF, XINST  = OFF
#pragma config BBSIZ = OFF, LVP    = OFF, STVREN = ON
#pragma config CP1  = OFF, CP0  = OFF, CPD  = OFF, CPB  = OFF
#pragma config WRT1 = OFF, WRT0 = OFF, WRTB = OFF, WRTC = OFF
#pragma config EBTR1 = OFF, EBTR0 = OFF, EBTRB  = OFF

void lcdOut(unsigned char cha,int mode,int bitMode)
{
unsigned char buf=0x00;
if(bitMode == 8){
    LCD_E=0;
     LCD=cha;
    LCD_RS=0;
    LCD_E=1;
    __delay_us(20);
    LCD_E=0;
}
else{
    buf=(cha>>4);
    LCD=buf;
    if( mode == MOJI )  LCD_RS=1;
    LCD_E=1;
    __delay_us(20);
    LCD_E=0;
    if( mode == MOJI)   LCD_RS=0;
    __delay_us(20);//上位4bitと下位4bitの間
    buf=cha;
    LCD=buf;
    if( mode == MOJI )  LCD_RS=1;
    LCD_E=1;
    __delay_us(20);
    LCD_E=0;
    if( mode == MOJI )  LCD_RS=0;
    __delay_us(20);
    }
}
void lcdInit(void)
{
    __delay_ms(20);
    lcdOut(0x03,0,8);
    __delay_ms(4);
    lcdOut(0x03,0,8);
    __delay_ms(4);
    lcdOut(0x03,0,8);//8bit mode
    __delay_ms(4);
    lcdOut(0x02,0,8);//4bit mode
    __delay_ms(4);
    lcdOut(0x08,CTRL,4);//2行表示モード
    __delay_ms(4);
    lcdOut(0x0c,CTRL,4);//表示設定
    __delay_ms(4);
    lcdOut(0x06,CTRL,4);//entry mode
    __delay_ms(4);
    lcdOut(0x01,CTRL,4);//cler
    __delay_ms(20);
}
void lcdPos(int x, int y)
{
    if( y == 1) lcdOut(0x80+x,CTRL,4);
    else lcdOut(0xC0+x,CTRL,4);    
}
 void lcdDsp(unsigned char *str,int x, int y)
{
    unsigned char *ad=0; 
    LCD_RS=0;
    lcdPos(x,y);
    __delay_ms(2);
    ad=str;
    while(*ad)
    {
    lcdOut(*ad,MOJI,4);
    ad++;
}
}
 void main(void){
    OSCCON = 0b01010010;         // 内部クロック4Mhz
    LATC = 0;                    // PortCのすべてのビットを「0」
    TRISC = 0b00000000;          // ポートを出力に設定
    lcdInit();//初期化
    lcdDsp("LCD",1,1);
    lcdDsp("Love",12,1);
    lcdDsp("Splendid",1,2);
    lcdDsp("More",12,2);
     while(1);
}
USB内蔵では最も廉価なPICマイコンです
PIC18F14K50マイコンボード(2016年10月〜11月)
左がPIC18F14K50マイコンボードの説明です。

秋月電子で買いました。この説明書は秋月電子のネットにあったものです。

ピンヘッダが3つついていて、はんだでボードにピンヘッダを取り付けます。

ボードの真ん中のものがPIC18F14K50です。

ボードの左端にUSBソケットがついています。
USBもついていて、しかもこのボードを基盤に取り付けたままでPICkit3をつないでプログラムを書き込める、 という優れものですが、左を見てください。


上が本ボードのピン配置、下がボードに載る前のPIC18F14K50のピン配置です。


よく見るとRA0〜RA4が上のボードのピン配置にはありません。
つまりPORTAをつぶしてPICkit3の端子を確保しています。
いつものようにLED4個をつなげてちかちかさせてみます。

RC0,RC1,RC2,RC3にLEDをつなぎます。ボードでは左上の4個の端子に当たります。

RB7、ボードでは右の真ん中の端子です、ここにスイッチをつなぎます。

このRB7にはプルアップ抵抗をつなぎます。
これらは前の8ピンのPIC12F683の場合と、つなぐピンが異なるだけで他は一緒なので回路図は省きます。

このボードの電源は5Vなので、前に使ったものと同じお手製の電源を使います。
このように本ボードをブレッドボードに挿したままでPICkit3をつけられてプログラムをPCから 転送できます。

以下にLEDちかちかのプログラムを載せます。

XC8コンパイラで作りました。

ただ今まで使っていたMPLABがXC8を認識できなくて、「MPLAB X」というIDEがXC8にジャスト 対応しているということで「MPLAB X」を使いました。

今までのMPLABとは使い方がすごく違っていたのでかなり苦労しました。

出力の時には、アセンブラで書いた時には直接その端子に1を与えましたが、C言語では該当のLATレジスタに1を 与えます。
例えばPORTCの0ビット目を1にするときには 「LATC = 0b00000001;」という風にです。

動作周波数が大きくなってくると、直接レジスタに1を与えるとその速さに動作がついていかないので、それ専用の レジスタとしてLATレジスタがあるようです。

このプログラムは、「はじめてのPIC」というサイトを参考にしました(1部変えただけで殆どコピペ)。
//  4つのLEDが順次点灯する。LEDはPORTCの0,1,2,3に取り付けている
//スイッチを押すと点灯する順番が逆になる
//  Notes: 4MHz内部クロック
//    Language: MPLABX  xc8(v1.12)
//    Target: PIC18F14K50
#include "xc.h"
#define _XTAL_FREQ 4000000    // 動作周波数値を4MHに設定する

#pragma config FOSC   = IRC, PLLEN  = ON,  FCMEN  = OFF
#pragma config IESO   = OFF, USBDIV = OFF, CPUDIV = NOCLKDIV
#pragma config PWRTEN = OFF, BOREN  = OFF, WDTEN  = OFF
#pragma config HFOFST = OFF, MCLRE  = OFF
#pragma config STVREN = ON,  BBSIZ  = OFF, LVP    = OFF
#pragma config XINST  = OFF
#pragma config CP0    = OFF, CP1    = OFF, CPB    = OFF
#pragma config WRT0   = OFF, WRT1   = OFF, WRTB   = OFF, WRTC   = OFF
#pragma config EBTR0  = OFF, EBTR1  = OFF, EBTRB  = OFF

void main(void){
    OSCCON = 0b01010010;         // 内部クロック4Mhz
    LATC = 0;                    // PortCのすべてのビットを「0」
    TRISC = 0b11110000;          // LEDの接続されているポートを出力に設定
    while(1){                    // 繰り返しループ
        if(PORTBbits.RB7){       // SW(RB7)が1なら
            LATC = 0b00000001; //     LED 1つ目点灯 3ヶ消灯
           __delay_ms(150);
            LATC = 0b00000010; //     LED 2つ目点灯 3ヶ消灯
           __delay_ms(150);
            LATC = 0b00000100; //     LED 3つ目点灯 3ヶ消灯
           __delay_ms(150);
            LATC = 0b00001000; //     LED 4つ目点灯 3ヶ消灯
           __delay_ms(150);
       }
        else{                   // SW(RB7)が0なら
            LATC = 0b00001000; //     LED 4つ目点灯 3ヶ消灯
            __delay_ms(150);
            LATC = 0b00000100; //     LED 3つ目点灯 3ヶ消灯
           __delay_ms(150);
           LATC = 0b00000010; //     LED 2つ目点灯 3ヶ消灯
           __delay_ms(150);
            LATC = 0b00000001; //     LED 1つ目点灯 3ヶ消灯
            __delay_ms(150);   
           }
    }                            // ここまで繰り返し
}
Picマイコンでスイッチを使う(20016年10月)
 アセンブラ言語でスイッチはどのように扱えばいいのだろうか?

と思って、スイッチがある回路を組みました。
ついでにLEDを4つにして、4つのLEDが順番に点灯してスイッチを押している間はその点灯順が 逆になる、というプログラムを組みました。

 左がその回路図です。
上の回路図をブレッドボードに組んだ全体のイメージです。
右の基盤は9Vの電池から3端子レギュレータを介して5Vを作っている電源回路です。

スイッチはプッシュスイッチを使っていますので、押している間はGP3の入力がGNDになります。

左の下の画像が、Pic・LED・スイッチの部分を拡大したものです。

画像ではよく見えていませんが、Picの左一番下のピン(GP3)に上の5Vからプルアップ抵抗をつなげて 、それをスイッチで分断してスイッチから下のグラウンドに線をつなげています。

上の回路図では200Ωとしていますが、手近なところにそれがあったのでそうしただけです。
以下にこのためのアセンブラプログラムを載せます。
ラベルsw1の行の命令にスイッチを押したときの条件分岐があります。
アセンブラで条件分岐の命令は次の4つしかありません。
BTFSC   ; レジスタの指定したビットが0なら次の命令をスキップ
BTFSS   ; レジスタの指定したビットが1なら次の命令をスキップ
DECFSZ  ; レジスタ値を1減算し,値が0なら次の命令をスキップ
INCFSZ  ; レジスタ値を1加算し,値が0なら次の命令をスキップ
このうちの最初の命令を使っています。
「BTFSC GPIO,3」
はGPIOレジスタのビット3(つまりGP3)が0になったら、すなわちプッシュスイッチSWを 押したら次の命令をスキップせよということになります。
	list      p=12f683
	#include 
	__CONFIG _CP_OFF & _CPD_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF
w_temp		EQU	0x70 
status_temp	EQU	0x71。
CNT1		EQU	0x20
CNT2		EQU	0x21
;**********************************************************************
		ORG     0x000
		goto    main
		ORG		0x004
		movwf		w_temp
		movf		STATUS,w
		movwf		status_temp
; ISR Codes
		movf		status_temp,w
		movwf		STATUS
		swapf		w_temp,f
		swapf		w_temp,w
		retfie
main
		bsf		STATUS,RP0	;bank1
		clrf	ANSEL		;デジタルIOモード
		clrf		TRISIO	;GPIO出力モード
		bcf		STATUS,RP0	;bank0	
		bcf		STATUS,RP1
		clrf		INTCON	;割り込み禁止
		movlw		0x07
		movwf		CMCON0	;コンパレータ電源OFF
		clrf		GPIO
;4つのLEDを順番に点灯 LEDはGP0,GP1,GP2,GP4につける
;スイッチをGP3につける on→Gnd off→5V
main_loop
		bsf		GPIO,0		;GP0のLEDを点灯
		call 	DLY_250		;時間待ち
		bcf		GPIO,0		;GP0のLEDを消灯

		bsf		GPIO,1		;GP1のLEDを点灯
		call 	DLY_250		;時間待ち
		bcf		GPIO,1		;GP1のLEDを消灯

		bsf		GPIO,2		;GP2のLEDを点灯
		call 	DLY_250		;時間待ち
		bcf		GPIO,2		;GP2のLEDを消灯

		bsf		GPIO,4		;GP4のLEDを点灯
		call 	DLY_250		;時間待ち
		bcf		GPIO,4		;GP4のLEDを

sw1		BTFSC 	GPIO,3		;スイッチ押下? GP3=0ならSKIP
		GOTO 	main_loop	;スイッチ押さず、GP3=1なら元へ戻る

		bsf		GPIO,4		;GP4のLEDを点灯
		call 	DLY_250		;時間待ち
		bcf		GPIO,4		;GP4のLEDを消灯

		bsf		GPIO,2		;GP2のLEDを点灯
		call 	DLY_250		;時間待ち
		bcf		GPIO,2		;GP2のLEDを消灯

		bsf		GPIO,1		;GP1のLEDを点灯
		call 	DLY_250		;時間待ち
		bcf		GPIO,1		;GP1のLEDを消灯

		bsf		GPIO,0		;GP0のLEDを点灯
		call 	DLY_250		;時間待ち
		bcf		GPIO,0		;GP0のLEDを消灯

		goto	sw1			;スイッチが押下?に戻る
;Delay Routine
DLY_250	; 250mS
		movlw		0xfa			;CNT1 ← 250
		movwf		CNT1
DLP1		
		movlw		0xf0			;CNT2 ← 240
		movwf		CNT2
DLP2    ;1ms時間待ち
		nop
		nop
		decfsz		CNT2,f	
		goto		DLP2
		decfsz		CNT1,f
		goto		DLP1
		return	
		END


はじめてのPicマイコン(20016年9月)

 PICというマイコンがあります。
左にその写真を載せます。この写真は http://www.eleclabo.com/denshi/micon/pic_basis/ のサイトから転載したものです。
左ようないろいろなものがあります。いろいろと言ってもその違いは足のピンの数です。
足のピンの一つ一つに機能が割り当てられているので足が多ければ多いほど機能が豊富ということになります。 そして、見てのようにピンの数が多いとサイズも大きくなります。

 電子工作を始めた頃、最初にマイコンの書物を買ったのはこのPicマイコンの本でした。
その中身を見ると、プログラムを組むのにアセンブラ言語を使っていました。C言語を使っている本は 見当たりませんでした。
アセンブラ言語というのは、記号言語とも呼ばれ最も難解な言語のひとつです。
これに反してC言語は高級言語であり人が見て何をしているか分かるような言語です。
例えば、C言語では、a=100 という命令がアセンブラ言語では3行4行必要です。
そもそもアセンブラ言語は、僕が修士論文を書く時にアセンブラ言語を使ったものであり、その時に 非常に難渋したのを覚えています。
 そういうことでアセンブラ言語は避けようと思っていましたのでC言語を使えるほかのマイコンに行きました。

 今回思うところがあってPicマイコンをやる必要に迫られ、改めて以前に買った書物を熟読しました。
すると、前は避けようと思っていたアセンブラ言語が案外わかりやすく、「それでは」と思ってPicマイコン を始めようと思いました。
マルツパーツ館のサイトに「はじめてのPicマイコン」 http://www.marutsu.co.jp/pc/static/large_order/begin_pic というページがあり、このページでPicマイコンのいろはが勉強できます。
ここではC言語を使ったPICマイコンの動かしかかたを説明しています。
アセンブラ言語を使った方が「頭の体操」にはいいので僕はアセンブラ言語を使いました。

マルツパーツ館のサイトで解説されていた内容を確認しようと思い、そこに載っていたパーツを購入しました。
以下にそれらを挙げます。
はんだ付けをしないで簡便に取り掛かろうと思ったのでこれら以外に、「ブレッドボード、配線ワイヤー、LED」が 必要です。
僕はこれらは手持ちのものを使いましたが・・・・・。
商品名 写真 金額(税抜) 用途 購入先
DIPパッケージ・
PICマイコンプログラミング・
アダプタキット
  ¥ 1,886 Picマイコンを装着して下のpickit3を経由してPCからのプログラムを書き込むためのもの
キットなので基盤にパーツをはんだ付けします。
マルツパーツ館
pickit3   ¥ 4,700 PCと上のアダプタキットをつなげてPC上のプログラムをPicに書き込む マルツパーツ館
DIP-IC引き抜き工具   ¥ 540 Picマイコンをソケットから引き抜く マルツパーツ館
PIC12F683−I/P ¥ 130 PICマイコン
マルツパーツ館のサイトの解説で使われていたPicで8本足  
秋月電子
PIC24FJ64GA002−I/SP ¥ 330 PICマイコン
機能豊富で特にSPI(シリアルペリフェラルインタフェイス)が2chあるということで購入
28本足  
秋月電子
ICソケット ( 8P)
 (10個入)
¥ 100 秋月電子
ICソケット (28P) 
スリム300milタイプ (10個入)
¥ 200 秋月電子
MPLALB IDE 無料 Picのプログラムを書いて、Picに書き込むソフトウエア
Microchipのサイト
無料ダウンロード出来る
Pic12F683のピン構成です。
LEDは7番ピンのGP0に接続することにします。
1番ピンに電源をつなげます。
8番ピンはグラウンドです。
PCのソフトMPLABからPICKIT3を経由してアダプタキット上のPIC にプログラムを書き込んでいるところです。

ブレッドボード上に回路を組んでLEDを点滅させているところです。

Picは2V〜5.5Vで動作するので単4電池4個を電源としました。
単4電池としたのは4個で 約5Vになる使い古しがあったためです。

非常に簡単な回路なので左を見てもらうとはわかると思いますので回路図は載せません。

LEDを抵抗で減圧する必要がありますが、使っているLEDは抵抗内蔵のもの(秋月で購入) なので抵抗を付けていません。

どのような信号が出ているのかを見るためにオシロスコープをつなぎました。
電圧5V、幅約300msの矩形波が断続的に出ているのがわかります。
以下にこのためのアセンブラプログラムを載せます。
参考にしたのはこのページです。
http://www.geocities.jp/ejiri_takahiro/S_5214_A5.html
	list      p=12f683
	#include 
	__CONFIG _CP_OFF & _CPD_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF
w_temp		EQU	0x70 
status_temp	EQU	0x71
CNT1		EQU	0x20
CNT2		EQU	0x21
;**********************************************************************
		ORG     0x000
		goto    main
		ORG		0x004
		movwf		w_temp
		movf		STATUS,w
		movwf		status_temp
; ISR Codes
		movf		status_temp,w
		movwf		STATUS
		swapf		w_temp,f
		swapf		w_temp,w
		retfie
main
		bsf		STATUS,RP0	;bank1
		clrf		ANSEL		;デジタルIOモード
		clrf		TRISIO	;GPIO出力モード
		bcf		STATUS,RP0	;bank0	
		bcf		STATUS,RP1
		clrf		INTCON	;割り込み禁止
		movlw		0x07
		movwf		CMCON0	;コンパレータ電源OFF
		clrf		GPIO
main_loop
		bsf		GPIO,0
		call 		DLY_250
		bcf		GPIO,0
		call 		DLY_250
		goto		main_loop
;Delay Routine
DLY_250	; 250mS
		movlw		0xfa			;CNT1 ← 250
		movwf		CNT1
DLP1		
		movlw		0xf0			;CNT2 ← 240
		movwf		CNT2
DLP2    		;1ms時間待ち
		nop
		nop
		decfsz		CNT2,f	
		goto			DLP2
		decfsz		CNT1,f
		goto			DLP1
		return	
		END