2015-01-22 6 views
1

Как подсчитать время в прерывании и установить как глобальную переменную? Мой микроконтроллер - Atmega8, F_CPU - 16 МГц, язык программирования - C. Я знаю несколько вещей, эта строка ниже - инициализация часов.Как считать время в C для ATMega8 с тактовой частотой 16MHz

TCCR1B |= (1 << CS10); 

И эта линия делают, что глобальная переменная «а» получить значение циклов, деленное на «ххх». Но какое значение должно быть присвоено xxx?

a = TCNT1/xxx; 

PS1: Я хочу считать последнюю очередь моего винта в Propelled светодиодного дисплея и дает это значение для следующего прерывания, чтобы отобразить изображение в правильном направлении.

PS2: Для выполнения задержек я использую функцию: _delay_ms().

+0

это не должно быть '(16 * 1000)'? Просто догадка. –

+0

прежде всего я пробовал это значение, но он дал неправильный путь моего пропеллера –

+0

Какое разрешение вам нужно? Вы, кажется, не знаете, что делает такой ответ невозможным. Вы делаете мертвый расчет пропеллера? Что такое RPM? – unwind

ответ

2

с использованием _delay_ms не является хорошим способом правильного выбора времени.

Я предлагаю следующее: использовать timer1 для измерения частоты вашего ротора. Когда вы получаете свое позиционное прерывание (предположительно за один ход), напишите текущее значение таймера переменной. На каждом из следующих прерываний вычисляют разницу счетчика циклов (правильно учитывайте переполнение).

Теперь у вас есть количество циклов за оборот. теперь я настроил бы второй таймер таким образом, что верхнее значение счетчиков (режим CTC) будет таким же, как ваш измеренный номер цикла, деленный на ваше угловое разрешение вашего дисплея. Таким образом, при переполнении-перерыве вы можете защелкнуть новые данные на светодиодах.

пример:

Предпосылки/предположение:

  • F_CPU (и фактические часы) 16МГц
  • Разрешение дисплея: 200 Углов
  • Скорость ротора: 137Hz
  • таймер 1 предделитель = 4 (в противном случае он переполняется несколько раз за оборот)

С этими значениями вы должны получить значение 29197 Timer-Ticks, что соответствует 116788.3 CPU-Cycles за оборот. Разделенные на 200 линий, у вас есть 583.94 цикла в секцию. Это число слишком велико для 8-разрядного счетчика. Использование prescaler 2 дает 291.97 - слишком большой. Таким образом, вы должны использовать следующий больший предварительный делитель (надеюсь) 4, чтобы получить значение 145.98. Раунд до 146 и -1, так как 0 также подсчитывается. Итак, я бы предложил использовать 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; 
    } 

    } 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^