티스토리 뷰

당연한 이야기이지만 라즈베리에는 타이머 인터럽트가 존재하지 않는다.


물론 타이머 인터럽트를 복잡하게 짜는 건 여러가지 방법이 있으나 그 중


쉬운 예를 두가지 들어보겠다.


가장 쉬운건 다들 알겠지만 delay나 sleep함수를 쓰는것이다.



while(1)
{
	digitalWrite(LED1,1);
	digitalWrite(LED2,0);
	delay(1);
	digitalWrite(LED1,0);
	digitalWrite(LED2,1);
	delay(1);
}

간단하게 1ms동안 led를 켰다가 1ms동안 led를 켜면서 500Hz로 동작하는 코드이다.


이런 코드는 구현하기는 정말 간단하지만 제어주기가 정확하지 않다는 단점이 있다.


실제로 위코드는 led 한개를 켜고 끄는 시간이 2ms에 더해지게 된다.


이를 방지하기 위해서는 각 코드의 수행시간을 정확하게 알아야하는데 이또한 일정하지 않아서 어렵다.



위 코드를 실제 구동해보면 500Hz로 구동되어야 하지만 실제로는 400~450Hz에서 진동한다.


그러니 제대로 된 작업을 위해서는 절대 delay나 sleep을 이용하지 말자. 


제대로 된 타이머 구현을 위해서는 적어도 wiringPi를 까는게 좋다.


물론 안깔아도 되지만 까는쪽이 사용하기 편하다.


uint32_t rateTimer;
uint32_t now;
uint32_t controlPeriod=1000;//1ms

if(wiringPiSetup()==-1)
return 1;

rateTimer = now=micros();
while(1)
{
	digitalWrite(LED1,1);
	digitalWrite(LED2,0);
	while((now-rateTimer) < controlPeriod) 
           now=micros(); 
        digitalwrite(led1,0);
        digitalwrite(led2,1);
        while((now-rateTimer) <controlPeriod) 
           now=micros(); 
}

아주 단순한 몇가지 변수의 추가로 훨씬 정확한 타이머를 사용할 수 있다.


micros()는 wiringPiSetup()함수를 호출후 지난 시간을 microsec 단위로 반환해주는 함수이다.

(혹시 작업이 70분 이상 지속된다면 millis()를 쓰세요.)


while loop 들어가기 전에 카운터를 초기화하고


while loop 안에서는 rateTimer와 now의 차이가 controlPeriod만큼 날때까지 기다렸다가 다음 작업을 진행한다.




돌려보면 훨씬 정확한 타이밍(500Hz)으로 함수가 실행된다. 약간의 떨림이 존재하지만 1Hz 미만이다.


위 코드를 응용하면 카운터를 몇개 추가하여 하나의 루프안에서 다양한 수행 주기를 가지도록 할 수 있다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
글 보관함