[AVR] 데이터 손실

2013. 12. 12. 12:26 from MCU/AVR

 요즘 ATmega128 책을 속독으로 보고 있는데 신기한 개념을 알게 되었다. ATmega128 이 데이터를 8 bit 로 처리하므로 인해서 발생하는 데이터 손실 문제이다. 다음과 같은 예제를 보자


unsigned short icount, temp;


while(1)

{

  icount = (unsigned short) (ts * CPU_CLOCK_KHZ  / PRESCALE);

  timer = 0xFFFF - icount + 1;


 timer = temp;

}


ISR (TIMER1_OVF_vect) // 타이머 1 오버플로 인터럽트 서비스루틴

{

  TCNT1 = timer;

}

<예제 1>


 원래 LED 를 주기적으로 패턴 이동시키면서 뭐 하는 예제인데 일부만 빼왔다. 위 과정을 보면 멀쩡하게 TCNT1 레지스트에 timer 값이 잘 들어갈 것 같지만! 함정이 있다. 


 CPU 가 연산하는 과정을 한번 뜯어보자. ATmega128 는 8 bit CPU 이므로 항상 1Byte 단위로 연산을 수행한다. 그러므로 temp 변수 0x1234 의 값이 timer 변수 0x5678 자리에 대입 될 때 


1. timer = temp     <==>     0x5634 = 0x1234  // 0x1234 중 34를 먼저 연산하고 아직 12 는 연산하지 못한 결과

2. timer = temp     <==>     0x1234 = 0x1234  // 0x1234 우 12까지 전부 연산한 결과

 <예제2>


 요렇게 두번의 과정을 거쳐서 대입된다. 그래서 <예제1>을 보면 인터럽트가 발생을 하는데 이 인터럽트가 <예제2> 의 과정을 다 마치고 실행 된다면 다행히도 TCNT1 에는 프로그래밍 한 사람이 원하는 0x1234 값이 들어가게 된다. (0x1234 는 temp 값이 timer 로 대입된 것) 하지만 인터럽트가 일정 시간이 되면 무작위로 발생하기 때문에 <예제2> 의 괴정 중간에 발생하게  될 수도 있다. 이렇게 된다면! TCNT1 값은 0x5634 가 대입 되게 된다.이런.. 그래서 제대로 원하는 값을 넣으려면 timer = temp 연산을 하는 중간에 인터럽트가 발생하지 않도록 해야한다. 다음 예제가 제대로 된 예제.


unsigned short icount, temp;


while(1)

{

  icount = (unsigned short) (ts * CPU_CLOCK_KHZ  / PRESCALE);

  timer = 0xFFFF - icount + 1;


  cli ();        // 전역 인터럽트 금지

  timer = temp;

  sei ();        // 전역 인터럽트 허용

}


ISR (TIMER1_OVF_vect) // 타이머 1 오버플로 인터럽트 서비스루틴

{

  TCNT1 = timer;

}


'MCU > AVR' 카테고리의 다른 글

펌웨어와 임베디드  (0) 2015.05.29
인터럽트 한개로 다수의 RC 서보 제어  (0) 2013.12.17
[AVR] 카운트 계산법. TCNTn  (0) 2013.12.12
Datasheet 레지스터 보는 방법  (0) 2013.12.03
[AVR] 인터럽트  (0) 2013.12.03
Posted by 나무길 :