BASIC4MCU | 질문게시판 | 토글스위치 질문드립니다.
페이지 정보
작성자 412904 작성일2022-06-11 16:29 조회578회 댓글3건본문
ISR(TIMER1_OVF_vect)
{
if(timerFlag==1){
if(switchCnt==0){
PORTA=rotationCW;
ADCSRA|=(0x01<<ADSC);
c=ADCW;
OCR1A=(c>>1)+(c>>2)+(c>>5);
}
else if(switchCnt==1){
PORTA=rotationCCW;
ADCSRA|=(0x01<<ADSC);
c=ADCW;
OCR1A=(c>>1)+(c>>2)+(c>>5);
}
else;
}
else if(timerFlag==0){
OCR1A=0;
PORTA=rotationStop;
}
else;
}
ISR(INT0_vect){// toggle switch-related
if(timerFlag==0){
timerFlag=1;
}
else if(timerFlag==1){
timerFlag=0;
}
else;
}
ISR(INT1_vect){// toggle switch-related
if(PORTA==rotationStop){// only can change when the motor stopped
if(switchCnt==0){
switchCnt=1;
}
else if(switchCnt==1){
switchCnt=0;
}
else;
}
else;
}
// 모터를 돌리고 있는데요, 실행 후 처음에는 모터를 정지시켰다가 외부 인터럽트0에 스위치를 연결하여 동작시키고
외부 인터럽트 1번에는 모터가 정지했을 때만 방향 전환이 가능하도록 설정하고 있습니다. 그런데 스위치 동작이 됐다가, 안 됐다가 해서
스위치를 교체도 해봤는데 여전히 문제는 해결되지 않습니다. 혹시나 프로그래밍의 신뢰성(?)이 떨어져 그런 게 아닌가 싶어 이렇게 글 올립니다.
조언해 주시면 감사하겠습니다.
댓글 3
조회수 578master님의 댓글
master 작성일
ISR(TIMER1_OVF_vect){
if(timerFlag){
c=ADCW; OCR1A=(c>>1)+(c>>2)+(c>>5); ADCSRA|=(0x01<<ADSC);
if(switchCnt)PORTA=rotationCCW; else PORTA=rotationCW;
}
else{ OCR1A=0; PORTA=rotationStop; }
}
//
ISR(INT0_vect){
timerFlag^=1;
}
//
ISR(INT1_vect){
if(PORTA==rotationStop)switchCnt^=1;
}
질문 코드를 정리 한 겁니다.
쓸데없이 else를 남용하고 있군요
현재 문제는 채터링 때문에 오동작 하는 것인데요
스위치에 병렬로 0.1uF 커패시터를 연결하면 채터링이 현저하게 줄어듭니다.
코드 보완은 아래 댓글로 적어드리죠
master님의 댓글
master 작성일
채터링은 누를 때만 발생하는 것이 아니고, 뗄 때도 발생합니다.
누를 때와 뗄 때 발생하는 채터링을 방지하기 위해서는
핀체인지 인터럽트를 사용하는 것이 좋습니다.
핀체인지 인터럽트는 INT4~INT7 에만 있습니다.
따라서 인터럽트는 INT4와 INT5로 변경하세요(핀 연결도 PE4,PE5로)
EICRB=0x00; LOW 레벨, EICRB=0xAA; 하강엣지, EICRB=0xFF; 상승엣지, EICRB=0x55; 핀체인지
아래처럼 인터럽트 설정을 변경합니다.
EICRB=0x55; EIFR=0xFF; EIMSK=0x30; // INT4,INT5 핀체인지 인터럽트 설정
인터럽트 함수는 아래처럼 변경하세요
ISR(TIMER1_OVF_vect){
if(timerFlag){
c=ADCW; OCR1A=(c>>1)+(c>>2)+(c>>5); ADCSRA|=(0x01<<ADSC);
if(switchCnt)PORTA=rotationCCW; else PORTA=rotationCW;
}
else{ OCR1A=0; PORTA=rotationStop; }
}
//
ISR(INT4_vect){
_delay_ms(50); // 채터링이 발생하는 동안 딜레이로 넘기고
if((PINE&0x10)==0)timerFlag^=1; // 누를 때(PE4=0)만 동작( 뗄 때(PE4=1)는 무시)
EIFR=0x10; // 딜레이 동안에 발생한 인터럽트 플래그는 clear
}
//
ISR(INT5_vect){
_delay_ms(50);
if((PINE&0x20)==0){ // 누를 때만 동작
if(PORTA==rotationStop)switchCnt^=1;
}
EIFR=0x20;
}
412904님의 댓글
412904
정말 감사드립니다. 하루 종일 고민하던 문제가 덕분에 단숨에 해결되었습니다...