AVR

[AVR] I2C 연습

박순창 2021. 4. 8. 09:11
728x90

제목 :

날짜 : 21.04.07

주제 : I2C 연습

목표 : I2C를 통해 LCD 글자 출력 

<활동>

- main.c -

#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>
#include "uart0.h"
#include "I2C.h"
#include "i2c_lcd.h"


FILE OUTPUT = FDEV_SETUP_STREAM(UART0_Transmit, NULL, _FDEV_SETUP_WRITE);

int main(void)
{	
	LCDInit();
	UART0_Init();
	stdout =&OUTPUT;
	
	LCDWriteStringXY(0,0,"hello world");
	int c=0;
	char stbuf[30];
    while (1) 
    {
		sprintf(stbuf,"count :%d",c++);
		LCDWriteStringXY(1,0,stbuf);
		_delay_ms(50);
    }
}

- i2c_lcd.c -

#include "i2c_lcd.h"

#define LCD_DEV_ADDR_W (0x27<<1)
uint8_t I2C_LCD_Data;

void LCDCommandMode(void)
{
	//1. cmd rs값을 0으로 출력
	I2C_LCD_Data &= ~(1<<LCD_RS);
}
void LCDDataMode(void)
{
	//cmd rs값을 1으로 출력
	I2C_LCD_Data |= (1<<LCD_RS);
}
void LCDWriteMode(void)
{
	//2. r/w pin값을 0(write)로 출력
	I2C_LCD_Data &= ~(1<<LCD_RW);
}
void LCDSendData(uint8_t data) //8bit mode data
{
	//3. 입력된 data 출력
	LCD_DATA_PORT = data;
}
void LCD_SendData4bit(uint8_t data)
{
	I2C_LCD_Data = (I2C_LCD_Data & 0x0f) | (data & 0xf0);
	LCDEnable();
	I2C_LCD_Data = (I2C_LCD_Data & 0x0f) | ((data & 0x0f)<<4);
	LCDEnable();
}

void LCD_BackLightOn(void)
{
	I2C_LCD_Data |= (1<<LCD_BACKLIGT);
	I2C_TxByte(LCD_DEV_ADDR_W, I2C_LCD_Data);
}
void LCD_BackLightOff(void)
{
	I2C_LCD_Data &= ~(1<<LCD_BACKLIGT);
	I2C_TxByte(LCD_DEV_ADDR_W, I2C_LCD_Data);
}

void LCDEnable(void)
{
	//4. enable pin을 0>1>0 으로 실행
	//LCD_ENABLE_PORT &= ~(1<<LCD_ENABLE);
	//LCD_ENABLE_PORT |= (1<<LCD_ENABLE);
	//LCD_ENABLE_PORT &= ~(1<<LCD_ENABLE);
	
	I2C_LCD_Data &= ~(1<<LCD_ENABLE);
	I2C_TxByte(LCD_DEV_ADDR_W, I2C_LCD_Data);
	I2C_LCD_Data |= (1<<LCD_ENABLE);
	I2C_TxByte(LCD_DEV_ADDR_W, I2C_LCD_Data);
	I2C_LCD_Data &= ~(1<<LCD_ENABLE);
	I2C_TxByte(LCD_DEV_ADDR_W, I2C_LCD_Data);
	
	//딜레이를 줘야 깨지지 않고 나옴
	_delay_us(1800);
}

void LCDWriteCommand(uint8_t cmdData)
{
	
	LCDCommandMode();
	LCDWriteMode();
	LCD_SendData4bit(cmdData);
	//LCDEnable();
}

void LCDWriteData(uint8_t charData)
{
	LCDDataMode();
	LCDWriteMode();
	LCD_SendData4bit(charData);
	//LCDEnable();
}

void LCDInit(void)
{
	//LCD_DATA_DDR =0xff;
	//LCD_RS_DDR |= (1<<LCD_RS);
	//LCD_RW_DDR |= (1<<LCD_RW);
	//LCD_ENABLE_DDR |= (1<<LCD_ENABLE);
	
	I2C_Init();
	
	_delay_ms(20);
	LCDWriteCommand(0x03); 
	_delay_ms(5);
	LCDWriteCommand(0x03); 
	_delay_ms(1);
	LCDWriteCommand(0x03); 
	LCDWriteCommand(0x02); 
	LCDWriteCommand(COMMAND_FUCTION_SET_4BIT); //4bit function set
	LCDWriteCommand(COMMAND_DISPLAY_OFF); //display off
	LCDWriteCommand(COMMAND_DISPLAY_CLEAR); //display clear
	LCDWriteCommand(COMMAND_ENTRY_MODE_SET); //entry mode set 0b00000110
	LCDWriteCommand(COMMAND_DISPLAY_ON);
	LCD_BackLightOn();
}

void LCDWriteString(char *string)
{
	for(uint8_t i=0;string[i];i++)
	{
		LCDWriteData(string[i]);
	}
}
void LCDGoToXY(uint8_t row, uint8_t col)
{
	col %= 16;
	row %= 2;
	
	uint8_t address = (0x40 * row) + col;
	uint8_t command =0x80 + address;
	LCDWriteCommand(command);
}
void LCDWriteStringXY(uint8_t row, uint8_t col, char *string)
{
	LCDGoToXY(row, col);
	LCDWriteString(string);
}

- I2C.c -

#include "I2C.h"

void I2C_Init(void)
{
	I2C_DDR |= (1<<I2C_SCL) | (1<<I2C_SDA);	//포트 출력으로 설정
	TWBR = 72;		//100khz 의미 (다른 곳에서 계산되있는 통신 속도를 사용)
	//TWBR = 32;	//200khz 의미
	//TWBR = 12;	//400khz 의미
}
void I2C_Start(void)
{
	TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);		//Send START condition
	while (!(TWCR & (1<<TWINT))) ;					//Wait for TWINT flag set.
													//This indicates that the START condition has been transmitted
}
void I2C_TxData(uint8_t data)
{
	TWDR = data;						//write bit = 0, SLA_W; SLA_W = slave dev 주소 +write, 1byte:dev주소+r/w  //lcd 주소
	TWCR = (1<<TWINT) | (1<<TWEN);		//Load SLA_W into TWDR Register.
										//Clear TWINT bit in TWCR to start transmission of address
	while (!(TWCR & (1<<TWINT))) ;		//Wait for TWINT flag set. This indicates that the
										//SLA+W has been transmitted, and ACK/NACK has been received.
}
void I2C_Stop(void)
{
	TWCR = (1<<TWINT)|(1<<TWEN)| (1<<TWSTO);		//Transmit STOP condition
}
void I2C_TxByte(uint8_t devAddr_RW, uint8_t data)
{
	/* I2C inteface를 이용한 1byte 전송 코드 */
	//1. start bit 전송
	I2C_Start();
	
	//2. data 전송 (dev address + r/w)
	I2C_TxData(devAddr_RW); //함수 사용, 반복되는 코드가 발생할시 함수 이용

	//3. 실제 데이터 전송
	I2C_TxData(data);
	
	//4. stop bit 전송, 통신 종료
	I2C_Stop();
}

 

 

<파일>

 

I2C_LCD.zip
0.06MB

'AVR' 카테고리의 다른 글

[AVR] UART 실험  (0) 2021.04.08