아트메가/활용

CLCD ATMEGA128로 제어하기 3편(I2C)

원원 2022. 10. 3. 19:25

안녕하세요. 오늘은 I2C(TWI)통신을 통해서 ATMEGA로 LCD를 제어해보겠습니다.

 

일단은 ATMEGA128로 I2C통신을통해 LCD를 제어하려면 여러가지 알아야 합니다.

1. CLCD 사용방법
1) CLCD MCU없이 제어하기(ADM1602) 1편
2) CLCD MCU없이 제어하기 (ADM1602) 2편
3) CLCD MCU없이 제어하기 (ADM1602) 3편
4) CLCD ATMEGA128로 제어하기 1편
5) CLCD ATMEGA128로 제어하기 2편

2. ATMEGA128로 TWI통신하는방법 
1) ATMEGA128 TWI(I2C)통신 알아보기 1편
2) ATMEGA128 TWI(I2C)통신 알아보기 2편
3) ATMEGA128 TWI(I2C)통신 알아보기 3편

3. PCF8574 사용방법
1) PCF8574 IC 알아보기

위의 3가지를 모두 알아야 합니다.

 

 

* 회로도

CLCD에 PCF8574를 연결해서 I2C로 제어합니다. 여기서는 아래 그림처럼 회로도가 구성되어있는 제품을 사용합니다.

위 제품의 회로도입니다. 여기서 중요한건 PCF8574와 CLCD가 연결된 회로입니다.
P0 : RS          0x01
P1 : RW         0x02
P2 : E             0x04
P3 : LIGHT     0x08
P4 : D4           0x10
P5 : D5           0x20
P6 : D6           0x40
P7 : D7           0x80

4bit모드를 사용해야하고 MCU와 CLCD는 선을 4가닥 연결해야합니다.(SDA,SCL,5V,GND)
그리고 P3핀은 LED전원인데 항상 키기위해서 0x08을 OR연산해줬습니다

 

*파형
LCD는 D0~D7 세팅을하고 ENABLE을 HIGH -> LOW 해줘야합니다. 4비트를 세팅할때 아래의 파형처럼 해주면 됩니다. 데이터를 세팅하고 ENABLE을 HIGH ->LOW 해줍니다.

 

- 초기세팅
1. P0~P7를 0으로 초기화시킵니다


2. "CLCD ATMEGA128로 제어하기 1편"에 있는 내용인데 LCD를 초기화시키기 위해서 아래의 세 과정을 해줄겁니다.
4bit사용을 세팅해줍니다. 

 

3. 화면을 클리어합니다

 

3. display on+커서표시+커서깜빡임을 세팅합니다

위의 1~3번 과정을하면 커서가 표시되고 커서가 깜빡이게 됩니다.

4. A를 표시합니다.

4번을하면 A가 표시됩니다. 데이터를 표시해야하니까 RS를 HIGH로 설정했습니다.( DR 모드)

 

*코드

#define __DELAY_BACKWARD_COMPATIBLE__
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <string.h>
#include <stdio.h>
#include "function.h"

int main(void)
{
	sei();
	twi_init();

	twi_write1(0x27,0x00);
	_delay_ms(1000);
	twi_write_lcd_ir_init(0x27,0x20);
	twi_write_lcd_ir(0x27,0x00,0x10);
	twi_write_lcd_ir(0x27,0x00,0xf0);
	twi_write_lcd_dr(0x27,0x40,0x10);
	while(1)
	{
	}
}
void twi_init()
{
	PORTD |= 0x03; // SDA,SCL pull-up setting PD0: SCL, PD1: SDA
	/* SCL 100kHz */
	TWBR = 0x48;
	TWSR = 0x00;
	
	TWCR = (1<<TWINT)|(1<<TWEN);
}

unsigned char twi_write_lcd_ir_init(unsigned char add, unsigned char dat1)
{
	int i;
	_delay_ms(1);
	dat1 |= 0x08;
	/* STEP1 Start */
	TWCR = (1<<TWSTA)|(1<<TWINT)|(1<<TWEN); //start

	/* STEP2 Start check */
	while(1)
	{
		if((TWCR & 0x80) && ((TWSR & 0xf8) == 0x08))
		break;
	}

	/* STEP3 Address send */
	TWDR = add<<1 | 0; // slave address, write
	TWCR = (1<<TWINT)|(1<<TWEN);

	/* STEP4 ACK Check */
	while(1)
	{
		if((TWCR & 0x80) && ((TWSR & 0xf8) ==0x18))
		break;
		if((TWCR & 0x80) && ((TWSR & 0xf8) == 0x20))
		return 0;
	}
	
	for(i=0; i<3; i++)
	{
		/* STEP5 Data1 send */
		if(i==1)
		TWDR = dat1 | 0x04;
		else
		TWDR = dat1;
		TWCR = (1<<TWINT)|(1<<TWEN);
		/* STEP6 Data send check */
		while(1)
		{
			if((TWCR & 0x80) && ((TWSR & 0xf8) == 0x28))
			break;
			if((TWCR & 0x80) && ((TWSR & 0xf8) == 0x30))
			return 0;
		}
		_delay_us(100);
	}

	/* STEP9 STOP */
	TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
	return 1;
}

