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