Atmega128 EEPROM
Atmega128에는 4K Bytes의 EEPROM이 있다. 이 EEPROM을 사용하기 위해서 3개의 레지스터를 사용한다.
 EECR(Control Register)
EEPROM에 읽거나 쓰는 동작을 제어하는 레지스터

EERE(Read Enable) : EEAR에 지정된 주소의 1바이트를 읽어 EEDR에 저장
EEWE(Write Enable) : 쓰기 기능 동작, 시스템에 의한 클리어
EEMWE(Master Write Enable) : EEWE 동작 전 1 지정해야 함, 시스템에 의한 클리어
EERIE(Ready Interrupt Enable) : EEWE가 클리어 될 때 인터럽트 발생 여부 // SREG 비트도 활성화 되어 있어야 함

 EEDR(Data Register)
EEPROM에 쓰거나 읽을 데이터를 저장하는  레지스터


 EEAR(Address Register)
EEPROM 어느 번지에 쓸껀지를 지정하는 레지스터

EEPROM 용량이 4K byte 이므로 12비트를 사용한다.

읽기 // 쓰기 동작


 // EEPROM Read&Write 실습1
#include "port.h"
#include <avr/signal.h>
#include <avr/interrupt.h>

#define CPU_CLOCK    16000000  // CPU clock = 16Mhz
#define TICKS_PER_SEC  1000    // Ticks per sec = 1000
#define PRESCALER    64      // 클럭의 배수

volatile unsigned int g_elapsed_time;  // 시간 변수

// TCCR0 설 정
void setTCCR0(void)
{
  TCCR0 = (1 << CS02);
}

// TCNT0 초기화
void initTCNT0(void)
{
  TCNT0 = 256 - (CPU_CLOCK / TICKS_PER_SEC / PRESCALER);
}

// TIMSK 설정
void setTIMSK(void)
{
  TIMSK = (1 << TOIE0);
}

void sleep(unsigned int elapsed_time)
{
  g_elapsed_time = 0;

  while(g_elapsed_time < elapsed_time);
}

// TIMER0 오버플로우 함수
SIGNAL(SIG_OVERFLOW0)
{
  g_elapsed_time++;

  TCNT0 = 256 - (CPU_CLOCK / TICKS_PER_SEC / PRESCALER);
}

void eeprom_write(unsigned int uiAddress, unsigned char ucData)
{
  while(EECR & (1 << EEWE));  // 쓰기 작업 중 이면 대기

  EEAR = uiAddress;      // 쓸 주소값 입력
  EEDR = ucData;        // 쓸 데이 터 입력
  EECR |= (1 << EEMWE);    // EEWE 할 준비
  EECR |= (1 << EEWE);    // 쓰기 명령
  return;
}

unsigned char eeprom_read(unsigned int uiAddress)
{
  while(EECR & (1 << EEWE));  // 쓰기 작업 중 이면 대기

  EEAR = uiAddress;      // 읽을 주소값 입력
  EECR |= (1 << EERE);    // 읽기

  return EEDR;        // 데 이터 리턴
}

int main(void)
{
  char state = 0;
  unsigned char ch = 0;
  unsigned int i, j;

  DDRC = 0x00;  // 스위치 입력
  PORTC = 0xFF;

  DDRF = 0xFF;  // FND 출력
  PORTF = 0xFF;

  setTCCR0();
  initTCNT0();
  setTIMSK();
  sei();

  for(i = 0 ; ; i++)
  {
    ch = PINC;
    if(ch == 0xFE)  // 0번 스위치를 누르면
    {
      ch = 0;
      for(j = 0 ; j < 10 ; j++)
      {
        eeprom_write(j, ch++);
      }
      ch = 9;
      for(j = 0 ; j < 10 ; j++)
      {
        eeprom_write(10 + j, ch--);
      }
    }
    ch = eeprom_read(i);  // EEPROM 의 i 주소에 들어 있는 데이터를 읽어옴
    PORTF = ch;
    if(i == 19)
    {
      i = -1;
    }
    
    sleep(500);
  }
  return 0;
}
// EEPROM 0번지부터 19번지안에 숫자를 저장하고, 이를 읽어와서 FND에 보여주는 코드이다.

 // EEPROM Read&Write 실습2
#include "port.h"
#include <avr/signal.h>
#include <avr/interrupt.h>

#define CPU_CLOCK    16000000  // CPU clock = 16Mhz
#define TICKS_PER_SEC  1000    // Ticks per sec = 1000
#define PRESCALER    64      // 클럭의 배수

volatile unsigned int g_elapsed_time;  // 시간 변수

// TCCR0 설 정
void setTCCR0(void)
{
  TCCR0 = (1 << CS02);
}

// TCNT0 초기화
void initTCNT0(void)
{
  TCNT0 = 256 - (CPU_CLOCK / TICKS_PER_SEC / PRESCALER);
}

// TIMSK 설정
void setTIMSK(void)
{
  TIMSK = (1 << TOIE0);
}

void sleep(unsigned int elapsed_time)
{
  g_elapsed_time = 0;

  while(g_elapsed_time < elapsed_time);
}

