Почему вы настаиваете на том, чтобы начинать свой заголовок с тега, когда я сделал это совершенно английским вопросом?
Стивенвх
4
Извиняюсь, Стивен, я искренне думал (и думаю), что это хороший способ выразить вопрос кратко и ясно. Об этом было много дискуссий, и в некоторых случаях Джефф соглашался, что это хороший способ спросить. Обсуждение здесь; тепловые карты - это то, что убедило меня в том, что для такого стиля вопросов стоит подчеркнуть операционную среду. meta.stackexchange.com/questions/10647/writing-good-titles/… Но, из уважения к вашим превосходным ответам, я был бы рад изменить его обратно, если вы считаете, что это лучше.
Марк Харрисон
Можно ли использовать его для функции pulsein ()? Мне нужно измерить длину импульса с разрешением менее 1 мксек.
Это место зарезервировано для ответов на вопрос сверху. Если у вас есть что спросить, начните свой вопрос.
Олин Латроп
Ответы:
9
Да, в зависимости от базовой частоты вашего Arduino. Например, здесь приведены входные частоты и периоды счетчика таймера после предварительного масштабирования для счетчика-таймера 2 ATMega2560 и базовая тактовая частота 16 МГц. Таймер имеет встроенные опции значений «prescaler», которые определяют частоту / период, показанные в этой таблице:
TCCR2B bits 2-0PrescalerFreq[KHz],Period[usec] after prescale
0x0(TC stopped)----0x1116000.0.06250x282000.0.5000x332500.2.0000x464250.4.0000x5128125.8.0000x625662.516.0000x7102415.62564.000
Для лучшего разрешения по времени вы используете значение TCNT2. Существует встроенный счетчик, который идет от 0 до 255, потому что таймер 8 бит. Когда счетчик достигает значения, назначенного TCNT2, он запускает прерывание. Это прерывание называется TIMER2_OVF_vect.
Вы можете заставить таймер работать на полных 16 МГц (62,5 нсек), хотя это намного быстрее, чем вам нужно; 2 МГц с начальным счетом (255-2) даст вам частоту прерываний 1 МГц. Разделите это на 2 в вашем ISR:
externuint32_tMicroSecClock=0;
ISR(TIMER2_OVF_vect){// this is a built in function that gets called when the timer gets to the overflow counter numberstatic uint_8 count;// interrupt counterif((++count &0x01)==0)// bump the interrupt counter++MicroSecClock;// & count uSec every other time.
digitalWrite(53,toggle);// pin 53 is arbitrary
TCNT2 =253;// this tells the timer when to trigger the interrupt. when the counter gets to 253 out of 255(because the timer is 8 bit) the timmer will trigger an interrupt
TIFR2 =0x00;// clear timer overflow flag};
Таблица данных для вашего MCU является основным ресурсом; эта статья даст вам (и дал мне!) хороший старт.
Марк, я решил написать новый набор функций, основанный на таймере Arduino Atmega328 Timer2 и использующий прерывания переполнения, чтобы получить точность до 0.5us. Мой код доступен для скачивания и использования здесь:
Вот краткое описание: «Я написал« libary », чтобы получить точность 0.5us для функции замены« micros () », чтобы я мог получать воспроизводимые результаты, читая сигнал PWM или PPM, с точностью до 1us. Я искал все вокруг Интернет и не мог найти что-то сопоставимое (или это было легко использовать, и поддерживал способность Arduino писать сигналы ШИМ через Servo Libary), поэтому я думаю, что это мой первый крупный вклад в мир Arduino и радиоуправления ».
Если допустимо снижение до уровня AVR (как вы упомянули в своем вопросе), вы можете установить таймер и даже получить отметки от часов AVR.
Вам нужно обратиться к таблице данных вашего AVR, потому что она отличается в разных ATMegas и ATTinys. Но процедура всегда одна и та же. Что вам нужно сделать, это:
решить, какой прескалер использовать (например, установить его на 1, т. е. не использовать предварительное масштабирование, если требуется фактическая тактовая частота процессора), см. документацию TCCR
установить прерывание по переполнению таймера, обработчик прерываний и активировать прерывания глобально
активировать таймер в регистре управления таймером / счетчиком TCCR
Таким способом можно получить точные отметки из регистра таймера, однако вам нужно подсчитывать переполнения вручную. Это максимально точно с точки зрения технологии.
Вот пример кода для устаревшего AT90S2313, но он дает вам хорошие подсказки, что делать в основном:
/* uC: AT90S2313 */#include<avr/io.h>#include<avr/interrupt.h>int main(void){// set up timer 0
TCCR0 =(1<<CS01);// Prescaler 8// enable overflow interrupt
TIMSK |=(1<<TOIE0);// activate interrupts
sei();while(1){/* Do whatever you like */}}
ISR (TIMER0_OVF_vect){/*
This gets called everytime there in an overflow in the timer register
*/}
Спасибо, FeeJai. Могу ли я установить эти прерывания в контексте эскиза Arduino?
Марк Харрисон
1
Я не знаком с фреймворком Arduino. Но если он не настроит все таймеры внутри, вы, конечно, можете. В противном случае вы все равно можете прочитать регистры таймера и рассчитать сами.
FeeJai
Да, вы программируете на полном C ++ в Arduino и можете использовать все регистры и символы, такие как TIMSKи TOIE0т. Д. (Скопируйте настройку таймера из таблицы данных atmega328p). Похоже, вы не можете использовать макрос ISR (), вместо этого используйте arduino.cc/en/Reference/AttachInterrupt .
Ответы:
Да, в зависимости от базовой частоты вашего Arduino. Например, здесь приведены входные частоты и периоды счетчика таймера после предварительного масштабирования для счетчика-таймера 2 ATMega2560 и базовая тактовая частота 16 МГц. Таймер имеет встроенные опции значений «prescaler», которые определяют частоту / период, показанные в этой таблице:
Для лучшего разрешения по времени вы используете значение TCNT2. Существует встроенный счетчик, который идет от 0 до 255, потому что таймер 8 бит. Когда счетчик достигает значения, назначенного TCNT2, он запускает прерывание. Это прерывание называется TIMER2_OVF_vect.
учитывая эту информацию, результирующая частота прерываний будет: 16 МГц / (предварительное масштабирование * (255 - TCNT2))
Вы можете заставить таймер работать на полных 16 МГц (62,5 нсек), хотя это намного быстрее, чем вам нужно; 2 МГц с начальным счетом (255-2) даст вам частоту прерываний 1 МГц. Разделите это на 2 в вашем ISR:
Таблица данных для вашего MCU является основным ресурсом; эта статья даст вам (и дал мне!) хороший старт.
источник
Марк, я решил написать новый набор функций, основанный на таймере Arduino Atmega328 Timer2 и использующий прерывания переполнения, чтобы получить точность до 0.5us. Мой код доступен для скачивания и использования здесь:
http://electricrcaircraftguy.blogspot.com/2014/02/Timer2Counter-more-precise-Arduino-micros-function.html
Вот краткое описание: «Я написал« libary », чтобы получить точность 0.5us для функции замены« micros () », чтобы я мог получать воспроизводимые результаты, читая сигнал PWM или PPM, с точностью до 1us. Я искал все вокруг Интернет и не мог найти что-то сопоставимое (или это было легко использовать, и поддерживал способность Arduino писать сигналы ШИМ через Servo Libary), поэтому я думаю, что это мой первый крупный вклад в мир Arduino и радиоуправления ».
источник
Если допустимо снижение до уровня AVR (как вы упомянули в своем вопросе), вы можете установить таймер и даже получить отметки от часов AVR.
Вам нужно обратиться к таблице данных вашего AVR, потому что она отличается в разных ATMegas и ATTinys. Но процедура всегда одна и та же. Что вам нужно сделать, это:
TCCR
Таким способом можно получить точные отметки из регистра таймера, однако вам нужно подсчитывать переполнения вручную. Это максимально точно с точки зрения технологии.
Вот пример кода для устаревшего AT90S2313, но он дает вам хорошие подсказки, что делать в основном:
источник
TIMSK
иTOIE0
т. Д. (Скопируйте настройку таймера из таблицы данных atmega328p). Похоже, вы не можете использовать макрос ISR (), вместо этого используйте arduino.cc/en/Reference/AttachInterrupt .