안녕하세요. 오늘은 ATMEGA128 TWI READ를 해보겠습니다
READ를 알아보기전에 먼저 알아야 할게 있습니다. 어떤 모듈에게 데이터를 WRITE/READ를 하려면 먼저 그 모듈의 메모리주소에 접근해야하고 접근하려면 WRITE를 해야합니다. 그래서 WRITE를 하고 READ를 하면 데이터를 읽을 수 있습니다.
*READ하기
Read통신하는 순서가 있습니다.
순서를 크게보면 슬레이브 주소를 전송하고 슬레이브가 응답했으면 데이터를 Read하고 통신을 끝냅니다.
- 순서
0) WRITE과정하기(ATMEGA128 TWI(I2C)통신 알아보기 2편 참고)
1) START신호 전송
2) START신호 전송완료했나 확인
3) 슬레이브 주소 전송(7bit) + READ전송( Write : 0, Read : 1)
4) 슬레이브가 응답했는지 확인(ACK or NACK)
5) 슬레이브에게 응답하기(ACK or NACK)
6) 데이터 수신했는지 확인
7) 데이터 변수에 저장하기 (한번당 데이터를 1byte읽고 2byte를 읽으려면 5~7과정을 두번 하면 됩니다)
8) STOP신호 전송
unsigned char twi_read2(unsigned char add, unsigned char len)
{
int i=0;
memset(twi_recv,'\0',sizeof(twi_recv));
/* STEP1 START */
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
/* STEP2 Start check */
while(1)
{
if((TWCR & 0x80) && ((TWSR & 0xf8) == 0x08))
break;
}
/* STEP3 Address send */
TWDR = add<<1 | 0x01; // slave address, read
TWCR = (1<<TWINT)|(1<<TWEN);
/* STEP4 ACK Check */
while(1)
{
if((TWCR & 0x80) && ((TWSR & 0xf8) == 0x40))
break;
if((TWCR & 0x80) && ((TWSR & 0xf8) == 0x48))
return 0;
}
for(i=0; i<len; i++)
{
/* STEP5 send ACK or NACK*/
if((i+1)!=len)
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA); //ACK
else
TWCR = (1<<TWINT)|(1<<TWEN); //NACK
/* STEP6 Data receive Check */
while(1)
{
if((TWCR & 0x80) && ((TWSR & 0xf8) == 0x50))
break;
if((TWCR & 0x80) && ((TWSR & 0xf8) == 0x58))
break;
}
/* STEP7 Receive Data*/
twi_recv[i] = TWDR;
}
/* STEP8 STOP */
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
return 1;
}
int main(void)
{
sei();
usart0_init();
twi_init();
/* STEP 0 Write*/
twi_write(0x48,0x02);
_delay_us(100);
twi_read2(0x48,2);
USART0_char(twi_recv[0]);
USART0_char(twi_recv[1]);
while(1)
{
}
}
여기서 사용하는 모듈의 주소는 0x48이고 읽을 데이터는 0x02에 있고 데이터는 2바이트로 이뤄져 있습니다.
시리얼모니터와 파형모두 예상대로 나왔습니다.
*READ하기(RESTART)
Read할 때 Restart기능도 있습니다. Restart는 Write를 하고 STOP을 안하고 Restart를 해서 데이터를 읽으면 됩니다.
Restart의 장점은 통신을 할 때 STOP을 안 하므로 모듈이 여러 개 연결해서 사용 중일 때 제어권을 다른 모듈에게 안 뺏기게 됩니다.
- 순서
1) START신호 전송
2) START신호 전송완료했나 확인
3) 슬레이브 주소 전송(7bit) + WRITE전송( Write : 0, Read : 1)
4) 슬레이브가 응답했는지 확인(ACK or NACK)
5) 데이터 전송
6) 슬레이브가 응답했는지 확인(ACK or NACK)
7) Restart신호 전송
8) Restart 신호 전송완료했나 확인
9) 슬레이브 주소 전송(7bit) + READ전송( Write : 0, Read : 1)
10) 슬레이브가 응답했는지 확인(ACK or NACK)
11) 슬레이브에게 ack or nack 전송
12) 데이터 수신했는지 check
13) 데이터 변수에 저장
14) STOP신호 전송
unsigned char twi_read(unsigned char add, unsigned char dat1, unsigned char len)
{
int i=0;
memset(twi_recv,'\0',sizeof(twi_recv));
/* 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 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 REPEAT START */
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
/* STEP8 ReStart check */
while(1)
{
if((TWCR & 0x80) && ((TWSR & 0xf8) == 0x10))
break;
}
/* STEP9 Address send */
TWDR = add<<1 | 0x01; // slave address, read
TWCR = (1<<TWINT)|(1<<TWEN);
/* STEP10 ACK Check */
while(1)
{
if((TWCR & 0x80) && ((TWSR & 0xf8) == 0x40))
break;
if((TWCR & 0x80) && ((TWSR & 0xf8) == 0x48))
return 0;
}
for(i=0; i<len; i++)
{
/* STEP11 send ACK or NACK*/
if((i+1)!=len)
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA); //ACK
else
TWCR = (1<<TWINT)|(1<<TWEN); //NACK
/* STEP12 Data receive Check */
while(1)
{
if((TWCR & 0x80) && ((TWSR & 0xf8) == 0x50))
break;
if((TWCR & 0x80) && ((TWSR & 0xf8) == 0x58))
break;
}
/* STEP13 Receive Data*/
twi_recv[i] = TWDR;
}
/* STEP14 STOP */
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
return 1;
}
중간에 있는 Sr이 Restart입니다.
데이터 읽는 걸 보면 마지막 부분에는 NACK를 보내게 되어있습니다. 그 이유는 모듈에게 데이터를 그만 보내라는 의미입니다.
사용하는 모듈의 데이터시트를보면 아래의 그림이 있습니다
이러한 그림대로 파형을 만들어야 정상적으로 동작합니다.
예를들어 0x02번지는 데이터를 2개 읽을 수 있는데 1개만 읽고 STOP신호를 보내버리면 정상적으로 STOP이 안되는 증상이 있었습니다. 파형은 아래처럼 나옵니다. 아마 슬레이브는 데이터1개를 보내고 그 다음에 데이터를 또 보내려고 SDA를 LOW로 잡고있었던거같습니다.
감사합니다.
'아트메가 > 이론' 카테고리의 다른 글
ATMEGA128 SPI통신 알아보기 1편 (0) | 2023.02.05 |
---|---|
ATMEGA128 UART 수신인터럽트 발생하는 시점 (0) | 2023.01.08 |
ATMEGA128 TWI(I2C)통신 알아보기 2편 (2) | 2022.09.11 |
ATMEGA128 TWI(I2C)통신 알아보기 1편 (0) | 2022.09.10 |
아트메가128 타이머/카운터0 주파수 알아보기 (2) | 2017.10.01 |