ユニバーサル基板工作練習回路 機能拡張1 I2C接続液晶ディスプレイ編
( Kaimunantai–UA1 Extension no. 1 I2C Liquid Crystal Display )
I2C接続の液晶ディスプレイを接続したもの。
I2C接続薄型16文字×2行液晶 変換基板キット AQM1602XA-RN-GBW Sitronix ST7032 controled
ピンソケット 4ピン
カーボン抵抗器 10kΩ × 2個、1/4 W
配線材 Φ0.32mm
(機能)押しボタンスイッチを押すと、10秒カウントダウンして、アラームが鳴る。
LCDの制御用に、下記のコードを使用させていただいた。
ヘッダファイル 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
ヘッダファイル i2c_lcd.h
ソースコード i2c_lcd.c
over80氏の下記URLに掲載されたコードを参考に、関数の書式を統一し、さらにKeinSoftで作成した拡張関数を追加したもの
http://d.hatena.ne.jp/over80/20141013/1413174967
//// kaimu-ua1-i2clcd-mega168.c//// Created by kaimunantai on 2015/12/31./* * Target : ATmega168P / 328P * OUTPUT : * LED : PD0 (PIN 2) * Buzzer : PB0 (PIN14) * LCD (AQM1602XA-RN-GBW) : I2C (TWI) SCL(PIN27) , SDA (PIN28) * INPUT : * tact switch sw0 : PD2 / INT0 (PIN 4) * */// #define F_CPU 1000000UL // define in makefile#include <avr/io.h>#include <avr/interrupt.h>#include <util/delay.h>#include <util/twi.h>#include <string.h>#include "i2cmaster.h"#include "i2c_lcd.h"/* * i2c-master interface for avrgcc ((C) 2015 Peter Fleury, GNU General Public License Version 3) *http://homepage.hispeed.ch/peterfleury/avr-software.html#libs * *//* * I/O Control MACROs */#define led() ( PORTD ^= (1<<PD0) )#define ledOn() ( PORTD |= (1<<PD0) )#define ledOff() ( PORTD &= ~(1<<PD0) )#define isSw0On() ( !( PIND & (1<<PD2) ) )#define isSw0Off() ( PIND & (1<<PD2) )#define buzOn() ( PORTB ^= (1<<PB0) )/* * stage definition */enum { STAGE_START, STAGE_READY, STAGE_COUNTDOWN, STAGE_ALARM, STAGE_END};static volatile uint8_t STAGE = STAGE_START;static inline void wait(volatile unsigned long i){ while (i-- > 0);}inline void beepOn(unsigned int tone, unsigned long length)// beep by Buzzer// Arguments :// tone : tone height , tone 2 (high) ~ 1000 (low)// length : beep sound time{ length /= tone; while (length-- > 0) { buzOn(); wait(tone); }}/* * initialize */static inline void io_init(void){ PORTD = (1<<PD2); // weak pull up resistor enagle on PD2 DDRD = 0b11111011; // PD2 as Input, others Output DDRB = 0b11111111; // PORTB All Output}static inline void int0_init(void){ EICRA |= (1<<ISC01) | (1<<ISC11); // INT0 Falling Edge, INT1 Falling edge EIMSK |= (1<<INT0) | (1<<INT1); // Enable Interrupt 0, 1}static inline void timer0_init(void)// Initialize TIMER0{ // 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] / I/O clock prescaler N}/* * Interrupt */volatile unsigned int T0count; // Timer0 interrupt counter#define TIMER0_LIMIT 65535#define TIMER0_10SEC 10000#define TIMER0_1SEC 1000#define TIMER0_500MSEC 500ISR(TIMER0_COMPA_vect)// Timer0 Timer counter Compair match Interrupt{ if ( T0count > TIMER0_LIMIT ) { T0count = 0; } else { T0count++; } }ISR(INT0_vect)// INT0 Interrupt{ switch ( STAGE ) { case STAGE_START : STAGE = STAGE_READY; break; case STAGE_READY : STAGE = STAGE_COUNTDOWN; break; case STAGE_COUNTDOWN : STAGE = STAGE_END; break; case STAGE_ALARM : STAGE = STAGE_START; break; default : STAGE = STAGE_START; } beepOn(10, 5000); while(isSw0On());}inline void putMinSec(int minutes, int seconds){ i2c_lcd_putNumberRC(2, 10, (unsigned)minutes, 2); i2c_lcd_putStringRC(2, 12, ":"); i2c_lcd_putNumberRC(2, 13, (unsigned)seconds, 2);}/* * main */int main(void){ int minutes = 0, seconds = 0; // minutes , seconds for timer io_init(); int0_init(); timer0_init(); i2c_lcd_init(); ledOn(); while(isSw0On()); // wait until switch released ledOff(); sei(); // Enable Interrupt i2c_lcd_setContrast(20); i2c_lcd_clearDisplay(); while (1) { switch ( STAGE ) { case STAGE_START : i2c_lcd_putStringRC(1, 1, " LCD-TIMER168 "); i2c_lcd_putStringRC(2, 1, " by KeinSoft "); break; case STAGE_READY : i2c_lcd_putStringRC(2, 1, "**START* "); seconds = 10; STAGE = STAGE_COUNTDOWN; T0count = 0; putMinSec(minutes, seconds); break; case STAGE_COUNTDOWN : if (T0count >= TIMER0_1SEC) { led(); seconds--; if (minutes <= 0 && seconds <= 0) { STAGE = STAGE_ALARM; ledOff(); i2c_lcd_putStringRC(2, 1, "!!! ALARM !!!! "); } else { if ( seconds <= 0) { seconds = 59; minutes--; } putMinSec(minutes, seconds); } T0count = 0; } break; case STAGE_ALARM : led(); beepOn(5,10000); wait(5000); break; case STAGE_END : i2c_lcd_putStringRC(1, 1, " KeinSoft 2015 "); i2c_lcd_putStringRC(2, 1, " BYE-BYE "); break; default : ledOff(); } } return 0;}# AVR-GCC Makefile PROJECT=kaimu-ua1-i2clcd-mega168 SOURCES=$(PROJECT).c twimaster.c i2c_lcd.c CC=avr-gcc OBJCOPY=avr-objcopy F_CPU=1000000 MMCU=atmega168 TARGETDEV=m168p #MMCU=atmega328p #TARGETDEV=atmega328p CFLAGS=-g -O2 -mmcu=$(MMCU) -Wall -DF_CPU=$(F_CPU) $(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).hexsudo avrdude -p $(TARGETDEV) -P usb -c avrispmkII -e -U flash:w:$(PROJECT).hex
clean:rm -f $(PROJECT).out
rm -f $(PROJECT).hex