디시인사이드 갤러리

갤러리 이슈박스, 최근방문 갤러리

갤러리 본문 영역

유리한과 함께하는 AVR로 임베디드 개념쌔우기 - #5. 무식한 Delay 똑똑한 Delay

유리한갤로그로 이동합니다. 2007.06.28 17:14:36
조회 3871 추천 1 댓글 17












Chapter 5. 무식한 Delay 똑똑한 Delay


부제 : Timer/Counter


/*


하나 짚고 넘어갈께.
횽이 대충 typedef로 만들어서 쓰는 데이터형은
u08 , u16 이야. unsigned char 랑 unsigned int.
8비트 프로세서라 int형은 2바이트.


임베디드하면서 코딩할때 가장 중요한건 비트연산일지도 몰라.
~,|,&,^ 등등..
오래 하다보면 16진수가 2진수로 변환되서 느껴질 날이 올꺼야..


근데 이게 또 전날 술퍼마셨거나 잠을 못자면 코드가 눈에 안들어올때가 있어요,
그니까 특히나 비트 만지작거리는 것들은 주석이라도 잘 달아놓자.


그리고 이건 임베디드 개념잡기 위한 용도지,
avr을 심도있게 배우라고 시작한 글은 아니니까
\'애새끼 ㅈㄹ 대충하네\' 라고 생각해도 할말 없다.
그래도 개념잡으면 하루 두어시간씩 일주일이면 avr 기능 익히는덴 떡을 친다.
익숙해지는게 문제겠지만.

*/



128은 나름대로 16MHz에 16MIPS로 동작해.
16MHz라면 느리다고 생각할지도 모르겠지만
거기에 그래픽작업이 있는것도 아니고 부동소숫점 연산같은 빡센 프로그램을
올리는일은 별로 없으니까 응답속도가 엄청나게 빨라.
(TFT-LCD 같은것들은 훡유.. 버벅버벅 빌빌빌빌...)


근데 생각을 해보자.
시계를 만든다고 했을때 1초에 한번씩 초가 가야되는데.. 이 1초를 어떻게 만드나?


일단 delay 함수를 만들어보자.


void delay(volatile u16 dt)
{
    u16 i=2727;
    while(--dt)
    {
        i=2727;
        while(--i);
    }
}


아무 의미없는 시간죽이는 함수 되시겠다.

/*
volatile 키워드에 대해서 짚고 넘어가자.
volatile 의 뜻은 \'휘발성의\' 라는뜻인데..
램 영역에 변수를 올리겠다는 뜻이야.
레지스터 영역에 올리는게 아니라..
복잡하게 생각하지는 말고, 그냥 최적화 시키지 말란말이야.
현재 영역에서 뿐만 아니라 다른쪽에서 변경될수도 있으니 손대지 말란뜻.
최적화때문에 정상동작을 보장하지 못하는 경우가 생기거든.


레지스터에 올라가서 엄청난 속도로 연산을 끝내버릴수도 있는거고..
타이밍 맞춰줘야되는데 연산이 빨리끝나면 절대로 안되지..
(램과 레지스터의 속도차는 수십~수백배까지 난다고 하더군.)


이런경우도 있을수 있지.


int* pABCD=(int *)0xABCD;
while(!*pABCD);


이런경우에는 무조건 참이거나 무조건 기짓이 되서 무한루프를 돌게 되.
이미 0xABCD의 값을 읽어왔다고 판단해서 그 밑의코드를 지 멋대로 최적화시키는거지.


이런 황당한 경우를 막기위해 volatile 키워드를 쓰는것이야..
*/


예전에 누군가 얘기했었는데 2727로 하면 1ms에 가깝게 나온다고 하더군.
자기가 오실로스코프로 찍어봤다고..


근데 컴파일러랑 최적화 따라 시간이 다르더라.


뭐 저 딜레이 함수가 가장 원초적인 딜레이 함수야. 만들기도 어렵지 않고..


하지만 정확한 딜레이를 줄수 없으니 어떻게 해야할까?


바로 AVR에 기능중 하나인 Timer/Count룰 이용하는거야.
128에는 총 4개의 타이머가 있는데 8비트가 2개 16비트가 두개.
간단히 16비트 카운터는 숫자를 65535까지 셀수 있고 8비트는255까지 셀수 있는 놈이야.


