-내 코드-
#define DDRD (*((volatile unsigned char*)0x2A)) //입력쪽 (INT0)
#define PIND (*((volatile unsigned char*)0x29)) //입력핀
#define DDRE (*((volatile unsigned char*)0x2D)) //입력쪽 (INT4)
#define PINE (*((volatile unsigned char*)0x2C))
#define DDRC (*((volatile unsigned char*)0x27)) //7세그먼트 표현
#define PORTC (*((volatile unsigned char*)0x28)) //출력핀
#define SREG (*((volatile unsigned char*)0x5F)) //상태 레지스터, 0000 0000 부분중 제일 끝 자리가 글로벌
#define EIMSK (*((volatile unsigned char*)0x3D)) //인터럽트 사용할 핀을 설정.(현재 int0 번 사용 중)
#define EICRA (*((volatile unsigned char*)0x69)) //edge setting(rising , falling)
#define EICRB (*((volatile unsigned char*)0x6A)) //edge setting
#define EIFR (*((volatile unsigned char*)0x3C)) //반환(인터럽트 사용했던 핀의 값을 반환)
volatile unsigned int uiCnt;
#define DELAY(X) for(uiCnt = 0; uiCnt < (X) ; ++uiCnt)
void ito7seg_cal(unsigned int tmp);
unsigned char bitcal(unsigned char c1, unsigned char c2, unsigned char c3, unsigned char c4, unsigned char c5, unsigned char c6, unsigned char c7);
void __vector_1(void)__attribute__((signal,used,externally_visible));//int0의 벡터 번호 1
void __vector_1(void)// 처리할 루트를 넣어준다. 끼어드는 조건이 만족하면 실행된다.
{
while(!(PIND & 0x01));
EIFR = 0x01; //반환 값. 그쪽 인터럽트를 사용했다라는 뜻의 반환.
}
void __vector_5(void)__attribute__((signal,used,externally_visible));//int4의 벡터 번호 5
void __vector_5(void)// 처리할 루트를 넣어준다. 끼어드는 조건이 만족하면 실행된다.
{
while((PINE & 0x10) == 0);
EIFR = 0x10; //반환 값. 그쪽 인터럽트를 사용했다라는 뜻의 반환.
}
int main(void)
{
volatile unsigned int uiCnt; //DELAY 정의 한 변수
volatile unsigned int i; //for문 제어
unsigned char cFlag = 0;
DDRD = 0xEE; //인터럽트 핀. 펌웨어 쪽에서는 사용하지 않는 핀들을 전부 출력으로 설정해 준다.
SREG &= 0x7F; /*0111 1111, &= 이 의미는 형태 sreg 0x7F 가 앤드 형태로 들어가 있으니 다른 어떤 값이 들어오면 &시켜버린다. 즉 지금의 형태는 모든 인터럽트를 사용 안하겠다가 된다.*/
DDRC = 0xFF; //7세그먼트 쪽 입/출력 핀을 전부 출력으로
EIMSK = 0x11; //인터럽트 핀(0),(4) 두 개 사용
EICRA = 0x02; //falling edge 사용
EICRB = 0x02; //falling edge 사용
SREG |= 0x80; //현재 인터럽트를 쓰지 않고 main 함수 while문에서 다 끝내려 한다
while(1)
{
if(PIND == 1 & cFlag == 0)//입력값이 들어왔을때 INT0 작동, 그 전까진 FOR문으로 숫자 증가 작업 중
{
for(i = 0; i<10; ++i)
{
ito7seg_cal(i); //이렇게 되면 0~9 까지 집어넣어서 세그먼트에 숫자를 표현되게 된다.
DELAY(5000);
}
cFlag = 1;
}
else if(PINE == 1 & cFlag == 1)
{
for(i = 9; i > -1; --i)
{
ito7seg_cal(i); //이렇게 되면 0~9 까지 집어넣어서 세그먼트에 숫자를 표현되게 된다.
DELAY(5000);
}
cFlag = 0;
}
}
return 0;
}
void ito7seg_cal(unsigned int tmp)//7세그먼트의 카운트 형태 함수 정의
{
switch(tmp)
{
case 0 :
PORTC = bitcal(0,0,0,0,0,0,1);
break;
case 1 :
PORTC = bitcal(1,0,0,1,1,1,1);
break;
case 2 :
PORTC = bitcal(0,0,1,0,0,1,0);
break;
case 3 :
PORTC = bitcal(0,0,0,0,1,1,0);
break;
case 4 :
PORTC = bitcal(1,0,0,1,1,0,0);
break;
case 5 :
PORTC = bitcal(0,1,0,0,1,0,0);
break;
case 6 :
PORTC = bitcal(0,1,0,0,0,0,0);
break;
case 7 :
PORTC = bitcal(0,0,0,1,1,0,1);
break;
case 8 :
PORTC = bitcal(0,0,0,0,0,0,0);
break;
case 9 :
PORTC = bitcal(0,0,0,0,1,0,0);
break;
}
}
unsigned char bitcal(unsigned char c1, unsigned char c2, unsigned char c3, unsigned char c4, unsigned char c5, unsigned char c6, unsigned char c7)
{
//return ( ( !c1 << 0 ) |( !c2 << 1 ) |( !c3 << 2 ) |( !c4 << 3 ) |( !c5 << 4 ) |( !c6 << 5 ) |( !c7 << 6 ) );
return ( ( c1 << 0 ) |( c2 << 1 ) |( c3 << 2 ) |( c4 << 3 ) |( c5 << 4 ) |( c6 << 5 ) |( c7 << 6 ) ); //common - anode type(세그먼트가 직접 vcc를 받는 형태) 이기에 0 값을 보내줘야 전압차로 인해서 불이 켜진다.
}
진짜 화가난다 화가나
-제혁씨 코드-
//#include <avr/interrupt.h>
#include <stdlib.h>
#define PORTE (*((volatile unsigned char *)0x2E))
#define DDRE (*((volatile unsigned char *)0x2D))
#define PINE (*((volatile unsigned char *)0x2C))
#define PORTD (*((volatile unsigned char *)0x2B))
#define DDRD (*((volatile unsigned char *)0x2A))
#define PIND (*((volatile unsigned char *)0x29))
#define PORTA (*((volatile unsigned char *)0x22))
#define DDRA (*((volatile unsigned char *)0x21))
#define PINA (*((volatile unsigned char *)0x20))
#define EICRA (*((volatile unsigned char *)0x69))
#define EICRB (*((volatile unsigned char *)0x6A))
#define SREG (*((volatile unsigned char *)0x5F))
#define EIMSK (*((volatile unsigned char *)0x3D))
#define EIFR (*((volatile unsigned char *)0x3C))
char led = 0;
unsigned int num = 0;
void ito7seg_cal(unsigned int tmp);
unsigned char bitcal(unsigned char c1, unsigned char c2, unsigned char c3, unsigned char c4, unsigned char c5, unsigned char c6, unsigned char c7);
void __vector_1(void)__attribute__((signal, used, externally_visible));
void __vector_1(void)
{
volatile unsigned int dt;
while((PIND & 0x01) == 0)
{
if(num < 9)
{
num++;
ito7seg_cal(num);
for(dt = 0; dt < 20000; dt++);
}
}
EIFR = 0x01; //INT0 Interrupt END
}
void __vector_5(void)__attribute__((signal, used, externally_visible));
void __vector_5(void)
{
volatile unsigned int dt;
while((PINE & 0x10) == 0)
{
if(num > 0)
{
num--;
ito7seg_cal(num);
for(dt = 0; dt < 20000; dt++);
}
}
EIFR = 0x10; //INT4 Interrupt END
}
int main(void)
{
volatile unsigned int dt = 0;
unsigned int direction = 1;
SREG = SREG & 0x7F; //Global Interrupt Disable MASK
DDRE = 0x00; // all input
DDRD = 0x00; // all input
DDRA = 0xFF; // led output
EIMSK = (1 << 0) | (1 << 4) ; //INT0 MASK
EICRA = 0x02; // INT0 falling level
EICRB = 0x02; // INT4 falling level
led = 0x01;
SREG |= 0x80; //Global Interrupt Disable MASK
while(1)
{
/*PORTA = (~led);
if(led == 0x80) direction = 0;
if(led == 0x01) direction = 1;
if(direction == 0) led = ( led >> 1 );
if(direction == 1) led = ( led << 1 );
for(dt = 0; dt < 5000; dt++);*/
}
return 0;
}
void ito7seg_cal(unsigned int tmp)
{
switch(tmp)
{
case 0 :
PORTA = bitcal(0,0,0,0,0,0,1);
break;
case 1 :
PORTA = bitcal(1,0,0,1,1,1,1);
break;
case 2 :
PORTA = bitcal(0,0,1,0,0,1,0);
break;
case 3 :
PORTA = bitcal(0,0,0,0,1,1,0);
break;
case 4 :
PORTA = bitcal(1,0,0,1,1,0,0);
break;
case 5 :
PORTA = bitcal(0,1,0,0,1,0,0);
break;
case 6 :
PORTA = bitcal(0,1,0,0,0,0,0);
break;
case 7 :
PORTA = bitcal(0,0,0,1,1,0,1);
break;
case 8 :
PORTA = bitcal(0,0,0,0,0,0,0);
break;
case 9 :
PORTA = bitcal(0,0,0,0,1,0,0);
break;
}
}
unsigned char bitcal(unsigned char c1, unsigned char c2, unsigned char c3, unsigned char c4, unsigned char c5, unsigned char c6, unsigned char c7)
{
//return ( ( !c1 << 0 ) |( !c2 << 1 ) |( !c3 << 2 ) |( !c4 << 3 ) |( !c5 << 4 ) |( !c6 << 5 ) |( !c7 << 6 ) );
return ( ( c1 << 0 ) |( c2 << 1 ) |( c3 << 2 ) |( c4 << 3 ) |( c5 << 4 ) |( c6 << 5 ) |( c7 << 6 ) );
}
-느낀점-
인터럽트 쪽에 가보면 알 수 있다. 굉장히 심플하고도 간단한 생각이지만 그걸 구현을 못했다라는게 하루종일 기분이 안 좋았다.
내가 몰랐던 점은 숫자가 증가하거나 감소할때나 가만히 있을때 그 값에서부터 인터럽트가 걸리면 그 숫자가 진행되던 중에 그 숫자값에서 감소,증가 를 어떻게 코드로 표현하느냐에 있었다.
제혁씨의 경우 while의 조건에 (PIND & 0x10) == 0 이런식으로 !(PIND & 0x10) 이것과 동일한데 조금 풀어 쓴 코드를 썼다.
나는 while문을 정확히 이해를 하고 있던것이 아니였다. c언어의 조건들의 포인트는 그 조건에 만족할 때 1값을 만들어 내겠다 에 있다.
즉, while 문의 PIND 쪽이 LOW LEVEL 이기에 &를 만족 시키지 못하고 == 0 과 같으므로 1값을 만들어내어 while 문을 돌리는 것 이다.
-동작 순서-
우선 일의 세분화를 시켜야 한다.
1. main 에서 뭘 하느냐 ?(인터럽트 작동을 안하는 조건은 몇가지가 있을까? 스위치를 둘다 안켰을 때, 스위치를 둘다 켰을 때 인터럽트 조건을 만족 하지 않기에 main으로 돌아와 하던 것을 반복한다. 이 때 while로 반복만 죽어라 시킨다. 숫자를 가만히 있게끔)
2. 현재 인터럽트 edge 셋팅을 falling으로 하라 했으니 켜졌다가 꺼지면 비로소 동작한다 라는 것을 명확히 하여 세분화 시킨다. 그리하여 인터럽트는 무엇을 하느냐?(INT0 부분은 +로 나타낸다, INT4 부분은 -로 나타낸다. 딜레이 정의가 필요할 것이고 또한 그 세그먼트 숫자를 정의한 함수에다가 인자로써 보내는 역활이 필요할 것이며 그 인자 변수를 전역에 선언하여 다 같이 그 숫자를 기본으로 증가,멈춤,감소 를 표현 할 수 있도록 해야 하겠다.)
저것을 정확히 동작하게끔 하려면 우선 인터럽트 스위치를 둘 다 킨 상태에서 시작하여 그 스위치를 껐을시 falling edge 가 만족하여 (low level == 0x00 또한 같은 역활) 그 쪽 인터럽트가 작동하게 된다.
그리고 if 문 안에
while((PIND & 0x01) == 0)
{
if(num < 9)
{
num++;
ito7seg_cal(num);
for(dt = 0; dt < 20000; dt++);
}
}
이 부분을 보자면 우선은 증가가 됬건 감소가 됬건 가만히 있었던건 간에 그 전 숫자를 이미 표현 해 냈었기 때문에 우린 그냥 그 다음 숫자만 표현하면 되는 것이다. 나는 그렇게 생각 하지 않고 그 숫자를 표현해야 하고 ++ 을 시켜야 한다고 생각했다.. (ito7seg-cal(num); 다음에 num++; 이 와야 한다고 생각했다..)
즉, c언어의 컴파일 순서를 명확히 모른다 라는 결론이 도출된다 봐도 무방할 것 같다.
크게 반성해야 하며 다시 한 번 더 열심히 해야 함을 느낀다.
'개발자 > C 언어' 카테고리의 다른 글
C언어_교환법칙, (2,3)차원 배열, 더블 포인터의 이해 (0) | 2015.04.17 |
---|---|
C언어_구조체 메모리 최적화(전처리어 pragma 사용법),구조체 활용, 공용체 사용법 (0) | 2015.04.17 |
C언어_구조체의 활용(배열 통째로 옮기기, 구조체 메모리 저장 형태) (0) | 2015.04.17 |
C언어_펌웨어_인터럽트 사용법 (0) | 2015.04.17 |
C언어_펌웨어_주사위 인터럽트 사용. (0) | 2015.04.17 |