AQM0802Aは、8桁2行のLCDです。今回は秋月さんから購入しました。単品はこちら。キットはこちらです。
ハードの準備
このモジュールのインターフェイスはI2C。信号線2本でコントロール出来るので配線が楽に済みます。今回は単品で購入して秋月さんのHPの回路を元にESP32と下記の様に接続しています。
ESP32 | AQM0802A |
---|---|
GPIO22 | SCL |
GPIO21 | SDA |
ソフトの準備
ArduinoでAQM0802A用ソフトを探したら下記を見つけました。
これを元にESP-IDF用に変更しました。
- FaBoLCDmini_AQM0802A.cpp -> AQM0802A.c
- FaBoLCDmini_AQM0802A.h -> AQM0802A.h
// i2c - AQM0802A // i2c - AQM0802A
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "AQM0802A.h"
// i2c master initialization
esp_err_t i2c_master_init(void)
{
int i2c_master_port = I2C_MASTER_NUM;
i2c_config_t conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = I2C_MASTER_SDA_IO,
.scl_io_num = I2C_MASTER_SCL_IO,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = I2C_MASTER_FREQ_HZ,
};
i2c_param_config(i2c_master_port, &conf);
return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
}
// Write a byte to a AQM0802A
esp_err_t AQM0802A_write_byte(uint8_t data, uint8_t reg_addr)
{
int ret;
uint8_t write_buf[2] = {reg_addr, data};
ret = i2c_master_write_to_device(I2C_MASTER_NUM, AQM0802A_ADDR, write_buf, sizeof(write_buf), I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS);
return ret;
}
// Command write
void AQM0802A_command(uint8_t value)
{
AQM0802A_write_byte(value, (uint8_t)0x00);
}
// Data write
void AQM0802A_data(uint8_t value)
{
AQM0802A_write_byte(value, (uint8_t)0x40);
}
void AQM0802A_init(void)
{
uint8_t value = 0x00;
// Initializing
// Wait time >40mS After VDD stable
vTaskDelay(40 / portTICK_PERIOD_MS);
//Function Set: Normal mode:
// Dl: interface data 8/4bits
// N: number of line 2/1
// 001D Nxxx
// 0011 1000 : 0x38
value = 0x38;
AQM0802A_command(value);
// Wait time >26.3uS
//Function Set: Extension mode:
// Dl: interface data 8/4bits
// N: number of line 2/1
// dH: double height font
// Is: instruction table select
// 001D NH0I
// 0011 1001 : 0x39
value = 0x39;
AQM0802A_command(value);
// Wait time >26.3uS
//Internal OSC frequency:
// Bs: 1=1/4 bias 0=1/5 bias
// F2-0: adjust internal OSC frequency for FR frequency.
// 0001 BFFF
// 0001 0100 : 0x14
value = 0x14;
AQM0802A_command(value);
// Wait time >26.3uS
//Contrast set:
// C3-0: Contrast set for internal follower mode.
// 0111 CCCC
// 0111 0000 : 0x70
value = 0x70;
AQM0802A_command(value);
// Wait time >26.3uS
//Power/ICON control/Contrast set:
// Ion: ICON display on/off
// Bon: set booster circuit on/off
// C5-4: Contrast set for internal follower mode.
// 0101 IBCC
// 0101 0110 : 0x56
value = 0x56;
AQM0802A_command(value);
// Wait time >26.3uS
// Contrast initialize: xx10 0000(32d)
//Follower control:
// Fon: set follower circuit on/off
// Rab2-0: select follower amplified ratio.
// 0110 FRRR
// 0101 1100 : 0x6C
value = 0x6C;
AQM0802A_command(value);
// Wait time >26.3uS
//Function Set: Normal mode:
// Dl: interface data 8/4bits
// N: number of line 2/1
// 001D Nxxx
// 0011 1000 : 0x38
value = 0x38;
AQM0802A_command(value);
// Wait time >26.3uS
// turn the display on with no cursor or blinking default
_displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
// Initialize to default text direction (for romance languages)
_displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
AQM0802A_display();
AQM0802A_clear();
AQM0802A_home();
}
void AQM0802A_print(char* buf)
{
int a;
for(a = 0; a < strlen(buf); a++) AQM0802A_data(buf[a]);
}
void AQM0802A_clear()
{
AQM0802A_command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero
vTaskDelay(200 / portTICK_PERIOD_MS); // this command takes a long time!
}
void AQM0802A_home()
{
AQM0802A_command(LCD_RETURNHOME); // set cursor position to zero
vTaskDelay(200 / portTICK_PERIOD_MS); // this command takes a long time!
}
void AQM0802A_setCursor(uint8_t col, uint8_t row)
{
if(row) col += 0x40;
AQM0802A_command(LCD_SETDDRAMADDR | col);
}
void AQM0802A_noDisplay()
{
_displaycontrol &= ~LCD_DISPLAYON;
AQM0802A_command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void AQM0802A_display()
{
_displaycontrol |= LCD_DISPLAYON;
AQM0802A_command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void AQM0802A_noCursor()
{
_displaycontrol &= ~LCD_CURSORON;
AQM0802A_command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void AQM0802A_cursor()
{
_displaycontrol |= LCD_CURSORON;
AQM0802A_command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void AQM0802A_noBlink()
{
_displaycontrol &= ~LCD_BLINKON;
AQM0802A_command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void AQM0802A_blink()
{
_displaycontrol |= LCD_BLINKON;
AQM0802A_command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void AQM0802A_scrollDisplayLeft(void)
{
AQM0802A_command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
}
void AQM0802A_scrollDisplayRight(void)
{
AQM0802A_command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
}
void AQM0802A_leftToRight(void)
{
_displaymode |= LCD_ENTRYLEFT;
AQM0802A_command(LCD_ENTRYMODESET | _displaymode);
}
void AQM0802A_rightToLeft(void)
{
_displaymode &= ~LCD_ENTRYLEFT;
AQM0802A_command(LCD_ENTRYMODESET | _displaymode);
}
void AQM0802A_autoscroll(void)
{
_displaymode |= LCD_ENTRYSHIFTINCREMENT;
AQM0802A_command(LCD_ENTRYMODESET | _displaymode);
}
void AQM0802A_noAutoscroll(void)
{
_displaymode &= ~LCD_ENTRYSHIFTINCREMENT;
AQM0802A_command(LCD_ENTRYMODESET | _displaymode);
}
void AQM0802A_createChar(uint8_t location, uint8_t charmap[])
{
location &= 0x7; // we only have 8 locations 0-7
AQM0802A_command(LCD_SETCGRAMADDR | (location << 3));
for (int i=0; i<8; i++) AQM0802A_data(charmap[i]);
}
AQM0802A.h
#include "driver/i2c.h"
#define I2C_MASTER_SCL_IO 22 /*!< GPIO number used for I2C master clock */
#define I2C_MASTER_SDA_IO 21 /*!< GPIO number used for I2C master data */
#define I2C_MASTER_NUM 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
#define I2C_MASTER_FREQ_HZ 400000 /*!< I2C master clock frequency */
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#define I2C_MASTER_TIMEOUT_MS 1000
#define AQM0802A_ADDR 0x3e
// commands
#define LCD_CLEARDISPLAY 0x01
#define LCD_RETURNHOME 0x02
#define LCD_ENTRYMODESET 0x04
#define LCD_DISPLAYCONTROL 0x08
#define LCD_CURSORSHIFT 0x10
#define LCD_FUNCTIONSET 0x20
#define LCD_SETCGRAMADDR 0x40
#define LCD_SETDDRAMADDR 0x80
// flags for display entry mode
#define LCD_ENTRYRIGHT 0x00
#define LCD_ENTRYLEFT 0x02
#define LCD_ENTRYSHIFTINCREMENT 0x01
#define LCD_ENTRYSHIFTDECREMENT 0x00
// flags for display on/off control
#define LCD_DISPLAYON 0x04
#define LCD_DISPLAYOFF 0x00
#define LCD_CURSORON 0x02
#define LCD_CURSOROFF 0x00
#define LCD_BLINKON 0x01
#define LCD_BLINKOFF 0x00
// flags for display/cursor shift
#define LCD_DISPLAYMOVE 0x08
#define LCD_CURSORMOVE 0x00
#define LCD_MOVERIGHT 0x04
#define LCD_MOVELEFT 0x00
void AQM0802A_init(void);
void AQM0802A_print(char* buf);
//------------------- high level commands, for the user! ------------------
void AQM0802A_clear(void);
void AQM0802A_home(void);
void AQM0802A_setCursor(uint8_t col, uint8_t row);
void AQM0802A_noDisplay(void);
void AQM0802A_display(void);
void AQM0802A_noCursor(void);
void AQM0802A_cursor(void);
void AQM0802A_noBlink(void);
void AQM0802A_blink(void);
void AQM0802A_scrollDisplayLeft(void);
void AQM0802A_scrollDisplayRight(void);
void AQM0802A_leftToRight(void);
void AQM0802A_rightToLeft(void);
void AQM0802A_autoscroll(void);
void AQM0802A_noAutoscroll(void);
void AQM0802A_createChar(uint8_t location, uint8_t charmap[]);
void AQM0802A_setContrast(uint8_t contrast);
//------------------- mid level commands, for sending data/cmds ------------------
void AQM0802A_command(uint8_t value);
void AQM0802A_data(uint8_t value);
esp_err_t AQM0802A_write_byte(uint8_t data, uint8_t reg_addr);
esp_err_t i2c_master_init(void);
uint8_t _displaycontrol;
uint8_t _displaymode;
簡単なデモプログラムと実行
プログラムの構造を以下に示します。
- i2c_sample/
- components/
- AQM0802A/
- AQM0802A.c
- AQM0802A.h
- CMakeLists.txt
- main/
- CMakeLists.txt
- i2c_sample_main.c
- CMakeLists.txt
使用するCPUはESP32。モニターから、idf.py -p [USB PORT] flash monitor でコンパイル実行出来ます。
実行すると、LCDの1行、5桁目から ”ABC”。2行 2桁目から ”123” と表示されます。