AT24xx IC의 READ 동작 방식은 3가지가 있습니다.
1. RANDOM BYTE READ
2. SEQUENTIAL READ
3. CURRENT ADDRESS READ
이 중, 테스트 결과 미리 말씀드릴 내용이 있는데,
3. Current Address Read 의 경우 Byte Write 와 Random Byte Read 를 실행한 다음에는 Current Address 값이 읽히는 것이 아니라 Current Address 위치의 데이터 값이 읽힙니다.
제가 잘 못한 것이 있는지 모르겠으나 여러번 테스트 해 봐도, 그렇네요.
Page Write 나 Sequential Read를 수행한 후에는 Address가 제대로 읽히네요.
또 1가지, Page의 마지막 1 바이트를 Random Byte Read로 읽은 후에는 Current Address Read가 제대로 동작합니다.
정리해보면 Current Address Read 명령은 다음과 같은 경우 동작한다.
1. Page Write 이후
2. Sequential Read 이후
3. Page의 마지막 데이터를 Random Byte Read한 이후
추가로 테스트해 본 결과, 전원 리셋 이후 AT24C04를 처음에 Current Address Read를 수행하면 0xFF 가 읽히고 그 다음에 계속 읽어 보아도 0xFF만 계속 읽히는 군요. 데이터가 읽히는 건지 current Address 가 계속 0xFF 고 자동으로 증가한다던 Address 가 증가를 안하는 건지 확인이 안되네요.
[1. RANDOM BYTE READ]
RANDOM BYTE READ 함수는 다음과 같이 정의했습니다.
uint8_t EEP_24C04_Read_Byte(uint32_t slaveAddress,uint8_t wordAddress)
{
uint8_t rtn_val;
I2C_1_I2CMasterWriteBuf(slaveAddress, &wordAddress, 1, I2C_1_I2C_MODE_COMPLETE_XFER );
for(;;)
{
if(0u != (I2C_1_I2CMasterStatus() & I2C_1_I2C_MSTAT_WR_CMPLT))
{
break;
}
}
I2C_1_I2CMasterReadBuf(slaveAddress, &rtn_val, 1, I2C_1_I2C_MODE_COMPLETE_XFER);
for(;;)
{
if(0u != (I2C_1_I2CMasterStatus() & I2C_1_I2C_MSTAT_RD_CMPLT))
{
break;
}
}
return rtn_val;
}
데이터시트를 보면 Device Address 와 Word Address 를 Dummy Write 하라고 했는데, 이 동작에서 Dummy 라는 말이 문제가 있습니다. Dummy 는 쓰레기 또는 아무 의미 없는 동작을 말하는데 테스트 결과, Dummy로 넣은 Word Address 에 의해 Word Address 에 해당하는 데이터가 출력됩니다. 이것은 Dummy 라는 표현이 옳지 않은 것 같습니다.
어쨓든 Device Address(/Write) + Word Address 를 Write한 후에 I2C_1_I2CMasterReadBuf() 함수로 데이터를 1개 읽으면 됩니다.
동작 테스트 예로써, 다음과 같은 코드를 실행해 봤습니다.
i=0;
i2c_buffer[i++] = EEP_24C04_Read_Byte(0x52,0x14);
Device Address : 0x52 , Word Address : 0x14 에 해당하는 데이터를 1개 읽는 동작입니다.
오실로스코프로 측정한 결과는 다음과 같습니다.
0x04가 읽혔네요. 이건 맞습니다. 이전에 제가 Word Address 0x10~0x1F 에 데이터 0x00~0x0F를 Write 했으니, Word Address 0x14 에 해당하는 데이터는 0x04 가 맞는 거죠.
UART로 뿌려 보니 0x04가 나오는 군요.
[2. SEQUENTIAL READ]
SEQUENTIAL READ 동작은 RANDOM BYTE READ 에서 1 BYTE만 읽던 것에 추가로 여러바이트를 읽으면 됩니다.
Device Address(/Write) + Word Address 를 Write한 후에 I2C_1_I2CMasterReadBuf() 함수로 데이터를 여러개 읽으면 됩니다.
동작시퀀스는 다음과 같습니다.
제가 만든 함수 원형은 다음과 같습니다.
void EEP_24C04_Read_Sequential(uint32_t slaveAddress,uint8_t wordAddress,uint8_t *RdData,uint32_t cnt)
{
I2C_1_I2CMasterWriteBuf(slaveAddress, &wordAddress, 1, I2C_1_I2C_MODE_COMPLETE_XFER );
for(;;)
{
if(0u != (I2C_1_I2CMasterStatus() & I2C_1_I2C_MSTAT_WR_CMPLT))
{
break;
}
}
I2C_1_I2CMasterReadBuf(slaveAddress, (uint8 *) RdData, cnt, I2C_1_I2C_MODE_COMPLETE_XFER);
for(;;)
{
if(0u != (I2C_1_I2CMasterStatus() & I2C_1_I2C_MSTAT_RD_CMPLT))
{
break;
}
}
}
테스트 동작 코드의 예는 다음과 같습니다.
EEP_24C04_Read_Sequential(0x52,0x10,i2c_buffer,16);
Device Address : 0x52 , Word Address : 0x10부터 16개의 데이터를 순차적으로 읽는 동작입니다.
오실로 스코프로 측정한 결과는 다음과 같습니다.
안보여서 확대해 본 그림은 다음과 같습니다.
앞부분만 분석해 본 결과 제대로 송/수신이 되고 있네요.
0x52(Device Address)+/Write+ACK ,
0x10(Word Address)+ACK,
0x52(Device Address)+Read+ACK ,
0x00+ACK , 0x01+ACK , 0x02+ACK~..
UART로 출력한 결과 다음과 같습니다.
제대로 읽혀졌음이 확인됐습니다.
[3. Current Address Read]
현재 어드레스를 읽는 동작으로 Random Byte Read에서 Write Code(Device address+Wordaddress) 를 뺀 것 과 같습니다.
함수 정의는 다음과 같습니다.
uint8_t EEP_24C04_Read_Address(uint32_t slaveAddress)
{
uint8_t rtn_val;
I2C_1_I2CMasterReadBuf(slaveAddress, &rtn_val, 1, I2C_1_I2C_MODE_COMPLETE_XFER);
for(;;)
{
if(0u != (I2C_1_I2CMasterStatus() & I2C_1_I2C_MSTAT_RD_CMPLT))
{
break;
}
}
return rtn_val;
}
맨 처음 문제를 제기한 것 처럼, Page Write 나 Sequential Read 일 때만 제대로 동작합니다. 다른 의미로는 페이지의 마지막 데이터를 Access한 다음에만 동작한다고도 할 수 있겠네요.
동작 시퀀스는 다음과 같습니다.
오실로 스코프로 측정한 결과 입니다.
Word Address 0x21이 읽히네요.
다음은 UART로 출력한 결과 입니다. UART에는 0x20 이 읽히는데, 위의 스코프 데이터와 관련없이 보십시요. 위의 파형은 Current Address Read만 1번 더 실행해서 측정하다 보니 Address 가 자동으로 +1 되어 0x21이 되어 버렸습니다.
자, 이것으로 I2C 기초 공부를 마치겠습니다. 혹시 Current Address Read 의 애매한 부분을 아시면 댓글 남겨 주시기 바랍니다. ^^
그리고 PSOC Creator 예제 파일추가 링크 입니다.
댓글 없음:
댓글 쓰기