2016-12-01 11 views
1

AVR 또는 STM32 MCU에서 실제 이벤트 (예 : 3 초 동안 버튼 누름)를 할 때까지 기다리는 중이며 다음과 같은 코드에 문제가 있습니다.Loop "while"이 인터럽트로 두 조건을 만족시키지 못합니다.

#define PRESS_BUTTON 
int waiting = 0; 
int t_ms = 0; // time counter 
//... 

int main(void) 
{   
    while(1) 
    {   
     waiting = t_ms + 3000; // waiting button 3 sec 

     while ((t_ms < waiting) && (!PRESS_BUTTON)) // infinite loop 
     {}     
     printf("out"); // not printed 
     waiting = t_ms = 0; 
    }  
} 

ISR(TIMER0_OVF_vect) // timer interrupt 
{ 
    t_ms++; 
} 

하지만이 while 루프 내부의 printf()를 추가하는 경우, 그것을 작동합니다!

do...while 루프를 사용하면 동일한 문제가 발생합니다. 이 원인은 무엇입니까?

+3

'휘발성'키워드의 강력 함. 'volatile int t_ms = 0;'로 변경하십시오. – LPs

+0

'휘발성'을 추가하는 것 이외에, 어떻게 단추를 디 바운스합니까? 이 작업은 소프트웨어 또는 하드웨어로 수행해야합니다. 그렇지 않으면 프로그램이 항상 제대로 작동하지 않습니다. – Lundin

+0

만월 5 회마다 한 번만 stackoverflow에 적절히 필요한 '휘발성'이 표시됩니다. 좋은 질문. –

답변

2

당신은 휘발성

volatile int t_ms =0; 

휘발성이 변수가 외부 요인으로 인해 변경 될 수 있습니다 컴파일러를 알려줍니다으로 t_ms를 선언해야하고,이 때문에 컴파일러는 동일하게 유지됩니다 생각하지 않습니다.

즉, 컴파일러가 모든 루프를 검사하여 t_ms가 변경되지 않을 것이라고 판단하지 않고 변경되었는지 확인해야합니다.

+0

하지만 원 자성을 가정 할 때는주의해야합니다. 일반적으로 말하자면 이것은 'sig_atomic_t '가 아닌 유형에서는 안전하지 않습니다. 특히 문제의 8 비트 AVR 아키텍처는 하위 바이트와 상위 바이트를 개별적으로 읽지 않으므로 인터럽트 경주의 경우 찢어진 값을 볼 수 있습니다. 가장 쉬운 해결 방법은 인터럽트를 마스킹하는 것 이외에도 순서대로 MSB, LSB 및 MSB 부분을 읽은 다음 두 번째 읽기가 불일치하는 경우 스핀하는 것입니다 (단조 증가 카운터 이상으로이 전략이 ABA 문제를 일으킬 수 있음). – doynax