// TIMER0 오버플로우 함수
SIGNAL(SIG_OVERFLOW0)
{
  g_elapsed_time++;

  TCNT0 = 256 - (CPU_CLOCK / TICKS_PER_SEC / PRESCALER);
}

void eeprom_write(unsigned int uiAddress, unsigned char ucData)
{
  while(EECR & (1 << EEWE));  // 쓰기 작업 중 이면 대기

  EEAR = uiAddress;      // 쓸 주소값 입력
  EEDR = ucData;        // 쓸 데이 터 입력
  EECR |= (1 << EEMWE);    // EEWE 할 준비
  EECR |= (1 << EEWE);    // 쓰기 명령
  return;
}

unsigned char eeprom_read(unsigned int uiAddress)
{
  while(EECR & (1 << EEWE));  // 쓰기 작업 중 이면 대기

  EEAR = uiAddress;      // 읽을 주소값 입력
  EECR |= (1 << EERE);    // 읽기

  return EEDR;        // 데 이터 리턴
}

int main(void)
{
  unsigned char ch = 0;
  unsigned char data = 0;

  DDRC = 0x00;  // 스위치 입력
  PORTC = 0xFF;

  DDRF = 0xFF;  // LED 출력
  PORTF = 0xFF;

  setTCCR0();
  initTCNT0();
  setTIMSK();
  sei();

  while(1)
  {
    data = eeprom_read(1);
    PORTF = data;

    if(0 == data)  // LED 모두가 ON이 면 
    {
      data = 0xFF;
      eeprom_write(1, data);
    }

    ch = PINC;
    ch = ~ch;
    if(ch)    // 키 가 눌러 졌으면
    {
      data ^= ch;    // toggle
      eeprom_write(1, data);
      sleep(500);
    }
  }

  return 0;
}
// 8개의 스위치와 LED를 매칭 시켜, 스위치를 누를 때마다 해당 LED가 Toggle 된다. 이때 LED ON 정보를 EEPROM에 저장해서 전원을 껐다 켜도 다시 그대로 복원된다.

   정적 멤버
정적 멤버는 모든 객체가 공유하는 멤버다. 지금까지 배워온 멤버 변수와 멤버 함수들은 객체마다 하나씩 존재했었고 객체는 저마다 자신의 멤버를 사용했다. 하지만 정적 멤버 변수와 정적 멤버 함수는 클래스에 오직 하나만 존재하기 때문에 모든 객체들은 하나의 정적 멤버를 같이 사용하게 된다. 정적 멤버는 기존에 사용하던 멤버 변수나 함수 앞에 static 키워드를 붙여서 만든다.

 // 정적 멤버를 사용한 객체 수 세기
#include <iostream>
#include <string>
using namespace std;

class Student
{
public:
  // 생 성자, 소멸자
  Student(const string& name_arg, int stdNumber);
  ~Student();

public:
  // 정 적 멤버들
  static int student_count;
  static void PrintStdCount();

private:
  string name;  // 이름
  int sNo;    // 학번
};

// 정 적 멤버 변수
int Student::student_count = 0;

// 정적 멤버 함수
void Student::PrintStdCount()
{
  cout << "Student 객체 수 = " << student_count << endl;
}

Student::Student(const string& name_arg, int stdNumber)
{
  // 학생 객체의 수를 증가시킨다.
  student_count++;

  name = name_arg;
  sNo = stdNumber;
}

Student::~Student()
{
  // 학생 객체의 수를 감소시킨다.
  student_count--;
}

void Func()
{
  // 객체 생성
  Student std1("Bill"342);
  Student std2("James"214);

  Student::PrintStdCount();
}

int main()
{
  Student::PrintStdCount();

  // 객체 생성
  Student std("Jeffrey"123);

  Student::PrintStdCount();

  // Func() 함수 호출
  Func();

  Student::PrintStdCount();

  return 0;
}


 // 위의 예제에서 클래스를 헤더 파일과 구현 파일로 나누어 보았다
 // Student.h
#ifndef STUDENT_H
#define STUDENT_H

#include <iostream>
#include <string>
using namespace std;

class Student
{
public:
  // 생 성자, 소멸자
  Student(const string& name_arg, int stdNumber);
  ~Student();

public:
  // 정 적 멤버들
  static int student_count;
  static void PrintStdCount();

private:
  string name;  // 이름
  int sNo;    // 학번
};

#endif

 // Student.cpp
#include "Student.h"

// 정적 멤버 변수
int Student::student_count = 0;

// 정적 멤버 함수
void Student::PrintStdCount()
{
  cout << "Student 객체 수 = " << student_count << endl;
}

Student::Student(const string& name_arg, int stdNumber)
{
  // 학생 객체의 수를 증가시킨다.
  student_count++;

  name = name_arg;
  sNo = stdNumber;
}

Student::~Student()
{
  // 학생 객체의 수를 감소시킨다.
  student_count--;
}

 // main.cpp
#include "Student.h"

void Func()
{
  // 객체 생성
  Student std1("Bill"342);
  Student std2("James"214);

  Student::PrintStdCount();
}

int main()
{
  Student::PrintStdCount();

  // 객체 생성
  Student std("Jeffrey"123);

  Student::PrintStdCount();

  // Func() 함수 호출
  Func();

  Student::PrintStdCount();

  return 0;
}

+ Recent posts