ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Четверг
25 апреля
426435 Топик полностью
zeleny (22.07.2013 16:33 - 16:59, просмотров: 298) ответил Юрий_СВ на Не могу найти дырку в своём простом алгоритме. А желательно сделать это за пару часов. Суть: измерение оборотов, программно(старшее слово)-аппаратный(младшее слово) захват значения таймера .
не совсем понятна логика вашего прерывания. Вот мой вариант (под Ардуино-Мега8), пока никаких заскоков не замечено:  volatile uint16_t rpm; //об/мин volatile uint8_t rpm_rdy; //флаг готовности счетчика (0-не готов, 1-готов, 2-переполнение (стоп/или медленные обороты) volatile uint32_t rpm_cnt; //значение счетчика volatile uint16_t rpm_high_cnt; //старшая половина счетчика //настройка void rpm_setup() { //вывод ICR1 - на вход pinMode(8, INPUT_PULLUP); digitalWrite(8, HIGH); //запуск таймера 1, разрешение прерываний TCCR1A = 0; TCCR1B = (1<<ICNC1)|(1<<CS10); TIMSK |= (1<<TICIE1)|(1<<TOIE1); } //осн.программа void main() { while (1) { //гл.цикл if (rpm_rdy) { //готовность счетчика ? if (rpm_rdy == 1) { //==1 - расчет RPM + фильтр rpm = (rpm + (F_CPU * 60UL) / rpm_cnt) >> 1; } else if (rpm_rdy == 2) { //==2 - переполнение, обнуление RPM rpm = 0; rpm_cnt = 0; } rpm_rdy = 0; //сброс флага } }} //прерывание захвата ISR(TIMER1_CAPT_vect) { if (!rpm_rdy) { //флаг сброшен ? rpm_cnt = ((uint32_t)rpm_high_cnt << 16) | ICR1; //рассчитать значение счетчика из двух половин rpm_rdy = 1; //установить флаг } TCNT1 = rpm_high_cnt = 0; //сбросить таймер/счетчик } //прерывание переполнения - инкремент старшей половины счетчика ISR(TIMER1_OVF_vect) { if (rpm_high_cnt < 1000) { //ограничить максимум rpm_high_cnt++; if (rpm_high_cnt == 1000) { //переполнение - выставить флаг переполнения rpm_rdy = 2; } } }