PICマイコン(PIC16F18346)でLCD(AE-AQM1602A)に文字を表示する

PICマイコン(PIC16F18346)でLCD(AE-AQM1602A)に文字を表示する

次のようなステップになります。

  1. 回路を作成する
  2. C言語でプログラムを作成する
  3. MPLAB X IDEでプログラムをPICに書き込む

必要なもの

I2C接続LCDはプルアップ抵抗を使うためにハンダをもってジャンパをショートさせておきます。

1. 回路を作成する

LCDのSDAをPIC16F18346のRB5につなぎます。
LCDのSCLをPIC16F18346のRB6につなぎます。

参考イメージ:

pic16f18346-aeaqm1602a"

2. C言語でプログラムを作成する

2-1. common.h

様々なところからインクルードする必要があるので、初期設定は別のヘッダファイルにしました。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#ifndef COMMON_H_INCLUDED
#define COMMON_H_INCLUDED

#pragma config FEXTOSC = OFF
#pragma config RSTOSC = HFINT32
#pragma config CLKOUTEN = OFF
#pragma config CSWEN = ON
#pragma config FCMEN = OFF
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config CP = OFF
#define _XTAL_FREQ 32000000

#endif

2-2. i2c.h

1
2
3
4
5
6
7
8
9
10
11
#ifndef I2C_H_INCLUDED
#define I2C_H_INCLUDED

#include <xc.h>

void i2c_start(void);
void i2c_stop(void);
void i2c_wait(void);
void i2c_write_data(unsigned char data);

#endif

2-3. i2c.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include "common.h"
#include "i2c.h"

void i2c_start() {
SSP1CON2bits.SEN = 1;
i2c_wait();
}

void i2c_stop() {
SSP1CON2bits.PEN = 1;
i2c_wait();
}

void i2c_wait() {
while ((SSP1CON2 & 0x1F) || (SSP1STATbits.R_nW));
}

void i2c_write_data(unsigned char data) {
SSP1BUF = data;
i2c_wait();
}

2-4 ae_aem1602a.h

ドキュメントにあるとおり、スレーブのアドレスは0x7Cを設定します。

1
2
3
4
5
6
7
8
9
10
11
12
13
#ifndef AE_AQM1602A_H_INCLUDED
#define AE_AQM1602A_H_INCLUDED

#define AE_AQM1602A_I2C_ADDRESS 0x7C

#include <xc.h>

void lcd_i2c_init(void);
void lcd_i2c_print_char(char ch);
void lcd_i2c_print_str(const char * str);
void lcd_i2c_set_cursor(char row, char col);

#endif

2-5 ae_aem1602a.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <xc.h>
#include "common.h"
#include "i2c.h"
#include "ae_aqm1602a.h"

static void lcd_i2c_write(unsigned char cont, char data) {
i2c_start();
i2c_write_data(AE_AQM1602A_I2C_ADDRESS);
i2c_write_data(cont);
i2c_write_data(data);
SSP1IF = 0;
i2c_stop();
__delay_us(50);
}

void lcd_i2c_init() {
lcd_i2c_write(0x00, 0x38);
__delay_ms(20);
lcd_i2c_write(0x00, 0x39);
__delay_ms(20);
lcd_i2c_write(0x00, 0x14);
__delay_ms(20);
lcd_i2c_write(0x00, 0x73);
__delay_ms(20);
lcd_i2c_write(0x00, 0x52);
__delay_ms(20);
lcd_i2c_write(0x00, 0x6C);
__delay_ms(300);
lcd_i2c_write(0x00, 0x38);
__delay_ms(20);
lcd_i2c_write(0x00, 0x01);
__delay_ms(20);
lcd_i2c_write(0x00, 0x0C); // display:on, cursor:off, blink:off
// lcd_i2c_write(0x00, 0x0E); // display:on, cursor:on, blink:off
// lcd_i2c_write(0x00, 0x0F); // display:on, cursor:on, blink:on
__delay_ms(20);
}

void lcd_i2c_print_char(char ch) {
lcd_i2c_write(0x40, ch);
__delay_us(50);
}

void lcd_i2c_print_str(const char * str) {
while (*str) {
lcd_i2c_print_char(*str++);
}
}

void lcd_i2c_set_cursor(char row, char col) {
char pos = row * 0x40 + col;
lcd_i2c_write(0x00, 0x80 | pos);
__delay_us(50);
}

2-6 main.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <xc.h>
#include "common.h"
#include "i2c.h"
#include "ae_aqm1602a.h"

int main() {
TRISBbits.TRISB5 = 1;
TRISBbits.TRISB6 = 1;
RB5PPS = 0b11001; // RB5 source is SDO1/SDA1
RB6PPS = 0b11000; // RB6 source is SCK1/SCL1
ANSELB = 0x00;

SSP1CLKPPS = 0b01110; // Peripheral input is RB6
SSP1DATPPS = 0b01101; // Peripheral input is RB5

SSP1CON1 = 0b00101000; // WCOL:0, SSPOV:0, SSPEN:1, CKP:0, SSPM<3:0>:1000
SSP1CON2 = 0x00;
SSP1CON3 = 0x00;
SSP1STAT = 0b10000000;
SSP1ADD = 0x27; // Baudrate: 200kHz(32MHz / (0x27+1) / 4)
// SSP1ADD = 0x13; // Baudrate: 400kHz(32MHz / (0x13+1) / 4)
SSP1DATPPS = 0b01100;

lcd_i2c_init();
lcd_i2c_print_str("Hello");

__delay_ms(1000);

lcd_i2c_set_cursor(1, 0); // row = 1, col = 0
lcd_i2c_print_str("World");
while(1) {
}

return 0;
}

RB5とRB6をそれぞれデータとクロックとして利用するための設定をします。

3. MPLAB X IDEでプログラムをPICに書き込む

1行目にHello、1秒後に2行目にWorldを表示します。