2015-01-22 7 views
1

인터럽트 시간을 카운트하는 방법과 전역 변수를 설정하는 방법은 무엇입니까? 내 마이크로 컨트롤러는 Atmega8이고, F_CPU는 16MHz이고, 프로그래밍 언어는 C입니다. 몇 가지 사항을 알고 있습니다. 그 줄은 시계의 초기화입니다.시계가 16MHz 인 ATMega8에서 C를 계산하는 방법

그리고이 행은 전역 변수 "a"가 "xxx"로 나눈주기 값을 얻습니다. 그러나 xxx에는 어떤 값을 할당해야합니까?

a = TCNT1/xxx; 

PS1 : 나는 추진의 LED 디스플레이 내 프로펠러의 마지막 회전을 계산하고 올바른 방법으로 이미지를 표시하려면 다음 인터럽트이 값을주고 싶다.

PS2 : 지연을 위해 함수 : _delay_ms()를 사용합니다.

+0

가 있어야하지 않나요'(* 1000 16)':

전체 프로그램은 다음과 같을 것이다? 그냥 추측. –

+0

우선 내가 그 값을 시도했지만 내 프로펠러의 잘못된 길을 준 것 –

+0

어떤 해상도가 필요합니까? 당신은 알지 못합니다. 그래서 이런 종류의 대답을 정확하게 할 수 없습니다. 프로펠러에 대한 추측을하고 있니? 어떤 RPM입니까? – unwind

답변

2

처음으로 _delay_ms을 사용하면 적절한 타이밍을 수행하는 좋은 방법이 아닙니다.

다음을 제안합니다. 로터의 주파수를 측정하기 위해 timer1을 사용하십시오. 위치 인터럽트를 얻으면 (차례 당 하나라고 가정) 현재 타이머 값을 변수에 씁니다. 다음 인터럽트 각각에서 사이클 카운터의 차이를 계산합니다 (오버플로를 올바르게 고려해야 함).

이제는 1 회 전당 사이클 수가 있습니다. 이제 카운터의 최고 값 (CTC 모드)이 측정 한 사이클 수를 디스플레이의 각도 해상도로 나눈 값과 같은 방식으로 두 번째 타이머를 설정합니다. 오버 플로우 인터럽트에서 새로운 데이터를 LED에 래치 할 수 있습니다.

예 :

전제/가정 :

  • F_CPU (실제 클럭) 16MHz 일
  • 디스플레이 해상도 : 200 앵글
  • 로터 속도 : 137Hz
  • 타이머 1 프리스케일러 = 4 (그렇지 않으면 1 회 전당 여러 번 넘침)

이 값을 사용하면 29197 Timer-Ticks의 차이가 발생하여 116878.3 CPU-Cycles/Revolution으로 변환됩니다. 200 줄로 나누면 섹션 당 583.94 사이클이 있습니다. 이 숫자는 8 비트 카운터에 비해 너무 큽니다. prescaler 2를 사용하면 291.97이 너무 큽니다. 따라서 다음으로 큰 프리스케일러 (희망 사항) 4를 사용하면 145.98이됩니다. 0으로 계산되기 때문에 최대 146 및 -1로 올림. 그래서이 카운터의 최고 값으로 145를 사용하는 것이 좋습니다. 이 고려 사항은 프로그래밍 방식으로 구현되어야합니다. 주기 값을 얻고 8 비트에 맞지 않는 한 프리스케일러를 늘리십시오.

volatile uint16_t oldTimer=0; 
volatile uint16_t newTimer=0; 
volatile uint8_t flag=0; // bit 1 = push new data, bit 2 = new revolution measurement 

ISR(Postional Interupt){ 
oldTimer = newTimer; 
newTimer = TCNT1; 
flag |= 2; 
} 

ISR(timer2_overflow){ 
    latchDataToOutput(); 
    flag |= 1; 
} 

int main() 
{ 
    while(1){ 
    if(flag & 2){ 
     calcNewTimer2Timing(); 
     flag &= ~2; 
    } 
    if(flag & 1){ 
     OutputDataToShiftRegister(); 
     flag &= ~1; 
    } 

    } 
}