再度PIC18F4550でLCDを動かす
2023/04/30


photo1720
前回LCDの実験をしていたのが2017年で、もう6年前になるのである。

ブレッドボードにセットしたPIC18F4550とLCDは、当時実験していた回路が、ほぼそのままで埃だらけになっていたのである。
当時は、介護をしていた母親の体調悪化が止まり、なんだか良い感じになって、私の気分にも余裕が出てきた頃だったのである。

今は誰もいなくなり、自由と言えば究極の自由になっているのである。
ただ、人間(私は)ダメなもので、時間が無いときは「やりたいことがあるのに時間が無い!!、時間が欲しい!!」と、駄々をこねるのだが、時間が十分にあると、「明日出来ることは今日はしない」と、何もしなくなるのである。


頭の中はすっかりクリアされて空っぽ状態だったのだが、幸いなことにこのHPでプログラムと説明を書いておいたので、思い出すのが比較的楽なのである。
ただプログラムは、単純にコピペをしてしまうと、ほんのちょっとのトラブルでも理解出来ない状況になるので、それなりに理解しながらもう一度書いていく。

1、I2Cの制御プログラム
2、LCDの制御プログラム
3、メインのプログラム


まずはI2Cを制御するプログラムのヘッダーファイル


#include  // include processor files - each processor file is guarded.  

void I2C_Master_Init(void);
void I2C_Master_Wait(void);
void I2C_Master_Wait2(void);
void I2C_Master_Start(void);
void I2C_Master_ReStart(void);
void I2C_Master_Stop(void);
void I2C_Master_Write(unsigned d);
unsigned char I2C_Master_Read(void);

#define _XTAL_FREQ 48000000     // 使用するPIC等により動作周波数値を設定する
                                // 水晶は20MHzでPLLで48MHz動作

次にI2Cを制御するプログラムの本体


#include 
#include "I2C.h"

void I2C_Master_Init()
{
    SSPSTAT = 0b11000000;        //
    SSPCON1 = 0b00101000;        //SSP Module as Master
    SSPCON2 = 0;
//    SSPADD = 119;                //Setting Clock Speed 100KHz
//    SSPADD = 239;                //Setting Clock Speed 50KHz
    SSPADD = 149;                //Setting Clock Speed 80KHz
}

void I2C_Master_Wait()
{
  while ((SSPSTAT & 0x04) || (SSPCON2 & 0x1F)); //Transmit is in progress
}

void I2C_Master_Wait2()
{
  while(!SSPIF);                              //wait till SSPIF flag is set
    SSPIF=0;
}

void I2C_Master_Start()
{
  I2C_Master_Wait();    
  SSPCON2bits.SEN = 1;             //Initiate start condition
  I2C_Master_Wait2();
}

void I2C_Master_Stop()
{
  I2C_Master_Wait();
  SSPCON2bits.PEN = 1;           //Initiate stop condition
  I2C_Master_Wait2();
}

void I2C_Master_Write(unsigned d)
{
  L1 : I2C_Master_Wait();
  SSPBUF = d;         //Write data to SSPBUF
  I2C_Master_Wait2();
  while(ACKSTAT)                              //check if acknowledgement signal received 
    {
        I2C_Master_ReStart();                 //If no acknowledgement received, give restart signal and transmit data again
        goto L1;
    }
}

void I2C_Master_ReStart(void)
{
    RSEN=1;                                     //Initiate restart condition
    I2C_Master_Wait2();                         //Wait till completion of event
}

unsigned char I2C_Master_Read(void)
{
    RCEN=1;                                     //Enable reception in Master device 
    while(!BF);                                 //Wait till buffer is full
    RCEN=0;                                     //Enable reception in Master device 
    return SSPBUF;                              //return received data
}

LCD制御プログラムのヘッダーファイル


#include  // include processor files - each processor file is guarded.  

#define LCD_ADDR          0xa0  // LCDのアドレス
#define LCD_CMD           0x00  // コマンド
#define LCD_DATA          0x80  // データ

#define LCD_CLEAR_DISPLAY 0x01  // LCDクリア
#define LCD_FUNCTION_SET  0x38  // 8ビットデータ、2行
#define LCD_DISPLAY_ON    0x0c  // ディスプレイオン
#define LCD_ENTRY_MODE    0x06  //
#define LCD_LOC           0x80  //

void lcd_init(void);
void lcd_cls(void);
void lcd_loc(unsigned char, unsigned char);
void lcd_putc(unsigned char);
void lcd_str(char *);

LCDの制御プログラム


#include "LCD.h"
#include "I2C.h"