(개념잡기 형태의 강좌니까 카운터 0만 쓰기로 하고 인터럽트는 오버플로우 인터럽트만 쓰자고.)
(스스로 데이터시트 찾아보고 삽질해야 느는것이야. 절대 귀찮아서 그러는게 아마 아닐꺼야. )


일단 소스코드 나가신다.


#include <avr/io.h>
#include <avr/interrupt.h>
#include "typedef.h"


volatile u16 Count = 0;
BOOL Wait = FALSE;

void Init_Timer0(void);
void delay_ms(u16 dt);

int main(void)
{
    cli();          //인터럽트 비활성화
    DDRD=0xff;
    Init_Timer0();
    TIMSK=0x01;     //Timer0 overflow 인터럽트.
    sei();          //인터럽트 활성화
    PORTD=0x55;     // 0b 0101 0101
    while(1)
    {
        delay_ms(500);
        PORTD=~PORTD;   //비트 반전.
    }


    return 0;
}



void Init_Timer0(void)
{
    TCCR0 = 0x05;       //프리스케일러 128
    TCNT0 = 0x83;
}


void delay_ms(u16 dt)
{
    Wait=TRUE;
    Count=dt;
    while(Count);
    Wait=FALSE;
}


ISR(TIMER0_OVF_vect) //인터럽트 서비스 루틴. TIMER0가 오버플로되면 호출
{
    TCNT0 = 0x83;    // 초기화
    if(Wait)Count--;
}


코드가 조금 길어지기 시작한다.


횽이 지금 테스트할게 없는 관계로다가 스튜디오에서 시뮬 돌렸다.
이쁘게 잘 동작하긴하네.. 빌어먹을 타이머가 시뮬에선 너무 느리게 돈다는게 문제지만..
간단하게 LED가 01010101에서 10101010으로 0.5초에 한번씩 뒤집히는 코드야.



d0052452_04065113.jpg


자. 일단 뒤져봐야할 코드는 몇줄 안되지?


cli() , sei() 라는 함수 두개와
TCNT0,TCCR0,TIMSK 레지스터 세개.
ISR(TIMER0_OVF_vect) 세가지.


cli()는 모든 인터럽트를 비활성화 시켜. 클리어인터럽트..쯤 될까?
sei()는 반대로 설정된 인터럽트들을 다시 활성화 시키고. 셋 인에이블 인터럽트?
일종의 크리티컬 섹션이지.
초기화라던지 시스템에 영향을 줄수있는 설정을 할때는 뻑나지 않도록 감싸주는 역할을 해.


자, 이제 사용된 레지스터를 보자.


d0052452_04065319.jpg 


TCCR0는 뭐하는 놈이냐?
타이머/카운터 컨트롤 레지스터 되시겠다.
데이터 시트를 보니 눈이 어지럽군화..
스샷찍기엔 좀 양이 많이서 우리가 쓴 부분만 간추려보자.


d0052452_04065354.jpg 

bit 0~2까지 세개는 클럭 셀렉트 란다.
우리는 0x05을 했으니 0000 0101 이지? 자 그럼 101을 찾아보자.
Clktos/128 from 프리스케일러라고 되어있다.


프리스케일러는 뭘까?
흔히 우리는 분주비..라고 한다.
원래 타이머는 클럭한번에 값이 1씩 많아지는게 정상이다.
근데 시간을 길게 잡으려고 했더니 이건뭐 얼마 되지도 않거덩.
그래서 만든게 프리스케일러야.
분주비를 128로 했으니 클럭이 128번 뛰어야 타이머를 올리라는거지.
16MHz를 기준으로 했을때 1초에 16,000,000번 클럭이 들어가잖아?
하지만 분주비를 128로 했기때문에(클럭/분주비) 타이머는 1초에 125000번 뛰어.
그냥 클럭을 나누는놈이지.
윗쪽 5개 비트도 뭔가를 설정하는데.. 개인적으로 공부해라.
(클럭소스는 외부에서 끌어다가 쓸수도 있어. 그런놈은 타이머보다는 카운터 라고 부르지.)


