先日PIC12でキャラクタLCDが出来たので
PIC32でも色々試してみたいと思いLCDを試すことに。
とりあえず成功したプログラムをパパっと移植して実行。
…動かない。
よくよく見ると3.3VじゃLCDが動作しないので
余っていたHT7750と4x4基板で5V変換基板をごちゃごちゃに作った。
しかしこれでも動かない。
1日悩んで色々調べてみるが、
なんとなくPICの動作が早すぎてダメなんじゃないかと思い
SD1602のデータシートを見たり色々と調べてみた。
どうもやはりPICのクロックが早すぎる場合は
ちょいちょいdelayを入れてあげないとダメっぽい気がしたので
色々な情報を参考に入れてみたところ動くようになった。
|c|
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はプログラムとか情報が少なくてきつい…。
Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。
また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!
こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?
コメント