void lcd_init(void)
{
    I2C_Master_Init();
    __delay_ms(5) ;        // 5ms

    I2C_Master_Start();
    I2C_Master_Write(LCD_ADDR);
    I2C_Master_Write(LCD_CMD);
    I2C_Master_Write(LCD_CLEAR_DISPLAY);
    I2C_Master_Stop();
    __delay_ms(5) ;        // 5ms

    I2C_Master_Start();
    I2C_Master_Write(LCD_ADDR);
    I2C_Master_Write(LCD_CMD);
    I2C_Master_Write(LCD_FUNCTION_SET);
    I2C_Master_Stop();
    __delay_ms(5) ;        // 5ms

    I2C_Master_Start();
    I2C_Master_Write(LCD_ADDR);
    I2C_Master_Write(LCD_CMD);
    I2C_Master_Write(LCD_DISPLAY_ON);
    I2C_Master_Stop();
    __delay_ms(5) ;        // 5ms

    I2C_Master_Start();
    I2C_Master_Write(LCD_ADDR);
    I2C_Master_Write(LCD_CMD);
    I2C_Master_Write(LCD_ENTRY_MODE);
    I2C_Master_Stop();
    __delay_ms(5);        // 5ms
}

void lcd_cls(void)
{
    I2C_Master_Start();
    I2C_Master_Write(LCD_ADDR);
    I2C_Master_Write(LCD_CMD);
    I2C_Master_Write(LCD_CLEAR_DISPLAY);
    I2C_Master_Stop();
    __delay_ms(5);        // 5ms
}

void lcd_loc(unsigned char x, unsigned char y)
{
    unsigned char addr;

    addr = y * 0x40 + x;
    addr = addr | LCD_LOC;
    I2C_Master_Start();
    I2C_Master_Write(LCD_ADDR);
    I2C_Master_Write(LCD_CMD);
    I2C_Master_Write(addr);
    I2C_Master_Stop();
}

void lcd_putc(unsigned char c)
{
    I2C_Master_Start();
    I2C_Master_Write(LCD_ADDR);
    I2C_Master_Write(LCD_DATA);
    I2C_Master_Write(c);
    I2C_Master_Stop();
}

void lcd_str(char *s)
{
    unsigned char i;

    for (i = 0; i < 16; i ++) {
	if (*s == 0) {
	    break;
	}
    I2C_Master_Start();
	I2C_Master_Write(LCD_ADDR);
	I2C_Master_Write(LCD_DATA);
	I2C_Master_Write(*s);
    I2C_Master_Stop();
	s ++;
    }
}

最後にメインのプログラム


//#include < stdio.h >
//#include < stdlib.h >
#include 

#include "I2C.h"
#include "LCD.h"

// コンフィギュレーション pic18f4550  c18
#pragma config PLLDIV = 5, CPUDIV = OSC1_PLL2, USBDIV = 2
#pragma config FOSC = HSPLL_HS, FCMEN = OFF, IESO = OFF
#pragma config PWRT = ON, BOR = OFF, BORV = 0
#pragma config VREGEN = ON, WDT = OFF, WDTPS = 1
#pragma config CCP2MX = OFF, PBADEN = OFF, LPT1OSC = OFF
#pragma config MCLRE = OFF, STVREN = OFF, LVP = OFF
#pragma config ICPRT = OFF, XINST = OFF, DEBUG = OFF
#pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF, CP3 = OFF
#pragma config CPB = OFF, CPD = OFF
#pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF, WRT3 = OFF
#pragma config WRTC = OFF, WRTB = OFF, WRTD = OFF
#pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTR3 = OFF, EBTRB = OFF

int main(void) {
    
    unsigned char x;
    unsigned char y;
    unsigned char chr;
    
    TRISD = 0b00000000;			//PORTA=0-7 output
    TRISB = 0b11111111;			//PORTB=0-7 input
    LATD = 0;
    
    lcd_init();
    
    x = 0;
    y = 0;
    chr = 32;
    
    while(1){
        RD0 = 1;

        lcd_loc(x,y);
        lcd_putc(chr);
//        lcd_loc(1,1);      // I2C信号のテスト
//        lcd_putc('X');
        
        x = x + 1;
        if ( x > 15 ) {
            x = 0;
            y = y + 1;
            if ( y > 1 ) y = 0;
        }
        chr = chr + 1;
        if ( chr > 127 ) chr = 32;
        
        RD0 = 0;
        __delay_ms(200) ;        // ms
   }
    
    return (0);
}


photo1721
動作中のLCD




HOME