AVR실습 외부 EEPROM쓰기
이전에 내부 EEPROM을 사용한 과제내용으로
TWI (l2C)직렬 통신을 이용한 외부 EEPROM을
사용하여 구동한 소스
<코드>
#include<avr/io.h>
#include<avr/signal.h>
#include<avr/interrupt.h>
#include<avr/eeprom.h>
#define CPU_CLOCK 16000000 //클럭
#define TICKS_PER_SEC 1000 //틱
#define PRESCALER 64 //프리스케일러
#define AT24C16_ADDR 0xA0 //외부EEPROM 디바이스주소
volatile unsigned int g_elapsed_time;
volatile unsigned int j=0;
void initLED(void);
void setTCCR0(void);
void initTCNT0(void);
void setTIMSK(void);
void sleep(unsigned int sec);
void toggleLED(char a,char b);
void eeprom_write(unsigned int uiAddress, unsigned char ucData);
unsigned char eeprom_read(unsigned int uiAddress);
SIGNAL(SIG_OVERFLOW0); // timer0의 오버플로우함수,매크로
volatile unsigned int tic_time; // 시간 변수
volatile unsigned int time=0;
int main(void)
{
DDRC = 0x00; // key
PORTC = 0xFF;
unsigned char ch=0;
initLED(); // LED초기화
setTCCR0(); // TCCR0 설정
initTCNT0(); // TCNT0 초기화
setTIMSK(); // TIMSK 설정
sei(); // 인터럽트 활성화
TWBR = 12;
TWSR = (0<<TWPS1)|(0<<TWPS0);
for(;;)
{
ch = ~PINC;
PORTF = eeprom_read(j);
if(ch!=0)
{
toggleLED(ch,PORTF);
eeprom_write(j,PORTF);
sleep(300);
}
}
return 1;
}
SIGNAL(SIG_OVERFLOW0) //시그날
{
g_elapsed_time++;
TCNT0 = 256 - (CPU_CLOCK / TICKS_PER_SEC / PRESCALER);
}
void sleep(unsigned int elapsed_time) //딜레이
{
g_elapsed_time=0;
while(elapsed_time>g_elapsed_time);
}
void toggleLED(char a,char b) //토글
{
PORTF = (a^b);
}
void initLED(void) // LED 초기화
{
DDRF=0xFF;
PORTF=0xFF;
}
void setTCCR0(void) //프리스케일러 값
{
TCCR0=(1<<CS02) | (0<<CS01) | (0<<CS00);
}
void initTCNT0(void) //타이머 초기화
{
TCNT0 = 256 - (CPU_CLOCK / TICKS_PER_SEC / 64);
}
void setTIMSK(void) // 인트럽트
{
TIMSK = (0 << OCIE0) | (1<<TOIE0);
}
void eeprom_write(unsigned int uiAddress, unsigned char ucData)
{
//시작 조건을 만들어준다.
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while(!(TWCR&(1<<TWINT)));
//슬레이브 디바이스 주소와 위치주소 상위 3비트를 포함하여전송
TWDR = AT24C16_ADDR|((uiAddress>>7)&0x000E);
TWCR = (1<<TWINT)|(1<<TWEN);
while(!(TWCR&(1<<TWINT)));
//AT24C16에 쓸 하위 8비트 주소를 전송한다.
TWDR = uiAddress&0x00FF;
TWCR = (1<<TWINT)|(1<<TWEN);
while(!(TWCR&(1<<TWINT)));
//슬레이브에 실제 데이터를 전송한다.
TWDR = ucData;
TWCR = (1<<TWINT)|(1<<TWEN);
while(!(TWCR&(1<<TWINT)));
//종료 조건을 만들어 준다.
TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN);
sleep(10);
}
unsigned char eeprom_read(unsigned int uiAddress)
{
//시작 조건을 만들어준다.
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while(!(TWCR&(1<<TWINT)));
//슬레이브 디바이스 주소와 위치주소 상위 3비트를 포함하여전송
TWDR = AT24C16_ADDR|((uiAddress>>7)&0x000E);
TWCR = (1<<TWINT)|(1<<TWEN);
while(!(TWCR&(1<<TWINT)));
//AT24C16에 읽을 위치의 하위 8비트 주소를 전송한다.
TWDR = uiAddress&0x00FF;
TWCR = (1<<TWINT)|(1<<TWEN);
while(!(TWCR&(1<<TWINT)));
//시작 조건을 만들어준다.
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while(!(TWCR&(1<<TWINT)));
//슬레이브 주소와 읽기 조건을 전송한다
TWDR = AT24C16_ADDR|((uiAddress>>7)&0x000E)|0x0001;
TWCR = (1<<TWINT)|(1<<TWEN);
while(!(TWCR&(1<<TWINT)));
//AT24C16으로 부터 데이터를 읽는다.
TWCR = (1<<TWINT)|(1<<TWEN);
while(!(TWCR&(1<<TWINT)));
//종료 조건을 만들어 준다.
TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN);
return TWDR;
}