BASIC4MCU | 질문게시판 | atmega
페이지 정보
작성자 hello0 작성일2021-12-20 23:04 조회731회 댓글1건본문
#include <avr/interrupt.h>
#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>
#define IDLE 0 //IDLE 상태 값
#define STOP 1 //STOP 상태 값
#define GO 2 //GO 상태 값
volatile int cur_time = 0; //'현재 시간'변수 초기화
volatile int stop_time = 0; //'STOP 시간'변수 초기화
volatile int state = IDLE; //state:현재 상태를 나타내는 전역변수 전역변수(global variable)
//처음 시작 시에는 STOP상태에서 출발
unsigned char digit[] = { 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7c,0x07,0x7f,0x67 };
unsigned char fnd_seI[4] = { 0x01, 0x02, 0x04, 0x08 }; //FND 선택 신호 어레이
ISR(INT4_vect)
{
_delay_ms(100); //스위치 바운스 기간 동안 기다림
if ((PINE & 0x10) == 0x10) //인터럽트 입력 핀(PE4)을 다시 검사하여
return; //눌러진 상태가 아니면('1') 인터럽트가 아니므로 리턴
EIFR |= 1 << 4; //눌러진 상태이면('0') 그 사이에 바운스에 의하여 생긴 인터럽트는 무효화
if (state == IDLE || state == STOP)
state = GO;
else
{
state = STOP;
stop_time = cur_time;
}
}
ISR(INT5_vect)
{
_delay_ms(100);
if((PINE & 0x30)==0x30)
return;
EIFR |= 1 << 5;
state = STOP;
stop_time = cur_time;
}
ISR(INT7_vect)
{
_delay_ms(100); //스위치 바운스 기간 동안 기다림
if((PINE & 0x80)==0x80) //인터럽트 입력 핀(PE7)을 다시 검사하여
return; //눌러진 상태가 아니면('1') 리턴
EIFR |= 1 << 7; //그 사이에 바운스에 의하여 생긴 인터럽트는 무효화
state = IDLE; //상태(state) 초기화, RESET 시 -> IDLE
cur_time = 0; //'현재시간' 변수 초기화
stop_time = 0; //'STOP 시간' 변수 초기화
}
void init_stopwatch(void); //main 함수가 call하는 함수는 main
//함수보다 먼저 나타나거나 그 타입만
//먼저 나오고 나중에 call 경우 유효함
void display_fnd(int); //마찬가지 이유
int main(void)
{
init_stopwatch();
while(1)
{
if(state == IDLE)
display_fnd(stop_time); //초기값 00.00 디스플레이, 시간은 정지
else if(state == STOP)// STOP상태이면
{
display_fnd(stop_time);
cur_time++;
}
else
{
display_fnd(cur_time);
cur_time++;
}
if (cur_time == 10000)// 99.99 다음은 00.00
cur_time = 0;
}
}
void init_stopwatch(void)
{
PORTE=0x00; // ISR 4~7
DDRE=0x00; //PE4(SW1),PE5(SW2),PE6(SW3),PE7(SW4)를 포함한 PE 포트는 입력신호
DDRA=0xFF; // 7-seg 값
DDRC=0xFF; // 7-seg 자리, C포트는 FND 데이터 신호
DDRG=0x0f; //G포트는 FND 선택 신호
sei(); //SREG 7번 비트(I)세트
//sei()는 "SREG|=0x80"와 동일한 기능을 수행
EICRB = 0x0F; // INT 4~7 트리거 신호 (0000 1111) 하강 에지(Falling Edge)
EIMSK = 0xF0; // INT4,INT5,INT6,INT7 인터럽트 enable
}
void display_fnd(int count) //이 함수의 1회 수행시간은
//약 10ms(1/100초)로 _delay_ms()
//외의 코드 실행시간은 us 단위로 무시
{
int i, fnd[4]; //각 자리수의 변수를 다르게 해도 되지만
//여기처럼 변수를 어레이로 잡는 것도 방법
fnd[3] = (count/1000)%10; //천 자리
fnd[2] = (count/100)%10; //백 자리
fnd[1] = (count/10)%10; //십 자리
fnd[0] = count%10; //일 자리
for (i=0; i<4; i++) //어레이의 첨자를 이용하면 프로그램 단순화 가능
{
if (i==2)
PORTC = digit[fnd[i]]|0x80; //구분점 (dot)추가
else
PORTC = digit[fnd[i]];
PORTG = fnd_seI[i];
if (i%2)
_delay_ms(2); //i가 홀수일 때는 2ms,
else
_delay_ms(3); //짝수일 때는 3ms, 딜레이 = i가 4번
//루프를 돌므로 총 10ms(1/100초)경과
}
}정지상태에서
SW2버튼 -> 진행 : cur_time 세그먼트에 표기(증가)
SW3버튼 -> 일시정지 : 버튼누른 시점의 cur_time 세그먼트에 표기(대기)
SW4버튼 -> 리셋 : cur_time=0
을 하려고 하는데 작동이 안되서요ㅠㅠ 어디가 문제일까요
댓글 1
조회수 731master님의 댓글
master 작성일
#include <avr/interrupt.h>
#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>
//
#define IDLE 0
#define STOP 1
#define GO 2
//
unsigned char digit[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7c,0x07,0x7f,0x67};
unsigned char fnd_seI[4]={0x01,0x02,0x04,0x08};
//
volatile int cur_time=0,stop_time=0,state=IDLE;
//
void display_fnd(int count){
int i,fnd[4];
fnd[3]=(count/1000)%10; //천
fnd[2]=(count/100)%10; //백
fnd[1]=(count/10)%10; //십
fnd[0]=count%10; //일
for(i=0;i<4;i++){
PORTC=digit[fnd[i]]; if(i==2)PORTC|=0x80; PORTG=fnd_seI[i]; _delay_us(2500);
}
}
//
ISR(INT4_vect){
_delay_ms(100); if((PINE&0x10)==0x10)return; EIFR|=0x10;
if(state==IDLE||state==STOP)state=GO; else{ state=STOP; stop_time=cur_time; }
}
//
ISR(INT5_vect){
_delay_ms(100); if((PINE&0x20)==0x20)return; EIFR|=0x20;
state=STOP; stop_time=cur_time;
}
//
ISR(INT6_vect){
_delay_ms(100); if((PINE&0x40)==0x40)return; EIFR|=0x40;
}
//
ISR(INT7_vect){
_delay_ms(100); if((PINE&0x80)==0x80)return; EIFR|=0x80;
state=IDLE; cur_time=0; stop_time=0;
}
//
int main(void){
DDRA=0xFF;
DDRC=0xFF; // seg
DDRG=0x0f; // select
EICRB=0xAA; EIMSK=0xF0; // INT 4~7 하강 에지(Falling Edge)
sei();
while(1){
if (state==IDLE){ display_fnd(stop_time); }
else if(state==STOP){ display_fnd(stop_time); if(++cur_time==10000)cur_time=0; }
else { display_fnd(cur_time); if(++cur_time==10000)cur_time=0; }
}
}