BASIC4MCU | 질문게시판 | EEPROM 저장 관련 문의
페이지 정보
작성자 총체적난국 작성일2021-07-14 18:21 조회41,441회 댓글12건본문
전원이 꺼질 때 EEPROM 저장하는 것은 어렵다고 하셔서 일단 스위치를 눌러 값을 저장하는 것부터 해보려고 코드를 짜봤는데 전원을 껐다 키면 값이 저장이 안 되어 있습니다.
혹시 어떤 부분이 틀렸는지 보시고 조언 부탁 드립니다.
#include <avr/io.h>
#include <avr/delay.h>
#include <avr/interrupt.h>
char fnd[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsigned int buff4,buff3,buff2,buff1;
unsigned int i = 0;
unsigned char eeget(unsigned int addr);
unsigned int data;
unsigned int k = 0;
ISR(INT0_vect)
{
i++;
_delay_ms(1);
}
int main()
{
DDRC=0xff; // FND 출력
DDRD=0b11110000; // TN 출력(7~4), 카운터,리셋 입력(3,2)
GICR = 0b01000000;
MCUCR = 0x00;
SREG = 0x80;
i = eeget(0x40);
while(1)
{
display();
fnd_on_0();
save();
}
}
void display()
{
buff4 =i/1000;
buff3 =i%1000/100;
buff2 =i%100/10;
buff1 =i%10;
}
void fnd_on_0()
{
if(i>=1000){
PORTD=0x10; PORTC=fnd[buff4]; _delay_ms(1); PORTC=0xff;
PORTD=0x20; PORTC=fnd[buff3]; _delay_ms(1); PORTC=0xff;
PORTD=0x40; PORTC=fnd[buff2]; _delay_ms(1); PORTC=0xff;
PORTD=0x80; PORTC=fnd[buff1]; _delay_ms(1); PORTC=0xff;
}
else if(i>=100){
PORTD=0x20; PORTC=fnd[buff3]; _delay_us(1333); PORTC=0xff;
PORTD=0x40; PORTC=fnd[buff2]; _delay_us(1333); PORTC=0xff;
PORTD=0x80; PORTC=fnd[buff1]; _delay_us(1333); PORTC=0xff;
}
else if(i>=10){
PORTD=0x40; PORTC=fnd[buff2]; _delay_ms(2); PORTC=0xff;
PORTD=0x80; PORTC=fnd[buff1]; _delay_ms(2); PORTC=0xff;
}
else{
PORTD=0x80; PORTC=fnd[buff1]; _delay_ms(4); PORTC=0xff;
}
}
void save()
{
if(!(PIND & 0b00001000))
{
eeput(0x40,i);
_delay_ms(10);
}
}
void eeput(unsigned int addr, unsigned int data)
{
while(EECR & 0x02);
EEAR = addr;
EEDR = data;
EECR |= (1<<EEMWE);
EECR |= (1<<EEWE);
}
unsigned char eeget(unsigned int addr)
{
while(EECR & 0x02);
EEAR = addr;
EECR |= (1<<EERE);
return EEDR;
}
댓글 12
조회수 41,441master님의 댓글
master 작성일
eeprom 헤더파일 추가해서 함수를 사용하세요
https://studymake.tistory.com/304
코드비젼 경우에는 내부 SRAM 데이터 사용하는 것처럼 아주 편합니다.
총체적난국님의 댓글
총체적난국 작성일
EEPROM에 저장된 값을 FND에 표현하려면 추가적인 변환 과정(ex. 진수변환)이 필요한지 궁금해서 댓글 남깁니다.
FND에 표현되는 숫자는 10진수인데 EEPROM에 저장되어 있는 값은 10진수가 아니니 이 값을 변환하는 과정이 필요할 것으로 생각되는데 만약 필요하다면 어떤 과정을 거쳐야하는지 안내 부탁 드립니다.
master님의 댓글
master 작성일
char fnd_table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //캐소드
char fnd_table[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E}; //애노드
일반적으로 10진수를 사용하지만 16진수로도 표시 가능합니다.
master님의 댓글
master 작성일
2바이트 크기의 카운터 (0~9999)값을 10진수로 FND에 표시하는 예제는 어렵지 않게 찾을 수 있을겁니다.
n/1000; // 천의자리
n/100%10; // 백의자리
n/10%10; // 10의자리
n%10; // 1의자리
총체적난국님의 댓글
총체적난국 작성일eeprom에 저장되는 데이터의 형식이 16진수라는 의미신가요? eeprom에 저장한 i 값을 다시 fnd로 표시하기 위해 16진수 -> 10진수의 변환이 필요한지요..
master님의 댓글
master
eeprom이든 sram이든 flash든 메모리에 저장되는 것은 각각의 비트 값이 0,1이고
이 것을 2진으로 표현하든, 10진으로 표현하든, 16진으로 표현하는 것은 인간이 필요에 의해서 선택할 뿐입니다.
FND는 10진 또는 16진으로 표현(출력)할 수 있습니다.
저야 16진을 봐도 10진수 처럼 이해가 가지만, 본인이 16진수에 익숙하지 않다면 10진수를 사용하세요
총체적난국님의 댓글
총체적난국 작성일
답변 감사합니다. 하나만 더 여쭤볼게요.
제가 어디서 본 코드인데 어떠한 값 i에 예를 들어 hi = i % 0xff / lo = i / 0xff라는 두 수식을 넣은 것을 봤는데 이게 혹시 어떤 의미인지 알 수 있을까요? 0xff를 %와 / 처리한 것이 어떤 의민지 궁금합니다..
master님의 댓글
master
hi = i % 0xff / lo = i / 0xff
i는 unsigned int 형이고, hi,lo는 byte(or unsigned char) 형입니다.
high byte 와 low byte로 나누는 연산입니다.
총체적난국님의 댓글
총체적난국 작성일그리고 마스터님이 알려주신 eeprom 헤더파일을 이용하지 않고 io.h 헤더파일을 이용해 코드를 짜는 것도 가능하다고 해서 짜본 것인데 제가 올려드린 코드에 문제점이 있는지도 가능하시면 확인 부탁 드립니다.
master님의 댓글
master
헤더파일을 이용한 코드로 잘 동작하도록 작성한 후에
해당 코드를 분석해서 이해하고
그 후에 헤더파일 없이 작성하는 것이 순서입니다.
물론 이 과정에는 우선적으로 헤더파일을 분석해야겠죠
헤더파일 분석과정 없이 작성한 코드가 제대로 동작하는지 아닌지 체크 해달라고요?
무슨 의미가 있을까요?
(구지 의미를 찾아본다면 숙제를 대신 해달라는.. 그정도로 생각됩니다.)
총체적난국님의 댓글
총체적난국
eeprom.h 헤더파일을 적용해보려니 어떻게 변경해야하는지 잘 모르겠습니다..
void eeput(unsigned int addr, unsigned int data)를 eeprom.h의 void eeprom_write_byte (uint8_t *__p, uint8_t __value)로
unsigned char eeget(unsigned int addr)을 uint8_t eeprom_read_byte (const uint8_t *__p) __ATTR_PURE__로 어떻게 바꾸는지 알려주심 감사하겠습니다..
master님의 댓글
master 작성일
코드비전을 사용하면 헤더파일이 필요없이 정말로 간단하게 작성이 가능합니다.
AVR용 컴파일러는 몇가지가 많이 사용되는데
유일하게 코드비전만 임베디드용 컴파일러 입니다.(다른 컴파일러 들은 모두 PC용을 개조해서 AVR용으로 만든 정도)
여러가지 장점이 있죠