아트메가/이론

ATMEGA128 TWI(I2C)통신 알아보기 2편

원원 2022. 9. 11. 12:11

안녕하세요. 오늘은 TWI통신의 Write에 대해 알아보겠습니다.

 

 

* 초기세팅하기

- 통신속도설정

일단 초기세팅으로 통신속도를 설정해줘야 합니다. 통신속도는 일반적으로 100kHz로 설정을 하고 10us입니다

위의 파형은 클럭 파형이고 100kHz로 설정한 모습입니다. 주기가 10us인것을 볼 수 있습니다.

속도를 구하는 공식인데 CPU Clock frequency는 16mHz이고 TWBR과 TWPS는 아트메가 레지스터입니다
TWBR = 0x48;, TWSR = 0x00;을 넣으면 100kHz가 나옵니다

 

- 풀업저항설정
SDA,SCL라인에 풀업저항을 연결해줘야 합니다.  데이터시트에 풀업저항권장 사양이 나와있는 경우도 있습니다. 일반적으로 10k옴을 연결합니다. 풀업저항에 따라서  파형의 기울기가 변합니다. 일반적으로 저항이 낮으면 파형의 기울기가 90도 가까이 나오고 저항이 높으면 파형이 눕는 모습으로 나옵니다.

풀업저항에 따라 기울기가 변하는것을 볼 수 있습니다. SDA,SCL에 저항을 연결해도되고 내부풀업저항을 사용해도 되는데 여기서는 내부풀업저항을 사용합니다.
SDA와 SCL가 PD0, PD1포트이므로 PORTD |=0x03;을 하면 됩니다.

 

- TWI 활성화

TWCR레지스터에보면 TWINT TWEN을 HIGH설정 해줘야 합니다.
TWINT는 TWI Interrupt Flag이고 TWI작업이 끝나면 HIGH가 됩니다. HIGH가 되면 SCL은 LOW로 유지하므로 TWI을 작업을 하기 전에 소프트웨어적으로 클리어를 해줘야 합니다. 그래서 초기화할때 HIGH설정을 합니다.
TWEN은 TWI Enable bit이고 TWI를 사용하려면 HIGH해줘야합니다.
TWCR = (1<<TWINT) | (1<<TWEN);

이제 위의 내용을 합쳐서 twi_init()함수를 만듭니다

void twi_init()
{
	PORTD |= 0x03; // SDA,SCL pull-up setting
	/* SCL 100kHz */
	TWBR = 0x48;
	TWSR = 0x00;
	
	TWCR = (1<<TWINT)|(1<<TWEN);
}

 

*WRITE하기

Write통신하는 순서가 있습니다.
순서를 크게보면 슬레이브 주소를 전송하고 슬레이브가 응답했으면 데이터를 Write하고 통신을 끝냅니다.


- 순서
1) START신호 전송
2) START신호 전송완료했나 확인
3) 슬레이브 주소 전송(7bit) +  WRITE전송( Write : 0, Read : 1)
4) 슬레이브가 응답했는지 확인(ACK or NACK)
5) 데이터 전송
6) 슬레이브가 응답했는지 확인(ACK or NACK)
7) STOP신호 전송

unsigned char twi_write(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 */
	USART0_char(TWSR);
	while(1)
	{
		if((TWCR & 0x80) && ((TWSR & 0xf8) ==0x18))
			break;
		if((TWCR & 0x80) && ((TWSR & 0xf8) == 0x20))
			return 0;
	}
	
	/* STEP5 Data 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;
	}

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

레지스터 설정하는건 데이터시트가 자세히 나와있으니 데이터시트보면 되고 레지스터외에 다른 부분을 설명하겠습니다.


1. While무한반복문을 돌려서 체크하는 이유?
While문을 계속 돌려서 예상된 값으로 변경되면 다음스텝으로 넘어갑니다. While문이 없다면 레지스터간에 딜레이가 없으므로 정상적으로 동작을 안합니다. 그래서 While문대신에 딜레이+if문으로해도 되긴합니다. 

 

2. STEP2에 NACK인경우 TWSR가 진짜로 0x20인가?
아래의 표에서 데이터주소를 전달했는데 NACK가 발생하면 0x20이라고 적혀있는데 슬레이브의 주소를 다른걸 전달하고TWSR를 찍어본경우 진짜 0x20이 나옵니다.

 

3.성공했을때 파형

 

4. 스텝마다 TWINT를 clear시켜주는데 clear안시켜주면 진짜 SCL이 Low로 Stretch 되는가?
TWINT를 clear 안시켜주는 부분에서 SCL이 LOW로 Stretch됩니다. 이 기능은 ATMEGA128뿐만아니라 다른 MCU에서도 비슷한 기능을 하는 변수가 있으니 잘 봐야합니다

 

다음에는 Read를 해보겠습니다.