d0052452_04065494.jpg

TCNT0를 보자.
타이머/카운터 레지스터 라고 되어있다.
별거없다.
클럭이 뛰면 값이 1 올라간다.
근데 왜 TCNT0를 0x83으로 했을까?


우리는 분명 정확한 1ms를 만들자고 했다.
말했다시피 프리스케일러 128로 잡은 지금,
1초에 TCNT0는 125000번 갱신된다.
여기까지만 기억하고 잠깐 밑으로 내려가자.



d0052452_04065165.jpg

TIMSK 를 보자. 타이머 인터럽트 마스크 레지스터라고 되어있다.
Init_Timer0함수에 포함시키지 않은 이유는..
다른 체널의 카운터에도 영향을 미치기 때문인데..
read도 가능하니까 포함시켜서 TIMSK|=0x01 라고해도 무방하다.
쓰는사람 마음.
우리는 오버플로우 인터럽트를 쓸거니까 타이머0의 오버플로인터럽트를 활성화 시킨다.


그럼 이제 오버플로우 인터럽트가 뭔지만 알면 되겠네?


TCNT0의 값이 0xff를 넘어 캐리(자리올림)가 발생하는순간 (오버플로우 되는순간)에 인터럽트가 발생한다.
그게 오버플로우 인터럽트다.


그래서 TCNT0를 0x83으로 해놓으면 00으로 넘어갈때까지 125번을 뛰는거다.
1초애 125,000번 분주했으니 125번이면 정확히 0.001초 라는 계산이 나온다. ㅇㅋ?


계산식을 말해줄께.


x = 메인클럭 * 1/분주비 * T
TCNT = 2^8(256) - x



그럼 직접 계산해보자.


16,000,000 * 1/128 * 0.001s = 125
256-125=131
131=0x83


다들 TCNT 계산법은 알겠지?
16비트 타이머는 0xffff까지 되는데
TCNT1H / TCNT1L 로 나눠서 할수도 있고
TCNT1 로 바로 대입시킬수도 있어.


자, 다시 본론으로 들어가서 인터럽트가 발생하면 인터럽트 서비스 루틴으로 점프~ 를 한다.


WinAVR에서는 ISR(TIMER0_OVF_vect) 로 점프~!


d0052452_04065248.jpg

친절하게도 WinAVR 레퍼런스를 보면 avr/interrupt.h 부분에 나와있다.
(winavr/doc/avr-libc/ 에 들어있다.)


저 함수를 처리하면 인터럽트가 발생하기전 루틴으로 복귀한다.


근데 TCNT0는 인터럽트가 발생했다고 해서 초기값으로 돌아가는게 아니라 0x00부터 다시 시작한다.


그래서 TCNT0를 초기값으로 돌려놓아야 할 필요가 있다.


 


명심해야 할 점은..


ISR쪽에 코드를 왕창 몰아넣으면
다 해치우기도 전에 인터럽트가 걸려서 중첩될수도 있다.
단발성이면 별 문제없이 해결될수도 있겠지만
영영 메인으로 돌아기지 못하는 개같은 경우가 생길수도 있으니 주의하자.


보통은 stack overflow 나서 칩이 견디다 못해 리셋되더라..


최소한의 코드만 박아넣고 메인에서 처리하자. ㅇㅋ?
(이벤트 플래그 확인해주는 역할로 쓴다던지..)

그리고 처리시간 염두해두고 코딩해.
인터럽트는 잘만 쓰면 OS없이도 멀티테스킹 효과를 가져올수 있는거다.
슈퍼루프+인터럽트로 즐거운 코딩생활하자.




오늘은 여기까지.



(추가하자면 기본라이브러리에 delay함수가 존재한다.
#include<util/delay.h>
를 추가하면된다.
_delay_ms()와 _delay_us() 를 사용하면된다.
근데 이놈도 정확한것 같진 않아..
딜레이를 인라인 어셈으로 만드는 사람도 있어.
의미없는 push pop..

void delay_us(unsigned char time_us)    // Time delay for 1us (1MHz)
{          
    register unsigned char i;

    for(i=0; i<time_us; i++)            // 4 cycle +
    {
        asm volatile(" PUSH R0 ");      // 2 cycle +
        asm volatile(" POP R0 ");       // 2 cycle +
        asm volatile(" PUSH R0 ");      // 2 cycle +
        asm volatile(" POP R0 ");       // 2 cycle +
        asm volatile(" PUSH R0 ");      // 2 cycle +
        asm volatile(" POP R0 ");       // 2 cycle = 16cycle = 1us
    }                                   // for 16MHz
}

)


 


