처음으로 _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;
}
}
}
가 있어야하지 않나요'(* 1000 16)':
전체 프로그램은 다음과 같을 것이다? 그냥 추측. –
우선 내가 그 값을 시도했지만 내 프로펠러의 잘못된 길을 준 것 –
어떤 해상도가 필요합니까? 당신은 알지 못합니다. 그래서 이런 종류의 대답을 정확하게 할 수 없습니다. 프로펠러에 대한 추측을하고 있니? 어떤 RPM입니까? – unwind