atmega128 내부에 있는 I2C통신을 사용한 소스입니다. atmega128에서는 I2C통신을 TWI통신이라고 표기하고 있습니다.

명칭만 다르게 쓸 뿐이지 똑같은 통신입니다. 통신속도는 100Kbps,400Kbps,3.4Mbps 세가지가 있는데 128에서는 3.4Mbps는 지원하지 않습니다. 아래 소스는 송신 수신 함수입니다. 데이터쉬트를 보면 송수신 순서가 자세하게 나와있습니다. 데이터쉬트를 참조해서 아래 소스를 보면 이해가 빠를 것 같습니다. 일일이 전부 설명하기에는 어려움이 있어서 패스~~;;

통신속도=cpu주파수/(16+2*TWBR*4^TWPS)

//u08 <---unsigned char(0~255) 8bit

그리고 SDA,SCL핀에 풀업저항을 꼭 달아줍니다.

#include <avr/io.h>
#include "def_variable.h"

void I2C_init(void)
{
TWBR=0x0C; // 16MHz/(16+2*12*4^0)=400KHz
TWSR=0x00; //TWPS1=0,TWPS0=0
}

void I2C_write(u08 SLA, u08 addr, u08 data)
{
TWCR=0xA4; //start condition
while((TWSR&0xF8)!=0x08); //start complete

TWCR=0xA4; //start condition
while((TWSR&0xF8)!=0x08); //start complete

TWDR=SLA; //SLA+W
TWCR=0x84;
while((TWSR&0xF8)!=0x18); //SLA+W complete

TWDR=addr; //address
TWCR=0x84;
while((TWSR&0xF8)!=0x28); //address complete

TWDR=data; //data
TWCR=0x84;
while((TWSR&0xF8)!=0x28); //data complete

TWCR=0x94; //stop condition
}

u08 I2C_read(u08 SLA, u08 addr)
{
u08 temp;

TWCR=0xA4; //start condition
while((TWSR&0xF8)!=0x08); //start complete

TWCR=0xA4; //start condition
while((TWSR&0xF8)!=0x08); //start complete

TWDR=SLA; //SLA+W
TWCR=0x84;
while((TWSR&0xF8)!=0x18); //SLA+W complete

TWDR=addr; //address
TWCR=0x84;
while((TWSR&0xF8)!=0x28); //address complete

TWCR=0xA4; //start condition
while((TWSR&0xF8)!=0x10); //start complete

TWDR=SLA+0x01; //SLA+R
TWCR=0x84;
while((TWSR&0xF8)!=0x40); //SLA+R complete

TWCR=0x84;
while((TWSR&0xF8)!=0x58); //data complete
temp=TWDR;

TWCR=0x94; //stop condition

return temp;
}

아래 소스는 내부 레지스터를 사용하지 않고 I2C통신을 프로그램으로 구현한 소스입니다. 저도 퍼온건데 수정할게 없어서 거의 수정을 안한거라서 올리기가 좀 그런데 일단 올리겠습니다. 근데 프로그램으로 구현한 I2C는 통신속도 계산을 못해서 속도가 어떻게 되는지를 모르겠습니다. 일단 128내부에 있는 TWI통신보다는 확실히 느립니다.



위 그림을 보면서 소스를 보면 이해가 빠를 것 같네요

#include <avr/io.h>
#include "def_variable.h"
#include "I2C_GPIO.h"
#include "USART.h"

void I2C_init(void) //I2C초기화 함수
{
DDRD |= 0x03; // Set SCL, SDA to output
PORTD |= 0x03; // Set SCL, SDA High
}

void I2C_start(void) //I2C 시작함수
{
DDRD |= 0x02; //SDA to output
PORTD = 0x03; //Set SCL, SDA High

PORTD &=0xFD; //SDA Clear
PORTD &=0xFE; //SCL Clear
}

void I2C_stop(void) //I2C 정지함수
{
DDRD |= 0x02; //SDA to output

PORTD &=0xFD; //SDA Clear
PORTD &=0xFE; //SCL Clear

PORTD |=0x01; //Set SCL Hight
PORTD |=0x02; //Set SDA Hight
}

void I2C_CLK(void) //I2C 클럭 함수
{
PORTD |=0x01; //Set SCL Hight
PORTD &=0xFE; //SCL Clear
}

u08 I2C_ACK(void)
{
u08 ack=0;
PORTD &= 0xFE; // SCL Clear
DDRD &= 0xFD; //SDA to input
PORTD |= 0x01; //Set SCL Hight

if((PIND & 0x02)==0x02) ack |= 1;
else ack=0;

PORTD &= 0xFE; //SCL Clear
DDRD |= 0x02; //SDA to output
PORTD &=0xFD; //SDA Clear
return ack;
}
void I2C_write(u08 data)
{
u08 i;
DDRD |= 0x02; //SDA to output
PORTD &= 0xFE; //SCL Clear

for(i=0;i<8;i++)
{
if((data & 0x80)==0x80) PORTD |= 0x02; //Set SDA Hight
else PORTD &= 0xFD; //SDA Clear

PORTD |= 0x01; //Set SCL Hight
data<<=1;
PORTD &= 0xFE; //SCL Clear
}
PORTD &= 0xFD; //SDA Clear
if(I2C_ACK()==1) TX0_string("error");
}

u08 I2C_read(void)
{
u08 i,temp=0;
DDRD &= 0xFD; //SDA to input

for(i=0;i<8;i++)
{
PORTD |= 0x01; //Set SCL Hight
if((PIND & 0x02)==0x02) temp |= 1; //input Hight
if(i<7) temp<<=1;
PORTD &= 0xFE; //SCL Clear
}
if(I2C_ACK()==1); //read에서는 ack 신호가 없다(ack=1)
else TX0_string("error");

DDRD |= 0x02; //SDA to output
PORTD &= 0xFD; //SDA Clear
return temp;
}

'OpenSTUDY > AVR' 카테고리의 다른 글

ESD110V2  (0) 2011.11.23
printf 사용  (0) 2011.10.27
SPI  (0) 2011.10.15
I2C  (0) 2011.10.15
UART  (0) 2011.10.15

+ Recent posts