8051/PIC > 인터럽트 사용 LED 켜기

TODAY847 TOTAL605,476
사이트 이용안내
Login▼/회원가입
최신글보기 질문게시판 기술자료 동영상강좌

아두이노 센서 ATMEGA128 PWM LED 초음파 AVR 블루투스 LCD UART 모터 적외선


BASIC4MCU | 8051/PIC | DT-516 강좌 | 인터럽트 사용 LED 켜기

페이지 정보

작성자 키트 작성일2017-09-12 09:59 조회654회 댓글0건

본문

 

void EXT0_int(void) interrupt 0{ //외부 인터럽트0 벡터번호=0
    EA=0; //전체인터럽트 디스에이블

    led=(led<<1) | 0x01; //led 상태 변경
    if (led==0xff) led=0xfe; //마지막인지 검사, 마지막이면 재설정
    P1=led; //포트 1로 출력
    delay(200); //스위치 디바운싱을위해 지연
 
    EA=1; //전체 인터럽트 디스에이블
    return;
}
 
//--------------------------
인터럽트 함수입니다.
몇가지만 체크 해보죠
 
 
void EXT0_int(void) interrupt 0{ //외부 인터럽트0 벡터번호=0
    EA=0; //전체인터럽트 디스에이블

    led=(led<<1) | 0x01; //led 상태 변경
    if (led==0xff) led=0xfe; //마지막인지 검사, 마지막이면 재설정
    P1=led; //포트 1로 출력
    delay(200); //스위치 디바운싱을위해 지연
 
    EA=1; //전체 인터럽트 디스에이블
    return;
}
 
리턴은 함수의 문장 중간에서 함수를 빠져나갈 일이 있을 때 사용 합니다.
지금처럼 제일 마지막에서는 없어도 아랫줄에서 리턴 됩니다.
 
또 한가지
일반 함수는 어셈으로 보면 RET이고
인터럽트 함수는 RETI입니다.
두개의 기능은 차이가 있습니다.
컴파일 후 어셈 창을 열어서 명령어가 어떻게 쓰이고 있는지 체크 하세요
 
//-------
 
void EXT0_int(void) interrupt 0{ //외부 인터럽트0 벡터번호=0
    EA=0; //전체인터럽트 디스에이블

    led=(led<<1) | 0x01; //led 상태 변경
    if (led==0xff) led=0xfe; //마지막인지 검사, 마지막이면 재설정
    P1=led; //포트 1로 출력
    delay(200); //스위치 디바운싱을위해 지연
 
    EA=1; //전체 인터럽트 디스에이블
}
 
많은 책에서 인터럽트 디저블 이네이블 시키는 것을 종종 봅니다.
(책을 직접 본게 아니고..학생들의 질문을 통한 간접 경험으로 추측...)
 
디저블 시키는 이유는 몇가지가 있을 수 있는데
첫번째는 현재의 인터럽트 함수 안에서 다른 인터럽트의 간섭을 받지 않고 싶을 때
또 다른 이유는 위 코드처럼 여러번 발생 하는 채터링을 막기 위해서도 사용 합니다.
다른 인터럽트를 사용 하고 있지 않다고 하면 없어도 되는 문장이고
자기 자신의 채터링을 막기 위한 것이라면
 
void EXT0_int(void) interrupt 0{ //외부 인터럽트0 벡터번호=0
    EA=0; //전체인터럽트 디스에이블

    led=(led<<1) | 0x01; //led 상태 변경
    if (led==0xff) led=0xfe; //마지막인지 검사, 마지막이면 재설정
    P1=led; //포트 1로 출력
    delay(200); //스위치 디바운싱을위해 지연
    인터럽트 플래그 크리어; 
    EA=1; //전체 인터럽트 디스에이블
}
인터럽트 플래그를 크리어 시킨 후에 이네이블 시키는 것이 맞으며
 
void EXT0_int(void) interrupt 0{ //외부 인터럽트0 벡터번호=0
    led=(led<<1) | 0x01; //led 상태 변경
    if (led==0xff) led=0xfe; //마지막인지 검사, 마지막이면 재설정
    P1=led; //포트 1로 출력
    delay(200); //스위치 디바운싱을위해 지연
    인터럽트 플래그 크리어; 
}
어차피 자기 자신의 인터럽트는 함수를 마치기 전에는 실행 하지 않으므로
플래그만 크리어 시켜도 마찬가지가 되겠습니다.
 
 
 //-------------------
 
 

#include         <REG_MPC82G516.H>
//
void Timer_0_Interrupt(void) interrupt 1{ // 7200Hz=138.89us 주기
    P4=1;
    return; // 1번
    P4=2;
    return; // 2번
    P4=3;
    return; // 3번
}
//
void main(void){
    TMOD=2; ET0=1; TR0=1; EA=1;
    while(1){
    }
}
 
위 소스코드를 컴파일 한 후 어셈창의 내용입니다.
리턴을 3개 넣었습니다.
 
 
     5: void Timer_0_Interrupt(void) interrupt 1{ // 7200Hz=138.89us 주기 
     6:     P4=1; 
     7:     return;  // 1번
C:0x002F    75E801   MOV      P4(0xE8),#0x01
C:0x0032    8008     SJMP     C:003C
     8:     P4=2; 
     9:     return;  // 2번
C:0x0034    75E802   MOV      P4(0xE8),#0x02
C:0x0037    8003     SJMP     C:003C
    10:     P4=3; 
    11:     return;  // 3번 코드는 생략 되었습니다.
C:0x0039    75E803   MOV      P4(0xE8),#0x03
    12: } 
    13:  
    14: // 
C:0x003C    32       RETI    

    15: void main(void){ 
    16:     TMOD=2; ET0=1; TR0=1; EA=1; 
C:0x003D    758902   MOV      TMOD(0x89),#0x02
C:0x0040    D2A9     SETB     ET0(0xA8.1)
C:0x0042    D28C     SETB     TR0(0x88.4)
C:0x0044    D2AF     SETB     EA(0xA8.7)
    17:     while(1){ 
    18:     } 
C:0x0046    80FE     SJMP     C:0046
    19: } 
C:0x0048    22       RET     
 
 
위 코드에서 return은 그 함수의 마지막으로 점프 합니다.

댓글 0

조회수 654

등록된 댓글이 없습니다.

8051/PICHOME > 8051/PIC > 전체 목록

게시물 검색

2019년 1월 2월 3월 4월 5월 6월 7월 8월 9월 10월 11월 12월
2018년 1월 2월 3월 4월 5월 6월 7월 8월 9월 10월 11월 12월
Privacy Policy
MCU BASIC ⓒ 2017
모바일버전으로보기