PIC16F883でI2Cインターフェース付きLCD1602の表示テストをしました。
Arduinoで実験済みのプログラムを移植しました。Arduinoの記事は、こちら
回路図です。
ブレッドボードです。表示された文字がちょっと見ずらいです。すみません。
プログラムです。I2Cインターフェースを使ってLCD1602に文字を表示する原理は、JH7UBCホームページのこちらの記事を見てください。
---------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include <stdlib.h>
#include <xc.h>
// CONFIG1
#pragma config FOSC = INTRC_NOCLKOUT
#pragma config WDTE = OFF
#pragma config PWRTE = ON
#pragma config MCLRE = OFF
#pragma config CP = OFF
#pragma config CPD = OFF
#pragma config BOREN = OFF
#pragma config IESO = OFF
#pragma config FCMEN = OFF
#pragma config LVP = OFF
#pragma config FOSC = INTRC_NOCLKOUT
#pragma config WDTE = OFF
#pragma config PWRTE = ON
#pragma config MCLRE = OFF
#pragma config CP = OFF
#pragma config CPD = OFF
#pragma config BOREN = OFF
#pragma config IESO = OFF
#pragma config FCMEN = OFF
#pragma config LVP = OFF
// CONFIG2
#pragma config BOR4V = BOR40V
#pragma config WRT = OFF
#pragma config BOR4V = BOR40V
#pragma config WRT = OFF
#define _XTAL_FREQ 8000000
#define LCD_EN 0b00000100 //Enable
#define LCD_BL 0b00001000 //Back Light
#define LCD_CMD 0x00
#define LCD_CHR 0x01
#define LCD_LINE1 0x80
#define LCD_LINE2 0xC0
#define LCD_addr 0x4E //0x27<<1
#define SW RB0
#define start_addr 0b00000111
#define end_addr 0b01111000
#define LCD_EN 0b00000100 //Enable
#define LCD_BL 0b00001000 //Back Light
#define LCD_CMD 0x00
#define LCD_CHR 0x01
#define LCD_LINE1 0x80
#define LCD_LINE2 0xC0
#define LCD_addr 0x4E //0x27<<1
#define SW RB0
#define start_addr 0b00000111
#define end_addr 0b01111000
/* I2C 初期化*/
void I2C_init(){
SSPCON = 0x28; //SSPEN = 1,I2C Master Mode
SSPSTATbits.SMP = 1; //標準速度モード(100KHz)
SSPADD = 19; //Fosc/(4*Clock)-1 Clock=100kHz,Fosc=8MHz
}
/* スタートコンディション */
void I2C_start(){
SEN = 1;
while(SEN);
}
void I2C_start(){
SEN = 1;
while(SEN);
}
/* ストップコンディション */
void I2C_stop(){
SSPIF = 0;
PEN = 1;
while(PEN);
SSPIF = 0;
}
void I2C_stop(){
SSPIF = 0;
PEN = 1;
while(PEN);
SSPIF = 0;
}
/* I2Cに1byte送信 */
unsigned char I2C_write(unsigned char dat){
SSPIF = 0;
SSPBUF = dat;
while(!SSPIF);
return ACKSTAT;
}
unsigned char I2C_write(unsigned char dat){
SSPIF = 0;
SSPBUF = dat;
while(!SSPIF);
return ACKSTAT;
}
void Write_data(unsigned char data){
unsigned char ackn;
I2C_start();
ackn = I2C_write(LCD_addr);
ackn = I2C_write(data | LCD_EN | LCD_BL);
ackn = I2C_write(data | LCD_BL);
I2C_stop();
__delay_us(100);
}
unsigned char ackn;
I2C_start();
ackn = I2C_write(LCD_addr);
ackn = I2C_write(data | LCD_EN | LCD_BL);
ackn = I2C_write(data | LCD_BL);
I2C_stop();
__delay_us(100);
}
void LCD_write(unsigned char bits,unsigned char mode){
//send High 4bits
Write_data((bits & 0xF0) | mode);
//send Low 4bits
Write_data(((bits << 4) & 0xF0) | mode);
}
//send High 4bits
Write_data((bits & 0xF0) | mode);
//send Low 4bits
Write_data(((bits << 4) & 0xF0) | mode);
}
void LCD_init(){
LCD_write(0x33,LCD_CMD);
LCD_write(0x32,LCD_CMD);
LCD_write(0x06,LCD_CMD);
LCD_write(0x0C,LCD_CMD);
LCD_write(0x28,LCD_CMD);
LCD_write(0x01,LCD_CMD);
__delay_ms(1);
}
LCD_write(0x33,LCD_CMD);
LCD_write(0x32,LCD_CMD);
LCD_write(0x06,LCD_CMD);
LCD_write(0x0C,LCD_CMD);
LCD_write(0x28,LCD_CMD);
LCD_write(0x01,LCD_CMD);
__delay_ms(1);
}
void LCD_clear(){
LCD_write(0x01,LCD_CMD);
__delay_ms(1);
}
LCD_write(0x01,LCD_CMD);
__delay_ms(1);
}
void LCD_home(){
LCD_write(0x02,LCD_CMD);
__delay_ms(1);
}
LCD_write(0x02,LCD_CMD);
__delay_ms(1);
}
void LCD_cursor(unsigned char x,unsigned char y){
if (y == 0){
LCD_write(LCD_LINE1+x,LCD_CMD);
}
if (y == 1){
LCD_write(LCD_LINE2+x,LCD_CMD);
}
}
if (y == 0){
LCD_write(LCD_LINE1+x,LCD_CMD);
}
if (y == 1){
LCD_write(LCD_LINE2+x,LCD_CMD);
}
}
void LCD_char(unsigned char byte){
LCD_write(byte,LCD_CHR);
}
LCD_write(byte,LCD_CHR);
}
void putch(unsigned char ch){
LCD_char(ch);
}
LCD_char(ch);
}
void main() {
ANSEL = 0; //アナログポートを使わない
ANSELH = 0;
OSCCON = 0x70; //内蔵クロック8MHz
TRISA = 0b00000000;
TRISB = 0b00000000;
TRISC = 0b00011000; //RC3(SCL),RC4(SDA)input
PORTA = 0x00;
PORTB = 0x00;
PORTC = 0x00;
I2C_init();
LCD_init();
printf("Hello World!");
LCD_cursor(5,1);
printf("JH7UBC");
while(1){
}
ANSEL = 0; //アナログポートを使わない
ANSELH = 0;
OSCCON = 0x70; //内蔵クロック8MHz
TRISA = 0b00000000;
TRISB = 0b00000000;
TRISC = 0b00011000; //RC3(SCL),RC4(SDA)input
PORTA = 0x00;
PORTB = 0x00;
PORTC = 0x00;
I2C_init();
LCD_init();
printf("Hello World!");
LCD_cursor(5,1);
printf("JH7UBC");
while(1){
}
}
-----------------------------------------------
-----------------------------------------------
今回のトラブルシューティング
すでにArduinoで実験済みのプログラムです。簡単に動作すると思ったのですが、どっこい、電源を入れてもまったく表示しません。
回路は簡単ですから、接続に間違いはないはず。
うーーん。表示されない原因が分からない。
Arduinoでやってみると、ちゃんと表示されます。
I2C1の信号はちゃんと出ているのか、picoスコープで確認すると問題ありません。
いろいろ確認に1日かかりました。
一夜明けて、はっつと気づきました。SDAとSCLの配線が逆になっているでは、ありませんか。
入れ替えたら、ぱっと表示されました。
正しく配線したはず、という思い込みでした。
反省。
さて、次に進みましょう。