Skip to content

Instantly share code, notes, and snippets.

@hunamizawa
Created March 26, 2019 05:07
Show Gist options
  • Save hunamizawa/4dbf34f331510b8fe45230b0bfdb7740 to your computer and use it in GitHub Desktop.
Save hunamizawa/4dbf34f331510b8fe45230b0bfdb7740 to your computer and use it in GitHub Desktop.
ATTiny13A I2C test with Atmel Studio
#define F_CPU 1200000UL
//
// tinyI2Clib 用 SC1602 + PCF8574 I2Cキャラクタ液晶モジュール制御ライブラリ by hunamizawa
//
// たま吉さん作の「tinyI2C用 I2C接続キャラクタLCDモジュール用ライブラリ」
// (秋月電子 ACM1602NI-FLW-FBW-M01 向け)を SC1602 + PCF8574 へ移植したものです
// 元のソースは http://nuneno.cocolog-nifty.com/blog/attiny13a/index.html にあります
//
// 2014/11/05 たま吉さん
// 2019/03/26 移植 by hunamizawa
//
// 参考HP
// http://akizukidenshi.com/catalog/g/gP-05693/
// http://elm-chan.org/docs/lcd/hd44780_j.html
// http://219.117.208.26/~saka/ham/LCD2/
// TI社 PCF8574 データシート
#define I2C_ADDR_READ 0x41
#define I2C_ADDR_WRITE 0x40
#include "F_CPU.h"
#include <avr/io.h>
#include <util/delay.h>
#include "tinyI2C.h"
#include "I2CLCD.h"
uint8_t DisplayMode;
uint8_t DisplayControl;
void _Write4_Intl_(uint8_t cmd) {
I2C_Start();
I2C_Write(I2C_ADDR_WRITE);
I2C_ReadBit();
I2C_Write(0);
I2C_ReadBit();
I2C_Write(cmd);
I2C_ReadBit();
I2C_Stop();
}
void Write4(uint8_t cmd) {
uint8_t c = (cmd | DPORT_BACKLIGHT);
_Write4_Intl_(c | DPORT_E);
_Write4_Intl_(c);
}
void Write8(uint8_t cmd) {
Write4(cmd & 0xF0);
Write4(cmd << 4);
}
// コマンド送信
void Lcd_writeCmd(uint8_t cmd) {
Write8(cmd);
}
// データ送信
void WriteData(uint8_t data) {
Write4((data & 0xF0) | DPORT_RS);
Write4((data << 4) | DPORT_RS);
}
// LCD初期化
void LCD_init() {
DisplayControl = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
DisplayMode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
_delay_ms(30);
Write4(LCD_FUNCTIONSET | 0x10);
_delay_ms(10);
Write4(LCD_FUNCTIONSET | 0x10);
//_delay_ms(1);
Write4(LCD_FUNCTIONSET | 0x10);
//_delay_ms(10);
Write4(LCD_FUNCTIONSET);
//_delay_ms(10);
Write8(LCD_FUNCTIONSET | 0x08);
Write8(LCD_DISPLAYCONTROL | DisplayControl);
//_delay_ms(10);
Write8(LCD_CLEARDISPLAY);
_delay_ms(5);
Write8(LCD_ENTRYMODESET | DisplayMode);
//_delay_ms(10);
LCD_setCursor(0, 0);
}
// カーソル移動
void LCD_setCursor(uint8_t col, uint8_t row) {
uint8_t row_offsets[] = { 0x00, 0x40 };
if (row >= NUM_LINES) {
row = NUM_LINES - 1;
}
Write8(LCD_SETDDRAMADDR | (col + row_offsets[row]));
}
// 非表示設定
void LCD_noDisplay() {
DisplayControl &= ~LCD_DISPLAYON;
Write8(LCD_DISPLAYCONTROL | DisplayControl);
}
// 表示設定
void LCD_display() {
DisplayControl |= LCD_DISPLAYON;
Write8(LCD_DISPLAYCONTROL | DisplayControl);
}
// カーソル非表示
void LCD_noCursor() {
DisplayControl &= ~LCD_CURSORON;
Write8(LCD_DISPLAYCONTROL | DisplayControl);
}
// カーソル表示
void LCD_cursor() {
DisplayControl |= LCD_CURSORON;
Write8(LCD_DISPLAYCONTROL | DisplayControl);
}
// カーソルブリンクなし
void LCD_noBlink() {
DisplayControl &= ~LCD_BLINKON;
Write8(LCD_DISPLAYCONTROL | DisplayControl);
}
// カーソルブリンク
void LCD_blink() {
DisplayControl |= LCD_BLINKON;
Write8(LCD_DISPLAYCONTROL | DisplayControl);
}
// 文字列表示
void LCD_string(char *str) {
for (uint8_t i = 0; i < 16; i++) {
if (str[i] == 0x00) {
break;
} else {
WriteData(str[i]);
}
}
}
//
// tinyI2Clib 用 SC1602 + PCF8574 I2Cキャラクタ液晶モジュール制御ライブラリ by hunamizawa
//
// たま吉さん作の「tinyI2C用 I2C接続キャラクタLCDモジュール用ライブラリ」
// (秋月電子 ACM1602NI-FLW-FBW-M01 向け)を SC1602 + PCF8574 へ移植したものです
// 元のソースは http://nuneno.cocolog-nifty.com/blog/attiny13a/index.html にあります
//
// 2014/11/05 たま吉さん
// 2019/03/26 移植 by hunamizawa
//
// 参考HP
// http://akizukidenshi.com/catalog/g/gP-05693/
// http://elm-chan.org/docs/lcd/hd44780_j.html
// http://219.117.208.26/~saka/ham/LCD2/
// TI社 PCF8574 データシート
#ifndef I2CLCD_H_
#define I2CLCD_H_
// for LCD
#define NUM_LINES 2
// 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
#define DPORT_RS 0x01
#define DPORT_E 0x04
#define DPORT_BACKLIGHT 0x08
#define LCD_clear() Lcd_writeCmd(LCD_CLEARDISPLAY)
#define LCD_home() Lcd_writeCmd(LCD_RETURNHOME)
// コマンド送信
void Lcd_writeCmd(uint8_t cmd);
// LCD初期化
void LCD_init();
// カーソル移動
void LCD_setCursor(uint8_t col, uint8_t row);
// 非表示設定
void LCD_noDisplay();
// 表示設定
void LCD_display();
// カーソル非表示
void LCD_noCursor();
// カーソル表示
void LCD_cursor();
// カーソルブリンクなし
void LCD_noBlink();
// カーソルブリンク
void LCD_blink();
// 文字列表示
void LCD_string(char *str);
#endif /* I2CLCD_H_ */
#include "F_CPU.h"
#include <avr/io.h>
#include <util/delay.h>
#include "tinyI2C.h"
#include "I2CLCD.h"
int main(void)
{
I2C_Init();
LCD_init();
while (1)
{
LCD_home();
_delay_ms(5);
LCD_string("Hello world.");
LCD_setCursor(0, 1);
LCD_string("This is tiny13A.");
_delay_ms(2000);
LCD_clear();
_delay_ms(500);
}
}
//
// ATtiny13 用 I2C ライブラリ tinyI2Clib for Atmel Studio by hunamizawa
//
// たま吉さん作の Arduino IDE 向けコードを Atmel Studio へ移植したものです
// 元のソースは http://nuneno.cocolog-nifty.com/blog/attiny13a/index.html にあります
//
// 2014/11/04 作成 by たま吉さん
// 2018/04/15 I2C_DATA_HI(),I2C_DATA_LO(),I2C_Stop(),I2C_Init(),ディレイ時間の修正 by たま吉さん
// 2019/03/26 移植 by hunamizawa
//
// 参考HP
// オリジナルソース I2C on an AVR using bit banging
// http://codinglab.blogspot.jp/2008/10/i2c-on-avr-using-bit-banging.html
// オリジナル応用例 bvdeenen/arduino-ethernet-tmp102
// https://github.com/bvdeenen/arduino-ethernet-tmp102/blob/master/temp_humidity.ino
//
#include "F_CPU.h"
#include <avr/io.h>
#include <util/delay.h>
#include "tinyI2C.h"
// Port for the I2C
#define I2C_DDR DDRB
#define I2C_PIN PINB
#define I2C_PORT PORTB
// Pins to be used in the bit banging
#define I2C_CLK PORTB3
#define I2C_DAT PORTB4
#define I2C_DATA_HI() I2C_DDR &= ~(1<<I2C_DAT)
#define I2C_DATA_LO() I2C_DDR |= (1<<I2C_DAT)
#define I2C_CLOCK_HI() I2C_DDR &= ~(1 << I2C_CLK); I2C_PORT |= (1 << I2C_CLK)
#define I2C_CLOCK_LO() I2C_DDR |= (1 << I2C_CLK); I2C_PORT &= ~(1 << I2C_CLK)
#define RWWAIT 10
void I2C_WriteBit(uint8_t c) {
if (c > 0) {
I2C_DATA_HI();
} else {
I2C_DATA_LO();
}
I2C_CLOCK_HI();
while ((I2C_PIN & (1 << I2C_CLK)) == 0) ;
_delay_us(RWWAIT);
I2C_CLOCK_LO();
_delay_us(RWWAIT);
if (c > 0) {
I2C_DATA_LO();
}
_delay_us(RWWAIT);
}
uint8_t I2C_ReadBit() {
I2C_DATA_HI();
I2C_CLOCK_HI();
while ((I2C_PIN & (1 << I2C_CLK)) == 0) ;
_delay_us(RWWAIT);
uint8_t c = I2C_PIN;
I2C_CLOCK_LO();
_delay_us(RWWAIT);
return (c >> I2C_DAT) & 1;
}
// Inits bitbanging port, must be called before using the functions below
//
void I2C_Init() {
I2C_DDR &= ~((1 << I2C_CLK) | (1 << I2C_DAT)); //bus pulled hi by pullup resistor.
I2C_PORT &= ~((1 << I2C_CLK) | (1 << I2C_DAT)); // lo when output, HI-Z when input. NEVER CHANGE THIS.
I2C_CLOCK_HI();
I2C_DATA_HI();
}
// Send a START Condition
//
void I2C_Start() {
// set both to high at the same time
I2C_DDR &= ~((1 << I2C_DAT) | (1 << I2C_CLK));
_delay_us(RWWAIT);
I2C_DATA_LO();
_delay_us(RWWAIT);
I2C_CLOCK_LO();
_delay_us(RWWAIT);
}
// Send a STOP Condition
//
void I2C_Stop(){
I2C_CLOCK_LO();
I2C_DATA_LO();
I2C_CLOCK_HI();
_delay_us(RWWAIT);
I2C_DATA_HI();
_delay_us(RWWAIT);
}
// write a byte to the I2C slave device
//
void I2C_Write(uint8_t c) {
for (char i = 0; i < 8; i++) {
I2C_WriteBit(c & 0x80);
c <<= 1;
}
}
// read a byte from the I2C slave device
//
uint8_t I2C_Read(uint8_t ack) {
uint8_t res = 0;
for (char i = 0; i < 8; i++) {
res <<= 1;
res |= I2C_ReadBit();
}
if (ack > 0) {
I2C_WriteBit(0);
} else {
I2C_WriteBit(1);
}
return res;
}
//
// ATtiny13 用 I2C ライブラリ tinyI2Clib for Atmel Studio by hunamizawa
// たま吉さん作の Arduino IDE 向けコードを Atmel Studio へ移植したものです
// 元のソースは http://nuneno.cocolog-nifty.com/blog/attiny13a/index.html にあります
//
// 2019/03/26 移植に伴いヘッダファイル作成 by hunamizawa
//
#ifndef TINYI2C_H_
#define TINYI2C_H_
void I2C_WriteBit(uint8_t c);
uint8_t I2C_ReadBit();
// Inits bitbanging port, must be called before using the functions below
void I2C_Init();
// Send a START Condition
void I2C_Start();
// Send a STOP Condition
void I2C_Stop();
// write a byte to the I2C slave device
void I2C_Write(uint8_t c);
// read a byte from the I2C slave device
uint8_t I2C_Read(uint8_t ack);
#endif /* TINYI2C_H_ */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment