読者です 読者をやめる 読者になる 読者になる
一人もくもく会 α verでサービス開始しました。

PIC32MX220F032BでキャラクタLCD

PIC32MX

先日PIC12でキャラクタLCDが出来たので
PIC32でも色々試してみたいと思いLCDを試すことに。

とりあえず成功したプログラムをパパっと移植して実行。
…動かない。

よくよく見ると3.3VじゃLCDが動作しないので
余っていたHT7750と4x4基板で5V変換基板をごちゃごちゃに作った。
DSC_0297

しかしこれでも動かない。
1日悩んで色々調べてみるが、
なんとなくPICの動作が早すぎてダメなんじゃないかと思い
SD1602のデータシートを見たり色々と調べてみた。

どうもやはりPICのクロックが早すぎる場合は
ちょいちょいdelayを入れてあげないとダメっぽい気がしたので
色々な情報を参考に入れてみたところ動くようになった。

#include <xc.h>
#include <plib.h>

#pragma config FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FPLLODIV = DIV_1, FWDTEN = OFF
#pragma config POSCMOD = HS, FNOSC = PRIPLL, FPBDIV = DIV_8

#define SYS_FREQ 			(80000000L)

#define LCD_RS    BIT_0
#define LCD_EN    BIT_1
#define LCD_D4    BIT_11
#define LCD_D5    BIT_13
#define LCD_D6    BIT_14
#define LCD_D7    BIT_15

void __delay_us(WORD us)
{
	DWORD start = _CP0_GET_COUNT();
	DWORD end = start + SYS_FREQ / 10000000 / 2 * us;
//	DWORD end = start + SYS_FREQ / 1000000 / 2 * us;
	if (end > start) while (_CP0_GET_COUNT() < end);
	else while (_CP0_GET_COUNT() > start || _CP0_GET_COUNT() < end);
}

void __delay_ms(unsigned int msec)        //1msec遅延関数
{
	unsigned int i;

	for(i=0; i<msec; i++) {
		__delay_us(1000);
	}
}

void lcdStrobe() {
	mPORTASetBits(LCD_EN);
	__delay_us(1);
	mPORTAClearBits(LCD_EN);
}

void lcdSetBit(int bt, char value) {
	if (value == 1) {
		mPORTBSetBits(bt);
	} else {
		mPORTBClearBits(bt);
	}
}

void lcdCommand(unsigned char c)
{
	mPORTAClearBits(LCD_RS);
	lcdSetBit(LCD_D4, c & 1);
	lcdSetBit(LCD_D5, (c >> 1) & 1);
	lcdSetBit(LCD_D6, (c >> 2) & 1);
	lcdSetBit(LCD_D7, (c >> 3) & 1);
	lcdStrobe();
	__delay_us(50);
}

void lcdWrite(unsigned char c)
{
	lcdSetBit(LCD_D4, (c >> 4) & 1);
	lcdSetBit(LCD_D5, (c >> 5) & 1);
	lcdSetBit(LCD_D6, (c >> 6) & 1);
	lcdSetBit(LCD_D7, (c >> 7) & 1);
	lcdStrobe();
	lcdSetBit(LCD_D4, c & 1);
	lcdSetBit(LCD_D5, (c >> 1) & 1);
	lcdSetBit(LCD_D6, (c >> 2) & 1);
	lcdSetBit(LCD_D7, (c >> 3) & 1);
	lcdStrobe();
	__delay_us(50);
}

/*******************************************************************************
*    lcd_setCursor - LCDモジュール画面内のカーソル位置を移動する処理        *
*      col : 横(列)方向のカーソル位置(0-15)                                    *
*      row : 縦(行)方向のカーソル位置(0-1)                                     *
********************************************************************************/
void lcdSetCursor(int col, int row)
{
     int row_offsets[] = { 0x00, 0x40 } ;

     mPORTAClearBits(LCD_RS);
     lcdWrite(0x80 | (col + row_offsets[row])) ; // Set DDRAM Adddress : 00H-0FH,40H-4FH
}

void lcdClear(void)
{
     mPORTAClearBits(LCD_RS);
     lcdWrite(0x01) ; // Clear Display : 画面全体に20Hのスペースで表示、カーソルはcol=0,row=0に移動
     __delay_ms(2) ;   // LCDが処理(1.53ms)するのを待ちます
}

void lcdPutc(char c) {
	mPORTASetBits(LCD_RS);
	lcdWrite(c);
}

void lcdPuts(const char *s) {
	mPORTASetBits(LCD_RS);
	while(*s) {
		lcdWrite(*s++);
	}
}

void lcdInit()
{
	mPORTAClearBits(LCD_RS | LCD_EN);

	__delay_ms(40) ;    // 電源ON後15msまで待ってから初期化

	// LCDの立上げ時のチェックデータ(イニシャライズ処理用)を設定
	lcdCommand(0x03) ;
	__delay_ms(5) ;
	lcdCommand(0x02) ;
	__delay_ms(5) ;
	// LCDにコマンドを発行します
	lcdWrite(0x28) ;   // function set   : データ線は4本・表示は2行・フォントは5x8ドット
	lcdWrite(0x0c) ;   // display control: 画面表示はON・カーソル表示はOFF・カーソル点滅はOFF
	lcdClear() ;       // Clear Display  : 画面をクリアし、カーソル位置はcol=0,row=0
	lcdWrite(0x06) ;   // entry mode set : 文字を表示した次にカーソルを移動するを指示
}

int main(void)
{
	char s[17];

    SYSTEMConfig(SYS_FREQ, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);
    mJTAGPortEnable(DEBUG_JTAGPORT_OFF);

	mPORTASetPinsDigitalOut(LCD_RS | LCD_EN);
	mPORTBSetPinsDigitalOut(LCD_D4 | LCD_D5 | LCD_D6 | LCD_D7);
	lcdInit();
	lcdPuts("Monitor");

	int i = 0;
    while(1)
    {
		__delay_ms(1000);
		itoa(s, i++, 10);
		lcdSetCursor(0, 1);
		lcdPuts("          ");
		lcdSetCursor(0, 1);
		lcdPuts(s);
	}
}

delayの関数はどっかの情報を参考にしたのだが、
指定の10倍くらいのdelayになってしまっていたのでちょっと変更してある。
なぜそのようなプログラムになっていたかも、計算してもよくわからない。
今の状態も適当に合わせてあるだけ。
計算して作ってみても全然合わなかったので…。

VoをGNDに繋いでいるせいか、コントラストがなさすぎて文字が見えにくい。
斜めから見るとよく見えるのだが。
PIC18の時はそんなことなかったのでなんかの設定が上手くできていないせいかもしれないが
そのへんは試してないのでよくわからない。

ほんとは内蔵の8MHzで動かしたかったのだが、
ちょいっとconfigをいじってみたらすぐ動かなくなるので
とりあえずは断念した。
8MHzで動かせたらdelay省けるところもあるっぽい。

しかしPIC32MXはプログラムとか情報が少なくてきつい…。