KAIMU-UA1 Ext. 01 I
2
C-LCD
(Kaimunantai - Universal circuit board – AVR - no.1)
ソフトウェア開発説明書
※開発環境のインストールなどはua1-00-avr-start.pdfを参照してください。
※プログラム開発環境の操作については、
Mac
ではua1-crosspackavr-xcode.pdfを、Windows
で はua1-atmelstudio-6.pdfを参照してください。1
使用するデバイス
KAIMU-UA1 Extension 01
I2C 接続液晶ディスプレイ AQM1602XA-RN-GBW Sitronix ST7032 による制御
2
必要なライブラリ
本機で使用する液晶ディスプレイモジュールは、
I2C
インタフェースで接続されるため、I2C
イ ンタフェース(AVR
マイコンではTWI
という)のライブラリが必要です。また、液晶ディスプレイに文字を表示するには、複雑なコマンドが必要ですが、それらを処理 してくれる関数ライブラリも必要となります。
本稿では、下記のライブラリを利用します。
(1) I2Cインタフェースライブラリ
ヘッダファイル i2cmaster.h
ソースコード twimaster.c
i2c-master interface for avrgcc
((C) 2015 Peter Fleury, GNU General Public License Version 3)
http://homepage.hispeed.ch/peterfleury/avr-software.html#libs
(2) 液晶ディスプレイの制御コード
ヘッダファイル i2c_lcd.h
ソースコード i2c_lcd.c
over80 氏の下記 URL に掲載されたコードを参考に、関数の書式を統一し、さらに KeinSoft で作 成した拡張関数を追加したものです
(3) makefileの例
# AVR-GCC Makefile
PROJECT=i2c-timer-lcd-led-buz-sw-adc-atmega168 SOURCES=$(PROJECT).c twimaster.c i2c_lcd.c CC=avr-gcc
OBJCOPY=avr-objcopy CLOCK = 1000000
MMCU=atmega168 TARGETDEV=m168p #MMCU=atmega328p #TARGETDEV=atmega328p
CFLAGS=-g -O2 -mmcu=$(MMCU) -Wall -DF_CPU=$(CLOCK)
$(PROJECT).hex: $(PROJECT).out
$(OBJCOPY) -j .text -j .data -O ihex $(PROJECT).out $(PROJECT).hex
$(PROJECT).out: $(SOURCES)
$(CC) $(CFLAGS) -I./ -o $(PROJECT).out $(SOURCES)
program: $(PROJECT).hex
sudo avrdude -p $(TARGETDEV) -P usb -c avrispmkII -e -U flash:w:$(PROJECT).hex clean:
rm -f $(PROJECT).out rm -f $(PROJECT).hex
(4) Xcodeで開発する場合の設定変更
[firmware]を[control]キーを押しながらクリックし、[Add Files “KAIMU-UA1”...]
をクリックします。
i2c_lcd.c , i2c_lcd.h , i2cmaster.h , twimaster.c を選択し、
[Add]をクリックします。
[Makefile]をクリックし、内容を修正します。
(修正箇所は
赤字
)DEVICE =
atmega168
AVRDUDE_DEVICE = m168p
CLOCK =
1000000
PROGRAMMER =
-c avrispmkII -P usb
OBJECTS = main.o
i2c_lcd.o twimaster.o
FUSES = -U hfuse:w:0x
df
:m -U lfuse:w:0x
62
:m
… (中略)…
3
液晶ディスプレイに文字を表示
(1) サンプルコード 液晶ディスプレイの初期化と文字の出力
#include <avr/io.h> #include <util/twi.h> #include "i2cmaster.h" #include "i2c_lcd.h"
/*
* initialize */
static inline void initIo(void) {
PORTD = (1<<PD2); // weak pull up resistor enagle on PD2 DDRD = 0b11111011; // PD2 as Input, others Output
DDRB = 0b11111111; // PORTB All Output }
/* * main */
int main(void) {
initIo(); //出力の初期化
i2c_lcd_init(); // 液晶ディスプレイの初期化
i2c_lcd_setContrast(20);
// 液晶ディスプレイのコントラストを 20 に設定(0〜63 に設定可能) i2c_lcd_clearDisplay(); // 液晶ディスプレイを消去
i2c_lcd_sendString(0x00, "KeinSoft", 8);
//アドレス 0x00 番地に KeinSoft という 8 文字の文字列を出力 i2c_lcd_sendString(0x40, "TEST", 4);
//アドレス 0x40 番地に TEST という4文字の文字列を出力
4
指定した行、列に文字列を表示する
(1) i2c_lcd_putStringRC関数
液晶ディスプレイの指定した行と列に文字列を表示するには、i2c_lcd_putStringRC 関数を使 います。
この関数は、下記の書式で使用します。
i2c_lcd_putStringRC(表示する行, 表示する列, “文字列”);
なお、本機の液晶ディスプレイは 2 行 x16 列が表示できるため、行は 1〜2、列は 1〜16 までの 数値を指定できます。
(2) サンプルコード
#include <avr/io.h> #include <util/twi.h> #include <string.h> #include "i2cmaster.h" #include "i2c_lcd.h"
/*
* initialize */
static inline void initIo(void) {
PORTD = (1<<PD2); // weak pull up resistor enagle on PD2 DDRD = 0b11111011; // PD2 as Input, others Output
DDRB = 0b11111111; // PORTB All Output }
/* * main */
int main(void) {
initIo();
i2c_lcd_init(); // 液晶ディスプレイの初期化
i2c_lcd_setContrast(20); // 液晶ディスプレイのコントラストを 20 に設定 i2c_lcd_clearDisplay(); // 液晶ディスプレイを消去
while (1) {
5
指定した行、列へ整数値を出力する。
(1) i2c_lcd_putNumberRC関数
整数型変数の値を出力するには、i2c_lcd_putNumberRC 関数を使います。この関数の書式は下 記の通りです。
i2c_lcd_putNumberRC(表示する行, 表示する列, 整数値または符号なし整数型変数, 表示桁数);
なお、本機の液晶ディスプレイは 2 行 x16 列が表示できるため、行は 1〜2、列は 1〜16 までの 数値を指定できます。
(2) サンプルコード 一定間隔で増加していく数値を出力する。
#include <avr/io.h> #include <util/twi.h> #include "i2cmaster.h" #include "i2c_lcd.h"
static inline void wait(volatile unsigned long i) {
while (i-- > 0); }
static inline void initIo(void) {
PORTD = (1<<PD2); // weak pull up resistor enagle on PD2 DDRD = 0b11111011; // PD2 as Input, others Output
DDRB = 0b11111111; // PORTB All Output }
int main(void) {
volatile unsigned int number = 0; // 数値を数える変数を宣言、0 で初期化
initIo(); //出力の初期化
i2c_lcd_init(); // 液晶ディスプレイの初期化
i2c_lcd_setContrast(20); // 液晶ディスプレイのコントラストを 20 に設定 i2c_lcd_clearDisplay(); // 液晶ディスプレイを消去
while (1) {
i2c_lcd_putNumberRC(1, 1, number, 16);// 1 行 1 列に number 変数の値を 16 桁で出力 number++; // number 変数を1増やす
wait(100); // ちょっと待つ }
6
応用プログラム
スイッチを押すと、1 秒ごとにカウントアップしていくプログラム
#include <avr/io.h>
#include <avr/interrupt.h> #include <util/twi.h> #include "i2cmaster.h" #include "i2c_lcd.h"
static inline void wait(volatile unsigned long i) {
while (i-- > 0); }
static inline int isSwitchOn(void) {
return ( !( PIND & (1<<PD2) ) ); }
/*
* stage definition */
enum {
STAGE_READY, STAGE_COUNTUP };
static volatile uint8_t STAGE = STAGE_READY;
/*
* Interrupt */
#define TIMER0_1SEC 1000
volatile unsigned int T0count; // Timer0 割込み発生回数のカウンタ
ISR(TIMER0_COMPA_vect) // Timer0 の割込み処理 {
T0count++; }
/*
* initialize */
static inline void initIo(void) {
static inline void initTimer0(void)
// TIMER0 の初期化 約1ミリ秒ごとにタイマ割込みが発生する {
// CTC mode , TOP is OCR0A
TCCR0A = (1 << WGM01) | (0 << WGM00) ; // I/O clock prescaler N = 8
TCCR0B = (0 << WGM02) | (0 << CS02) | (1 << CS01) | (0 << CS00); // Timer0 on OCR0A compare match interrupt enable
TIMSK0 |= ( 1<< OCIE0A );
// set TOP value . Interrupt every 1 ms
OCR0A = 125; // OCR0A = interrupt period [s] * f_clkio [Hz] / clock prescaler N }
int main(void) {
volatile unsigned int number = 0; // 数値を数える変数を宣言、0 で初期化
initIo(); // 出力の初期化
i2c_lcd_init(); // 液晶ディスプレイの初期化 initTimer0(); // Timer0 の初期化
i2c_lcd_clearDisplay(); // 液晶ディスプレイを消去
i2c_lcd_setContrast(20); // 液晶ディスプレイのコントラストを 20 に設定
while (1) {
switch (STAGE ) { case STAGE_READY : number = 0; T0count = 0;
i2c_lcd_putNumberRC(1, 1, number, 16); if (isSwitchOn() ) {
//スイッチが押されたら、カウントアップのステージに移行 STAGE = STAGE_COUNTUP;
T0count = 0;
while (isSwitchOn()); // スイッチが離されるまで待つ sei(); // 割込み待ち受けの開始
} break;
case STAGE_COUNTUP :
i2c_lcd_putNumberRC(1, 1, number, 16); // 1 行 1 列に number 変数の値を 16 桁で出力 if ( T0count > TIMER0_1SEC ) {
T0count = 0; number++;
} // number 変数を 1 秒ごとに 1 増やす break;
default :
i2c_lcd_clearDisplay(); // 液晶ディスプレイを消去 }
}