BASIC4MCU | 질문게시판 | ATMEGA128 외부 인터럽트 수행.
페이지 정보
작성자 소고기카레 작성일2025-05-11 01:29 조회476회 댓글2건본문
#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
// 소프트웨어 딜레이
static void Delay_ms(unsigned int ms) {
while (ms--) _delay_ms(1);
}
static void Delay_us(unsigned int us) {
while (us--) _delay_us(1);
}
// 키패드 정의 (PORTB)
#define KEY_MASK_ROWS 0x0F // PB0~PB3 → Row (출력)
#define KEY_MASK_COLS 0xF0 // PB4~PB7 → Col (입력+풀업)
#define SW_1_KEY 0xEF // row0+col4 → '1'
#define SW_3_KEY 0xBF // row0+col6 → '3'
// PWM 정의 (Timer3, OC3A)
#define PWM_TOP 500 // 16MHz/8/500 ≒4kHz
#define PWM_DDR DDRE
#define PWM_PORT PORTE
#define PWM_PIN PE3
// 1) Timer3 하드웨어 PWM 초기화 (Fast PWM Mode14, Non-inv, N=8)
void initPWM(void) {
TCCR3A = (1<<COM3A1);
TCCR3B = (1<<WGM33)|(1<<WGM32)|(1<<CS31);
ICR3 = PWM_TOP;
OCR3A = 0; // 초기 0%
PWM_DDR |= (1<<PWM_PIN);// PE3 출력
}
// 2) PORTB 4×4 키패드 → PCINT0_vect 설정
void initKeypadInterrupt(void) {
DDRB |= KEY_MASK_ROWS; // PB0~PB3 출력
PORTB |= KEY_MASK_COLS; // PB4~PB7 풀업
GICR |= (1<<PCIE0); // PCINT0..7 그룹 허용
PCMSK0 |= KEY_MASK_COLS; // PB4~PB7 변화만 인터럽트
}
// 3) PCINT0_vect → 키패드 스캔 & PWM 듀티 조절
ISR(PCINT0_vect) {
Delay_ms(20); // 디바운싱
// 행 스캔
for (uint8_t row = 0; row < 4; row++) {
// 해당 row만 LOW, 나머지는 HIGH(풀업 유지)
PORTB = (~(1<<row)) | KEY_MASK_COLS;
Delay_us(5);
uint8_t cols = PINB & KEY_MASK_COLS;
if (cols != KEY_MASK_COLS) {
// '1'키 → PWM 0%
if (row==0 && cols==SW_1_KEY) {
OCR3A = 0;
}
// '3'키 → PWM 100%
else if (row==0 && cols==SW_3_KEY) {
OCR3A = PWM_TOP;
}
break;
}
}
// 키 완전 해제 대기
while ((PINB & KEY_MASK_COLS) != KEY_MASK_COLS) {;}
}
int main(void) {
initPWM();
initKeypadInterrupt();
sei(); // 전역 인터럽트 허용
while (1) { }
}
현재 code에서 동일한 Error가 계속 발생합니다.
사진 첨부 합니다. 감사합니다 ㅠㅠ
댓글 2
조회수 476master님의 댓글
master 작성일
오류가 발생한 것을 하나씩 처리하시면 됩니다.
//
GICR 대신 EIMSK 레지스터를 사용해야 합니다.
데이터시트에서 EIMSK를 검색해보세요
//
mega8 이라든가 낮은 버전의 AVR에서 GICR을 사용합니다.
master님의 댓글
master 작성일
PCIE0 이 명칭도 데이터시트에서 검색되지 않습니다.
//
128, 2560처럼 AVR 버전이 올라 갈 수록 기능이 많아서 레지스터가 복잡해지므로
어느 순간 이전 버전과 차이가 발생할 수 있습니다.
//
128 경우, 8개의 외부인터럽트는 기능이 모두 동일하지 않습니다.
핀체인지 인터럽트는 PE4(INT4)~PE7(INT7) 4개만 가능합니다.
데이터시트에서 Table 50. Interrupt Sense Control 표를 보시면
ISCn1=0, ISCn0=1 설정으로 "Any logical change on INTn generates an interrupt request" 설정할 수 있으며, 핀체인지 인터럽트가 됩니다.
예를들면
PE4 1개만 핀체인지 인터럽트로 사용하려면
EIMSK=0x10; // INT4 이네이블
EICRB=0x01; // 핀체인지 트리거 설정
INT4~INT7 4개 모두 핀체인지 인터럽트로 사용한다면
EIMSK=0xF0; // INT4~7 이네이블
EICRB=0x55; // 핀체인지 트리거 설정
INT4,5는 핀체인지트리거, 6은 폴링엣지트리거, 7은 라이징엣지트리거로 사용한다면
EIMSK=0xF0; // INT4~7 이네이블
EICRB=0xE5; // 11(라이징) 10(폴링) 01(체인지) 01(체인지)