d0052452_0406527.jpg

avr32 주문한거 취소됐네..
아.. 몇달동안 배고프게 살뻔했네.. 
근데 왜 취소됐는지 모르겠다..ㅡㅡ;;
근데 1달러는 왜 결제된걸까?

모르겠다~ 퇴근하고 avr 키트도 받을겸 친구랑 사우나 가야겠다.
그럼 다들 수고!!


자꾸 관심 안주면 싼다.

추천 비추천

1

고정닉 0

0

댓글 영역

전체 댓글 0
본문 보기

하단 갤러리 리스트 영역

왼쪽 컨텐츠 영역

갤러리 리스트 영역

갤러리 리스트
번호 제목 글쓴이 작성일 조회 추천
설문 우리나라를 대표해서 UN 연설자로 내보내고 싶은 스타는? 운영자 25/09/29 - -
AD 프로게이머가 될테야!! 운영자 25/10/01 - -
공지 프로그래밍 갤러리 이용 안내 [96] 운영자 20.09.28 47606 65
2893720 [이스트소프트] AI 교육받고 제주 자연 속 워케이션 즐기자! [1] [ESTsoft]oreumi-camp(125.183) 10:39 15 0
2893719 뭔지랄을해야 이딴나라에서 태어날수있는거지 [1] 타이밍뒷.통수한방(1.213) 10:35 9 0
2893718 ❤✨☀⭐⚡☘⛩나님 시작합니당⛩☘⚡⭐☀✨❤ ♥냥덩이♥갤로그로 이동합니다. 10:09 11 0
2893717 ❤✨☀⭐⚡☘⛩나님 시작합니당⛩☘⚡⭐☀✨❤ ♥냥덩이♥갤로그로 이동합니다. 09:33 13 0
2893716 수..숨막혀..ㅇㅅㅇ 헤르 미온느갤로그로 이동합니다. 09:31 15 0
2893714 태연 ㅇㅅㅇ 헤르 미온느갤로그로 이동합니다. 09:26 13 0
2893713 하루 한 번 헤르미온느 찬양 헤르 미온느갤로그로 이동합니다. 09:25 15 0
2893712 의정부역 PC방 ㅇㅇ(223.38) 08:40 11 0
2893711 앱공장 해볼만함? 프갤러(180.231) 08:12 18 0
2893692 넥도리아 양념 헌돈 돼지 갈비 추석을 향해 전진. 넥도리아2025(220.74) 06:22 16 0
2893675 음기 충전 발명도둑잡기(118.216) 05:13 34 0
2893673 조심해라 [1] 프갤러(211.118) 04:44 36 0
2893671 스포티파이 개인정보 국방부로 팔려나가는 건 시간문제 발명도둑잡기(118.216) 04:16 18 0
2893666 이 패션 진짜 올 가을 유행인가요? 발명도둑잡기(118.235) 04:01 19 0
2893665 스포티파이 인공지능 규제 발표 [1] 발명도둑잡기(118.235) 03:56 25 0
2893663 “엡스타인, 정보기관과 연관됐나” 의혹 여전… 美 정부는 침묵 발명도둑잡기(118.235) 03:36 15 0
2893655 흐름 상징 발명도둑잡기(118.235) 02:54 26 0
2893649 한국 국회, 정부, 법원은 여전히 미군위안부같은 정치를 하고 있다 발명도둑잡기(118.216) 02:42 16 0
2893644 사실 세대론으로 비판하면 안되고 생산수단 가진자를 비판해야 발명도둑잡기(118.235) 01:57 23 0
2893642 오늘의 소설, 영화 실마리: 성매매자 데이터베이스가 외국 정보기관에 발명도둑잡기(118.235) 01:52 15 0
2893641 엠스타인 명단 공개 예정인 의원 발명도둑잡기(118.235) 01:38 19 0
2893639 형님들 스타트업은 원래 조용한가요? [4] ㅇㅇ(106.101) 01:16 68 0
2893638 이직 하고 싶은데 물경력이라 방법이 없다.. ㅇㅇ(175.197) 01:16 34 0
2893637 BTS (방탄소년단) 'Dynamite' 발명도둑잡기(118.216) 01:07 20 0
2893636 먹고 살려고 안해본 일이 없는데, IT 프리랜서 장점은 [1] ㅆㅇㅆ(124.216) 01:06 52 0
2893635 내가 느끼는게 랜딩 페이지 하나 작성에 15만 ㅆㅇㅆ찡갤로그로 이동합니다. 00:59 37 0
2893634 프리로 협업 몇번해봤는데 항상 느끼지만 ㅆㅇㅆ찡갤로그로 이동합니다. 00:56 41 0
2893632 어차피 개발하다보면 서로 지식의 빈곳이 있을수밖에 없어서 [3] ㅆㅇㅆ찡갤로그로 이동합니다. 00:48 58 0
2893631 신해철, 싸이-Dear America [1] 발명도둑잡기(118.216) 00:38 31 0
2893629 우리나라가 소프트웨어 강국이 되려면 ㅇㅇ(121.168) 00:30 28 0
2893628 한국 10년뒤엔 러스트충들 국비찍어될듯 타이밍뒷.통수한방(1.213) 00:29 44 0
2893627 일하면 그냥 현타 존나옴 [25] ㅇㅇ갤로그로 이동합니다. 00:24 118 0
2893626 오늘의 작사 실마리: 관세전쟁 [3] 발명도둑잡기(118.216) 00:24 28 0
2893625 진짜 돈 모아서 C드라이브랑 메인보드 교체해야할듯 [2] ㅆㅇㅆ(124.216) 00:20 40 0
2893624 이거 교정 방법 잘못 고른건가? 발명도둑잡기(118.216) 00:18 22 0
2893622 후 아뮤튼 러스트 배워두십시오. 지능이 향상됩니다. [1] 프갤러(110.8) 00:12 38 0
2893620 밀레니얼로서 난 X세대보다 더 행복한 유년기에 꿀빨았다고 생각해 ㅇㅇ(121.168) 00:12 25 0
2893619 간식을 먹는데 입 안에 자꾸 찔려서 눈물이 저절로 난다 발명도둑잡기(118.216) 00:10 20 0
2893618 문화생활 깊이있게 하려면 무조건 일본에 의지 할 수 밖에 없음 [2] ♥냥덩이♥갤로그로 이동합니다. 00:10 60 0
2893616 sm은 원래 현업보다 it팀이 더 업무 프로세스를 잘 앎? [1] 프갤러(182.230) 00:02 37 0
2893615 서울에서 자란 친구들은 공부 못하면 부모가 ADHD의심해? ㅇㅇ(121.168) 00:01 24 0
2893614 이 시절 그리우면 개추 [3] ♥냥덩이♥갤로그로 이동합니다. 00:00 45 1
2893613 야야야야양야 진짜 발견. 계란국에 페퍼론치노 넣으니까 더 맛있음 ㅇㅇ(223.39) 10.02 20 0
2893612 성매매 국내 최고 DB 다크웹에 나와서 각국 정보기관이 샀을 것 발명도둑잡기(118.216) 10.02 33 0
2893611 나 금 산 거 며칠 전에 드디어 100% 넘었다 발명도둑잡기(118.216) 10.02 24 0
2893610 프갤에 모모와 김희철의 사랑 소설 써볼까 발명도둑잡기(118.216) 10.02 26 0
2893609 낼 봐야징 ♥냥덩이♥갤로그로 이동합니다. 10.02 17 0
2893608 ㅆㅇㅆ새끼 뭣좀 해볼려고 우울증갤러리,업소 프갤러(210.217) 10.02 40 3
2893607 최근에 있던 회사에서 얻은 교훈은 ㅇㅇ(121.168) 10.02 25 0
뉴스 방송인 김나영, 가수 마이큐와 재혼…"가족이 되기로 했다" 디시트렌드 10.02
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

뉴스

디시미디어

디시이슈

1/2