도움이 되실지 모르겠습니다. I2C로 EEPROM의 내용을 R/W하는 예제입니다.


//=======================================

// MAIN PROJECT FILE

//=======================================

//

#include <avr/io.h>

#include <stdio.h>


#include <util/twi.h>


#include "eeprom24lc32.h"

#include "lcd.h"

#include "button.h"


int main()

{

long data, saved_data;

short rtn;

char string[80];


EprmInit(400); // 400 kHz TWI 전송속도

LcdInit();


data = 0x12345678;


if((rtn=EprmWriteNByte(0x500, (char *)&data, sizeof(data)))<0)

{

sprintf(string, "write error: %d", (int) rtn);

LcdMove(0,0); LcdPuts(string);


while(1);

}


// verify


if((rtn=EprmReadNByte(0x500, (char *)&saved_data, sizeof(saved_data)))<0)

{

sprintf(string, "write error: %d", (int) rtn);

LcdMove(0,0); LcdPuts(string);


while(1);

}

else

{

LcdMove(0,0); LcdPuts("Saved Data = ");


sprintf(string, "0x%lx", saved_data);

LcdMove(1,0); LcdPuts(string);

}


while(1);

}



//=======================================

// EEPROM24LC32.H

//=======================================

//


#ifndef __EEPROM24LC32_H__

#define __EEPROM24LC32_H__


void  EprmInit(unsigned int kHz);

short EprmWriteByte(short addr, char data);

short EprmWriteNByte(short addr, char data[], int n);

short EprmReadNByte(short addr, char data[], int n);


#endif


//=======================================

// EEPROM24LC32.C

//=======================================

//

//===========================================
// eerpom24lc32.c
//
// EEPROM 24LC32 구동 프로그램
//===========================================
//
#include <avr/io.h>
#include <util/twi.h>
#include <util/delay.h>

#include "lcd.h"

#include "eeprom24lc32.h"

#define DEVICE 0x00 // Device Select Bit
#define SLA_W (0xA0 | (DEVICE << 1))
#define SLA_R (0xA0 | (DEVICE << 1) | 0x01)

static short setAddr(short addr);

//====================================================
// TWI 버스를 초기화한다.
//====================================================
//
void EprmInit(unsigned int kHz)
{
TWSR = 1<<TWPS0; // 비트율 프리스케일러값을 16으로 한다.

// 비트율 설정
TWBR = (unsigned char) ((F_CPU/(kHz*1000L) - 16L)/(2L*4L));
}

//===================================================
// 1바이트 데이터를 24LC32A EEPROM에 쓴다.
//
// addr : 데이터를 쓸 EEPROM 주소
// 0x00 ~ 0xFFF
//  data : 쓸 데이터
//
// return :
// 0 - 성공
//   -1 - 쓰기 실패
//===================================================
//
short EprmWriteByte(short addr, char data)
{
short rtn;

//-----------------------------------
//  데이터를 쓸 EEPROM 주소를 보낸다.
//-----------------------------------
if((rtn=setAddr(addr)) < 0)
return rtn;

//-----------------------------------
// 데이터 전송
//-----------------------------------
TWDR = data;
TWCR = (1<<TWINT) | (1<<TWEN);

while(!(TWCR & (1<<TWINT))); // DATA가 보내질 때까지 기다린다.
if((TWSR & TW_STATUS_MASK) != TW_MT_DATA_ACK) // DATA 전송후 슬레이브로 부터 ACK를 받았는 지 검사
return -3;

//----------------------------------
// STOP 조건을 보낸다.
//----------------------------------
TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);
while((TWCR & (1<<TWSTO))); // STOP조건이 보내질 때까지 기다린다.

return 0;
}

//===================================================
// n 바이트 데이터를 EEPROM에 쓴다.
//
// addr : EEPROM 주소 
// 0x00 ~ 0xFFF
//  data : 쓸 데이터를 저장한 버퍼주소
//  n : 쓸 데이터 개수
//
// return :
// 양수 - 다음 쓸 EEPROM 주소
//   -1 - 쓰기 실패
//===================================================
//

short EprmWriteNByte(short addr, char *data, int n)
{
int i, rtn;

for(i=0; i<n; i++)
{
if((rtn=EprmWriteByte(addr, *data))<0)
return rtn;
addr++;
data++;
}

return addr;
}