unsigned char twi_write_lcd_ir(unsigned char add, unsigned char dat1, unsigned char dat2)
{
	int i;
	_delay_ms(1);
	dat1 |= 0x08;
	dat2 |= 0x08;
	/* STEP1 Start */
	TWCR = (1<<TWSTA)|(1<<TWINT)|(1<<TWEN); //start

	/* STEP2 Start check */
	while(1)
	{
		if((TWCR & 0x80) && ((TWSR & 0xf8) == 0x08))
		break;
	}

	/* STEP3 Address send */
	TWDR = add<<1 | 0; // slave address, write
	TWCR = (1<<TWINT)|(1<<TWEN);

	/* STEP4 ACK Check */
	while(1)
	{
		if((TWCR & 0x80) && ((TWSR & 0xf8) ==0x18))
		break;
		if((TWCR & 0x80) && ((TWSR & 0xf8) == 0x20))
		return 0;
	}
	
	for(i=0; i<3; i++)
	{		
		/* STEP5 Data1 send */
		if(i==1)
			TWDR = dat1 | 0x04;
		else
			TWDR = dat1;
		TWCR = (1<<TWINT)|(1<<TWEN);
		/* STEP6 Data send check */
		while(1)
		{
			if((TWCR & 0x80) && ((TWSR & 0xf8) == 0x28))
			break;
			if((TWCR & 0x80) && ((TWSR & 0xf8) == 0x30))
			return 0;
		}
		_delay_us(100);
	}
	for(i=0; i<3; i++)
	{
		/* STEP5 Data1 send */
		if(i==1)
		TWDR = dat2 | 0x04;
		else
		TWDR = dat2;
		TWCR = (1<<TWINT)|(1<<TWEN);
		/* STEP6 Data send check */
		while(1)
		{
			if((TWCR & 0x80) && ((TWSR & 0xf8) == 0x28))
			break;
			if((TWCR & 0x80) && ((TWSR & 0xf8) == 0x30))
			return 0;
		}
		_delay_us(100);
	}

	
	
	/* STEP9 STOP */
	TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
	return 1;
}
unsigned char twi_write_lcd_dr(unsigned char add, unsigned char dat1, unsigned char dat2)
{
	int i;
	_delay_ms(1);
	dat1 |= (0x08 | 0x01);
	dat2 |= (0x08 | 0x01);
	/* STEP1 Start */
	TWCR = (1<<TWSTA)|(1<<TWINT)|(1<<TWEN); //start

	/* STEP2 Start check */
	while(1)
	{
		if((TWCR & 0x80) && ((TWSR & 0xf8) == 0x08))
		break;
	}

	/* STEP3 Address send */
	TWDR = add<<1 | 0; // slave address, write
	TWCR = (1<<TWINT)|(1<<TWEN);

	/* STEP4 ACK Check */
	while(1)
	{
		if((TWCR & 0x80) && ((TWSR & 0xf8) ==0x18))
		break;
		if((TWCR & 0x80) && ((TWSR & 0xf8) == 0x20))
		return 0;
	}
	
	for(i=0; i<3; i++)
	{
		/* STEP5 Data1 send */
		if(i==1)
		TWDR = dat1 | 0x04;
		else
		TWDR = dat1;
		TWCR = (1<<TWINT)|(1<<TWEN);
		/* STEP6 Data send check */
		while(1)
		{
			if((TWCR & 0x80) && ((TWSR & 0xf8) == 0x28))
			break;
			if((TWCR & 0x80) && ((TWSR & 0xf8) == 0x30))
			return 0;
		}
		_delay_us(100);
	}
	for(i=0; i<3; i++)
	{
		/* STEP5 Data1 send */
		if(i==1)
		TWDR = dat2 | 0x04;
		else
		TWDR = dat2;
		TWCR = (1<<TWINT)|(1<<TWEN);
		/* STEP6 Data send check */
		while(1)
		{
			if((TWCR & 0x80) && ((TWSR & 0xf8) == 0x28))
			break;
			if((TWCR & 0x80) && ((TWSR & 0xf8) == 0x30))
			return 0;
		}
		_delay_us(100);
	}

	
	
	/* STEP9 STOP */
	TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
	return 1;
}

unsigned char twi_write1(unsigned char add, unsigned char dat1)
{
	/* STEP1 Start */
	TWCR = (1<<TWSTA)|(1<<TWINT)|(1<<TWEN); //start

	/* STEP2 Start check */
	while(1)
	{
		if((TWCR & 0x80) && ((TWSR & 0xf8) == 0x08))
		break;
	}

	/* STEP3 Address send */
	TWDR = add<<1 | 0; // slave address, write
	TWCR = (1<<TWINT)|(1<<TWEN);

	/* STEP4 ACK Check */
	while(1)
	{
		if((TWCR & 0x80) && ((TWSR & 0xf8) ==0x18))
		break;
		if((TWCR & 0x80) && ((TWSR & 0xf8) == 0x20))
		return 0;
	}
	
	/* STEP5 Data1 send */
	TWDR = dat1;
	TWCR = (1<<TWINT)|(1<<TWEN);

	/* STEP6 Data send check */
	while(1)
	{
		if((TWCR & 0x80) && ((TWSR & 0xf8) == 0x28))
		break;
		if((TWCR & 0x80) && ((TWSR & 0xf8) == 0x30))
		return 0;
	}
	

	/* STEP9 STOP */
	TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
	return 1;
}

 

이제 CLCD제어는 그만하겠습니다.

 

CLCD MCU없이 제어하기 (ADM1602) 1편 => CLCD 기초설명
CLCD MCU없이 제어하기 (ADM1602) 2편 => 여러기능 테스트
CLCD MCU없이 제어하기 (ADM1602) 3편 => DDRAM,CGROM,CGRAM,AC설명
CLCD ATMEGA128로 제어하기 1편
CLCD ATMEGA128로 제어하기 2편
CLCD ATMEGA128로 제어하기 3편(I2C)