해당강좌가 개설된 까페에서 스톱워치 만들기 강좌에 관한 질문 및 답변 정리 글입니다.
출처 : cafe.naver.com/laydigital/
안녕하세요 해당강좌를 공부한후에 과제를 수행후 기본강좌에서 궁금한점이 있어 질문올려봅니다.
아래 코드는 해당강좌에 기재하신 부분을 그대로 발췌하였습니다.
아래 코드에서
ISR(INT5_vect)
{
state = IDLE;
cur_time = 0;
stop_time = 0;
}
이 루틴을 수행하고 나오면 cur_time 과 stop_time은 0으로 초기화되는데 궁금증에 IDLE 상태에서 받는변수를 stop_time이 아닌 cur_time 변수를 넣어주었더니 00.00 표시값이 아닌 00.01표시값이 나오고 한번더 스위치2번을 눌러서 ISR루틴을
실행해야지 00.00이 표시되는데 왜 그런지 잘 이해가 않되서 질문드려봅니다. 0으로 초기화되서 나왔는데 왜 1값이 증가된 상태로 main 의 state==IDLE 상태에서 표시값이 받는 변수값이 증가되어 입력된건지 궁금합니다.
혹시 질문드린부분의 의미전달이 않될수도 있어서 아래 코드에서 수정한 부분을 빨간색으로 표시해 두었습니다.
/----------------------------------------------------------------------------------------------------------------------------------------/
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 16000000UL
#include <util/delay.h>
#define IDLE 0
#define STOP 1
#define GO 2
volatile int cur_time = 0;
volatile int stop_time = 0;
volatile int state = IDLE;
unsigned char digit[]= {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7c, 0x07, 0x7f, 0x67};
unsigned char fnd_sel[4] = {0x01, 0x02, 0x04, 0x08};
ISR(INT4_vect)
{ if (state == IDLE || state == STOP)
state = GO;
else
{
state = STOP;
stop_time = cur_time;
}
}
ISR(INT5_vect)
{
state = IDLE;
cur_time = 0;
stop_time = 0;
}
void init_stopwatch(void);
void display_fnd(int);
int main()
{
init_stopwatch( );
while(1)
{
if (state == IDLE)
display_fnd(cur_time); //원래는 stop_time , 두변수는 sw2 ISR루틴에서 모두 0으로 초기화됨.
else if (state == STOP)
{
display_fnd(stop_time);
cur_time++;
}
else
{
display_fnd(cur_time);
cur_time++;
}
if (cur_time == 10000)
cur_time = 0;
}
}
void init_stopwatch(void)
{
DDRC = 0xff;
DDRG = 0x0f;
DDRE = 0xcf;
sei();
EICRB = 0x0a;
EIMSK = 0x30;
}
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++)
{
if (i==2)
PORTC = digit[fnd[i]] | 0x80;
else
PORTC = digit[fnd[i]];
PORTG = fnd_sel[i];
if (i%2) _delay_ms(2);
else _delay_ms(3);
}
}
확인은 안해봤지만.
위의 코드에 잠재적인 atomic접근 문제가 있습니다.
2바이트짜리 state 및 counter 를
비인터럽트 루틴에서 사용하고
인터럽트에서 수정합니다.
critical section을 적용해 보시거나,
state를 char 타입으로 해 보세요.
critical section과 관련하여 이해도가 많이 부족합니다, 관련 용어를 이해하고 적용해보는 좋은 예가 있다면
알려주시면 감사하겠습니다.
atomic : 다른 인터럽트나 이벤트로부터 보호되며 최상의 우선순위를 가지고 실행 이라고 검색되는데, 설명해주신 용어를 이해하기엔 좀 버겁네여 아직 C언어 사용에만 급급해서 따라가고있습니다 ^^;
일단 알려주신 방법을 활용하여 연습했을땐 정상적으로 작동하네요.
http://cafe.naver.com/lazydigital/3450
참조하세요.
cur_time, stop_time 도 같은 이슈에 포함됩니다.
제가 이번주말에 어디를 가야 해서,
올려주신 소스에 대한 comment는 나중에 하겠습니다.
No comments:
Post a Comment