//===================================================
// n 바이트 데이터를 EEPROM으로부터 읽어들인다.
//
// addr : EEPROM 주소 
// 0x00 ~ 0xFFF
//  data : 읽은 데이터를 저장할 버퍼
//  n : 읽을 데이터 개수
//
// return :
//    0 - 성공
//   -1 - 읽기 실패 
//===================================================
//
short EprmReadNByte(short addr, char data[], int n)
{
int i;

//----------------------------------------
// 읽을 데이터의 주소를 보낸다.
//----------------------------------------
if(setAddr(addr) < 0)
return -5;

//---------------------------------------
// REPEATED START
//---------------------------------------
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); // START 조건을 보낸다.
while(!(TWCR & (1<<TWINT))); // START조건이 보내질 때까지 기다린다.
if((TWSR & TW_STATUS_MASK) != TW_REP_START) // 정상적으로 REPEATED START조건이 보내졌는 지 검사한다.
return -6;


//--------------------------------------
// SLA_R를 보낸다.
//--------------------------------------
TWDR = SLA_R;
TWCR = (1<<TWINT) | (1<<TWEN);

while(!(TWCR & (1<<TWINT))); // SLA_R이 보내질 때까지 기다린다.
if((TWSR & TW_STATUS_MASK) != TW_MR_SLA_ACK) // SLA_R 전송후 슬레이브로 부터 ACK를 받았는 지 검사
return -7;

//----------------------
// 데이터 읽기
//----------------------
for(i=0; i<n-1; i++)
{
TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN); // TWI동작을 시작한다.  데이터를 받으면 ACK를 보낸다.
while(!(TWCR & (1<<TWINT))); // 데이터를 받을 때까지 기다린다.
if((TWSR & TW_STATUS_MASK) != TW_MR_DATA_ACK)
return -8;
data[i] = TWDR; // 데이터를 읽는다.
}

// 마지막 바이트를 받으면 ACK를 보내지 않는다.

TWCR = (1<<TWINT) | (1<<TWEN); // TWI동작을 시작한다. 데이터를 받으면 ACK를 보내지 않는다.
while(!(TWCR & (1<<TWINT))); // 데이터를 받을 때까지 기다린다.
if((TWSR & TW_STATUS_MASK) != TW_MR_DATA_NACK)
return -9;
data[i] = TWDR; // 마지막 데이터를 읽는다.

//-----------------------------
// STOP 조건을 보낸다.
//-----------------------------

TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);
while(TWCR & (1<<TWSTO)); // STOP조건이 보내질 때까지 기다란다.
return 0;
}


//=========================================-------===================
// eeprom에 데이터를 쓰기/읽기를 위한 제어 및 주소 바이트를 보낸다.
//
//  addr : 데이터를 쓰기/읽기를 할 주소
//
// return :
// 0   - 성공
//   음수 - 전송 실패
//===================================================================
//
static short setAddr(short addr)
{
while(1)
{
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); // START 조건을 보낸다.
while(!(TWCR & (1<<TWINT))); // START조건이 보내질 때까지 기다린다.
if((TWSR & TW_STATUS_MASK) != TW_START) // 정상적으로 START조건이 보내졌는 지 검사한다.
return -10;

TWDR = SLA_W;
TWCR = (1<<TWINT) | (1<<TWEN); // SLA_W를 보낸다.
while(!(TWCR & (1<<TWINT))); // SLA_W가 보내질 때까지 기다린다.

if((TWSR & TW_STATUS_MASK) == TW_MT_SLA_ACK)
break;
else // eeprom이 준비되지 않았음
{
TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN); // STOP 조건을 보낸다.
while(TWCR & (1<<TWSTO)); // STOP조건이 보내질 때까지 기다란다.
}
};

//--------------------------------------------------------
// eeprom 주소를 상위바이트, 하위바이트 순으로 보낸다.
//--------------------------------------------------------

TWDR = (unsigned char) (addr >> 8);
TWCR = (1<<TWINT) | (1<<TWEN); // 상위바이트 전송
while(!(TWCR & (1<<TWINT))); // DATA가 보내질 때까지 기다린다.

// DATA 전송후 슬레이브로 부터 ACK를 받았는 지 검사
if((TWSR & TW_STATUS_MASK) != TW_MT_DATA_ACK)
return -12;

TWDR = (unsigned char) addr; // 하위바이트 전송
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); // DATA가 보내질 때까지 기다린다.

// DATA 전송후 슬레이브로 부터 ACK를 받았는 지 검사
if((TWSR & TW_STATUS_MASK) != TW_MT_DATA_ACK)
return -13;

return 0;
}


+ Recent posts