PICマイコンでI2Cを使って、 LCD 1602A を表示してみる。

PICマイコンでI2C制御の LCD を使用して文字を表示してみました。

I2C制御のプログラムと、簡単な説明については、この記事で書いています。

今回使用するプログラムは、その記事のものを使用しています。

使用機器

LCD 制御ヘッダープログラム(lcd_lib.h)

I2Cのアドレスは、0x3Fで動きました。動かない場合は、0x27とかに変えてみてください。

製品によってアドレスの値が異なるので、説明書を読んで調べてください。

#define LCD_ADD 0x3F //動かなければここのアドレスを変更する
    
#define En 0b00000100
#define Rs 0b00000001

void lcd_init();
void lcd_backlight();    
void lcd_cmd(uint8_t cmd);
void lcd_clear();
void lcd_set_cursor(uint8_t col, uint8_t row);
void lcd_print(char *str);
    
void command(uint8_t val, uint8_t mode);

LCD 制御プログラム(lcd_lib.c)

/*
 * File:   lcd_lib.c
 * Author: dexte
 *
 * Created on October 4, 2020, 2:52 PM
 */

#include <xc.h>
#include "mcc_generated_files/device_config.h"

#include "i2c.h"
#include "lcd_lib.h"

#define ROW 2
#define COL 16

uint8_t _backlightval;

void lcd_cmd(uint8_t cmd){
    i2c_start();
    i2c_write(LCD_ADD << 1);  
    i2c_write(cmd);
    i2c_stop();    
    __delay_us(10);
}

void lcd_init(){
    __delay_ms(400);
    
    lcd_cmd(0x30);            
    lcd_cmd(0x34);        
    lcd_cmd(0x30);    
    __delay_ms(5);  //write4bits(0x03 << 4)
    
    lcd_cmd(0x30);        
    lcd_cmd(0x34);        
    lcd_cmd(0x30);
    __delay_ms(5);  //write4bits(0x03 << 4)
    
    lcd_cmd(0x30);     
    lcd_cmd(0x34);        
    lcd_cmd(0x30);
    __delay_us(300);  //write4bits(0x03 << 4)
    
    lcd_cmd(0x20);    
    lcd_cmd(0x24);    
    lcd_cmd(0x20);     
    __delay_us(10); //write4bits(0x02 << 4)
    
    //command(0x28)
    lcd_cmd(0x20);    
    lcd_cmd(0x24);    
    lcd_cmd(0x20);  //write4bits(0x20);
    
    __delay_us(100);
    
    lcd_cmd(0x80);    
    lcd_cmd(0x84);    
    lcd_cmd(0x80);  //write4bits(0x80)
    
    //display
    //command(0x0C)
    lcd_cmd(0x00);    
    lcd_cmd(0x04);    
    lcd_cmd(0x00);  //write4bits(0x00);
    
    __delay_us(100);
    
    lcd_cmd(0xC0);    
    lcd_cmd(0xC4);    
    lcd_cmd(0xC0);  //write4bits(0xC0);
    
    //clear
    //command(0x01);
    lcd_cmd(0x00);    
    lcd_cmd(0x04);    
    lcd_cmd(0x00);  //write4bits(0x00);
    
    __delay_us(100);
    
    lcd_cmd(0x10);    
    lcd_cmd(0x14);    
    lcd_cmd(0x10);  //write4bits(0x10);
    
    __delay_ms(5); //takes a long time
    
    //command(0x06);
    lcd_cmd(0x00);    
    lcd_cmd(0x04);    
    lcd_cmd(0x00);  //write4bits(0x00);
    
    __delay_us(100);
    
    lcd_cmd(0x60);    
    lcd_cmd(0x64);    
    lcd_cmd(0x60);  //write4bits(0x60);
    
    //home()
    //command(0x02)
    lcd_cmd(0x00);    
    lcd_cmd(0x04);    
    lcd_cmd(0x00);  //write4bits(0x00);
    
    __delay_us(100);
    
    lcd_cmd(0x20);    
    lcd_cmd(0x24);    
    lcd_cmd(0x20);  //write4bits(0x20);
    
    __delay_ms(3);
}

void lcd_backlight(){
    lcd_cmd(0x08);
    _backlightval = 0x08;
    __delay_us(10);
}

void lcd_clear(){
    for(uint8_t row = 0; row < ROW; row++){
        for(uint8_t col = 0; col < COL; col++){
            lcd_set_cursor(col, row);
            lcd_print(" ");
        }
    }
}

void lcd_set_cursor(uint8_t col, uint8_t row){
    uint8_t row_offsets[] = {0x00, 0x40, 0x14, 0x54};
    if(row > ROW){
        row = ROW - 1;
    }    
    uint8_t cmd = 0x80 | (col + row_offsets[row]);    
    command(cmd, 0);
}

void lcd_print(char *str) {
    while (*str) {
        uint8_t cmd = *str++;
        command(cmd, Rs);     
    }
}

void command(uint8_t val, uint8_t mode){    
    uint8_t highnib = (val & 0xf0) | _backlightval | mode;
	uint8_t lownib = ((val << 4) & 0xf0) | _backlightval | mode;
    
	lcd_cmd(highnib);
    lcd_cmd(highnib | En);
    lcd_cmd(highnib & ~En);
    
    __delay_us(100);
        
	lcd_cmd(lownib);
    lcd_cmd(lownib | En);
    lcd_cmd(lownib & ~En);  
}

メインプログラム(main.c)


#include "mcc_generated_files/mcc.h"

#include "i2c.h"
#include "lcd_lib.h"

void main(void)
{
    // initialize the device
    SYSTEM_Initialize();     
     
    WPUB = 0x24;
    OPTION_REGbits.nWPUEN = 0;
    
    SSP2ADD = 0x13;    
    SSP2CON1 = 0x28;
    SSP2CON2 = 0x0;
    SSP2STAT = 0;
    
    lcd_init();
    lcd_backlight();
    lcd_set_cursor(0, 0);
    
    lcd_print("HIZ");   
    
    __delay_ms(1000);
    
    lcd_set_cursor(3, 0);
    lcd_print("12:00");
    
    while(1){}
}

「PICマイコンでI2Cを使って、 LCD 1602A を表示してみる。」への1件のフィードバック

  1. お世話になります、何年かぶりでPIC(16f18857)をいじくりまわしています。 初学習者です。
    基本的な機能確認を進めていますが、I2CでLCD1602を操作しようと思い、貴殿の記事にたどり着きました。
    動作そのものは問題ないのですが、lcd_init()の中の、例えば
     lcd_cmd(0x60);
    lcd_cmd(0x64); ??送り出したい数値+0x04、上下行は、送り出したい数値??
    lcd_cmd(0x60); //write4bits(0x60); 
    の3回連続送出の意味が理解できません。ご教示ください!!

    返信

コメントする