ну это понятно, сдвинуть на десять разрядов за два такта совсем никак, хотя бы за десять )))
Меня переклинило потому что я предположил - т.к результат uint_8t то вдруг он просто берет второй байт от long. Ну а то, что в байте не 10 бит, это мой мозг пропустил, в попытке обосновать 2 такта.
Немного переделал, т.к. мне очень надо, чтобы ещё была частота: 0 (без блинка).
Это я пытаюсь сделать индикацию режимов. Задача простая:
Частота: 0 - обычный режим;
Частота №1 - режим настройки №1;
Частота №2 - режим настройки №2.
Переключение режимов вручную (пока не задано новое значение).
Но пока у меня получилось, что блинк работает с нужной частотой примерно 1 сек. Переменная reqfreq почему-то обнуляется в конце void loop() , хотя я пытался сделать её глобальной переменной.
А как переделать Ваш калькулятор для рассчёта параметров для Timer2.
Ну, калькулятор - игрушка, а делать расчёты для всех таймеров позволяет вот такая библиотека. Прелесть её в том, что она ВСЕ вычисления делает на этапе компиляции и в код попадают уже готовые цифири 0 никаких расчётов во время выполнения. Там на гитхабе есть ссылка на обсуждение и подробности на этом форуме.
Сделай всё то же самое, но на одном таймере, я разрешил
На гитхабе в описании к библиотеке написано, что с вопросами и предложениями лучше обращаться на форум arduino.ru. Если на форуме есть своя тема по этой библиотеке, может имеет смысл на гитхабе дать не нее ссылку?
Сама библиотека вызывает двоякое впечатление. С одной стороны мне было интересно и полезно посмотреть в коде, как на практике используются разные приемы программирования. С другой стороны, "поломка" работы millis (ибо кого волнует точность?) отталкивает от желания использовать на практике.
Еще вопрос. В операторе "--" вы разрешаете прерывания перед вызовом fCallback();. Насколько это допустимо? Ведь этот оператор используется внутри обработки прерывания ISR(TIMER0_COMPA_vect).
TCounterDown &operator --(int) {
uint8_t sreg = SREG; // на всякий случай запомним состояние прерываний
cli(); // запрещаем прерывания
if ((isActive()) && (!isEmpty()) && ((--fWorkCount) == 0)) { // если счетчик досчитал до 0
fWorkCount = fInitCount; // перезагружаем рабочий счётчик начальным значением, чтобы считать заново
sei(); // разрешаем прерывания
fCallback(); // и вызываем нашу фунцию обратного вызова
}
SREG = sreg; // восстанавливаем прерывания
return *this;
}
А как переделать Ваш калькулятор для рассчёта параметров для Timer2.
Ну, калькулятор - игрушка, а делать расчёты для всех таймеров позволяет вот такая библиотека. Прелесть её в том, что она ВСЕ вычисления делает на этапе компиляции и в код попадают уже готовые цифири 0 никаких расчётов во время выполнения. Там на гитхабе есть ссылка на обсуждение и подробности на этом форуме.
Вапще-то, правила хорошего тона, в низкоуровневом программировании, требуют разрешать прерывания при заходе в обработчик, за исключением случаев, критичных ко времени обработки. Зачем создавать очередь отложенных прерываний, если оне друг другу не мешают? Но, тут нужна еще культура написания самого обработчика, чтоб он выполнялся как можно быстрее и не делал ничего лишнего. Поэтому, в последних версиях я отказался от колбэков, сработавший таймер просто кладёт в очередь сообщение о событии, а оно потом уже штатно обрабатывается диспеччером в loop(). И никто никаво не тормозит.
Поэтому, в последних версиях я отказался от колбэков, сработавший таймер просто кладёт в очередь сообщение о событии, а оно потом уже штатно обрабатывается диспеччером в loop(). И никто никаво не тормозит.
а делать расчёты для всех таймеров позволяет вот такая библиотека. Прелесть её в том, что она ВСЕ вычисления делает на этапе компиляции и в код попадают уже готовые цифири 0 никаких расчётов во время выполнения. Там на гитхабе есть ссылка на обсуждение и подробности
C:\Install\arduino-1.8.5-windows\arduino-1.8.5\libraries\ConstTimers/Printing.h:10:17: note: no known conversion for argument 2 from 'const char*' to '__int24'
C:\Install\arduino-1.8.5-windows\arduino-1.8.5\libraries\ConstTimers/Printing.h:11:17: note: no known conversion for argument 2 from 'const char*' to '__uint24'
exit status 1
ambiguous overload for 'operator<<' (operand types are 'Print' and 'char')
Спрошу здесь, дабы не плодить темы.
Можно ли заменить micros другой конструкцией в данном примере?
currentmicros = micros(); // текущее время
if (currentmicros - previousmicros >= interval) {
/* мой код*/
}
Это работает на Ардуино, и на других атмегах, но упорно не хочет работать на Attiny13. Кроме того, зачем использовать две переменные unsigned long, когда мне нужно измерять интервалы времени до 200 микросекунд с точностью +-5 микросекунд.
Как я это вижу: при каждой проверке сравниваем значение счётчика с интервалом, и сразу же обнуляем счётчик, и так далее.
attiny-1-series очень далеки от attiny13, это сравнительно новое поколение AVR, для них есть готовое ядро, поддерживающее в том числе и микрос, и на них у меня тоже всё работает. Также работает и на старушке attiny25, а на attiny13 отлично компилируется, но не отрабатывает микрос нормально, пробовал с несколькими разными ядрами (MicroCore и ещё три).
Объясню ещё раз свою задумку: таймер-счетчик Т0 (например) работает с предделителем, обеспечивающим переключение, скажем, каждые 2 микросекунды, прерывание по совпадению обнуляют таймер-счетчик Т0, к примеру, раз в 6 микросекунд, при каждом прерывании МОЙ СЧЁТЧИК (не таймер-счетчик) прибавляет значение. В основном цикле программы я в любой момент могу считать значение МОЕГО СЧЁТЧИКА, а также обнулить его. Таким образом, я смогу считать с дискретностью 6 мкс, что даёт интервалы до 255*6=1530 мкс, что меня вполне устраивает.
На самом деле у меня не получается
1 заставить таймер-счетчик сбрасываться по совпадению менее чем каждые 5 мкс, и цифры не соответствуют даташитам
2 МОЙ СЧЁТЧИК тоже ведёт себя не так как нужно.
Все опыты на Ардуино нано, прошивать каждый раз attiny13 задолбаешься.
Green, это всё у меня есть, на ардуино именно так и работает
int a;
void setup() {
DDRB = 255; // пины 8...13 - выходы
noInterrupts(); // отключаем все прерывания
TCCR0A = (1 << WGM01); // режим таймера CTC
TCCR0B = (1 << CS00); // Тактировать без делителя
OCR0A = 31; // регистр сравнения
TIMSK0|= (1 << OCIE0A); // включаем прерывание по совпадению
TCNT0 = 0; // счетный регистр
interrupts(); // разрешаем все прерывания
}
//ОБРАБОТЧИК ПРЕРЫВАНИЙ ПО ТАЙМЕРУ
ISR (TIMER0_COMPA_vect)
{
TCNT0 = 0; a++;
}
void loop() {
if (a > 10) { // переключаем порт в противоположное состояние
a = 0;
if (PORTB == 0)PORTB = 255;
else PORTB = 0;
}
}
Запускаю таймер-счетчик Т0 без делителя, значит он прибавляет своё значение каждые 62,5 наносекунд. По достижении значения 31 происходит прерывание, переменная а увеличивается на единицу, а таймер-счетчик обнуляется. В основном цикле я проверяю значение переменной а, если больше 10, инвертирую порт. Логическим анализатором проверяю выходы, вижу там меандр с периодом примерно 80 микросекунд. Хотя по моим расчётам должно быть 20 мксек. Но и это не всё. OCR0A можно увеличивать вплоть до 255, период импульсов тоже увеличивается примерно пропорционально. Но при уменьшении OCR0A меньше 31 период не уменьшается, а может даже увеличиваться почти в два раза, это мне не понятно. При уменьшении if (a > 10) до if (a > 1) тоже период уменьшается не сильно. Минимальный период 10 мксек удаётся получить при if (a > 0) и OCR0A= 31, меньше никак.
Это не совсем то, что мне нужно, но я уже вижу немного другое решение с тем же таймер-счетчиком Т0, о результатах напишу.
int a;
void setup() {
DDRB = 255; // пины 8...13 - выходы
noInterrupts(); // отключаем все прерывания
TCCR0A = (1 << WGM01); // режим таймера CTC
TCCR0B = (1<<CS00)|(1<<CS01); // Тактировать с делителем 64
TIMSK0=0; // вЫключаем прерывание по совпадению
interrupts(); // разрешаем все прерывания
}
void loop() {
if (TCNT0 > 100) { // переключаем порт в противоположное состояние
TCNT0 = 0;
if (PORTB == 0)PORTB = 255;
else PORTB = 0;
}
}
Запускаю таймер-счетчик Т0 с делителем 64, он увеличивается каждые 4 мксек, в основном цикле просто сравниваю значение счётчика с заданным, при необходимости таймер-счетчик обнуляю. Можно измерять интервалы до 255*4=1020 мксек с дискретностью 4 мксек, что меня вполне устраивает.
Если предделитель установить 8, дискретность будет 0,5 мксек, измерять интервалы до 255*0,5=120 мксек.
seri0shka, а какая собссно конечная цель, что должно выполняться раз в 100 тактов? Вполне возможно что сама конечная задача не успеет отработаться за 100 тактов, и ситуация if (TCNT0 > 100) никогда не наступит или будет работать абы как. Поэтому принято, работая с переполняющимся регистром проверять соответствующие флаги переполнения в регистре TIFR. Флаг никуда не убежит, и будет терпеливо ждать пока его прочтут.
int main() {
DDRB |= 1<<DDB5; //pin13 -выход
TCCR0A = (1 << WGM01); // режим таймера CTC
TCCR0B = (1<<CS00)|(1<<CS01); // Тактировать с делителем 64
OCR0A=99;// поднять флаг каждые 100 тактов
while(1) {
if (TIFR0&(1<<OCF0A)) { // если было совпадение
TIFR0=(1<<OCF0A); //снять флаг
PORTB^=1<<5; //переключаем порт в противоположное состояние
}
}
}
Вполне возможно что сама конечная задача не успеет отработаться за 100 тактов, и ситуация if (TCNT0 > 100) никогда не наступит
Ситуация if (TCNT0 > 100) никогда не наступит, если задача не успеет отработаться за 255 тактов. А вообще надо подумать, я не знал об этом флаге. Флаг поднимется после 99 такта от нулевого состояния счётчика или от момента снятия флага?
Ещё интересный момент: Все скетчи со счётчиком у меня не хотят работать с написанием
На американском форуме Вы задаете вопрос и Вам дают ответ.
На еврейском форуме Вы задаете вопрос и Вам задают встречный вопрос.
На русском форуме Вы задаете вопрос и Вам долго объясняют почему Вы такой мудак.
Именно поэтому я вопросы на форумах задаю крайне редко.
Ну от. Значить, gcc всёже лучше меня оптимизирует :)
Оптимизация вообще последнее дело. Только в исключительных случаях.
ну это понятно, сдвинуть на десять разрядов за два такта совсем никак, хотя бы за десять )))
ну это понятно, сдвинуть на десять разрядов за два такта совсем никак, хотя бы за десять )))
Меня переклинило потому что я предположил - т.к результат uint_8t то вдруг он просто берет второй байт от long. Ну а то, что в байте не 10 бит, это мой мозг пропустил, в попытке обосновать 2 такта.
Уважаемый dimax !
Пытался сделать блинк из Вашего "Терминального" генератора.
Немного переделал, т.к. мне очень надо, чтобы ещё была частота: 0 (без блинка).
Это я пытаюсь сделать индикацию режимов. Задача простая:
Частота: 0 - обычный режим;
Частота №1 - режим настройки №1;
Частота №2 - режим настройки №2.
Переключение режимов вручную (пока не задано новое значение).
Но пока у меня получилось, что блинк работает с нужной частотой примерно 1 сек. Переменная reqfreq почему-то обнуляется в конце void loop() , хотя я пытался сделать её глобальной переменной.
Подскажите, что не так!
volatile-то вам зачем? Serial.parseInt() у вас возвращает ноль не только если введена строка "0", но и если мусор считал.
Переменная reqfreq почему-то обнуляется в конце void loop() , хотя я пытался сделать её глобальной переменной. Подскажите, что не так!
По виду всё так. Наверно из терминалки прилетает ноль. Если в ардуиновском мониторе смотрите, то выберете в настройке "Нет конца строки"
там что попало прилетает, функция parseint просто такая. замена на readbytes плюс sscanf решает вопрос. проверил.
в настройке "Нет конца строки"
Помогло, спасибо!
там что попало прилетает, функция parseint просто такая. замена на readbytes плюс sscanf решает вопрос. проверил.
readbytes плюс sscanf - можно по-подробней. В справочниках не нашёл.
я же прицепил исправленный скетч в ответе на ваш вопрос. сравните со своим, там лишь пара строк отличается.
исправленный скетч в ответе на ваш вопрос. сравните со своим, там лишь пара строк отличается.
Я протестил: работает, спасибо!
Ну и вот он мой вариант Блинка:
Спасибо, venus !
Спасибо, dimax !
Спасибо, ЕвгенийП !
Евгений, в качестве продолжения темы.
А как переделать Ваш калькулятор для рассчёта параметров для Timer2.
Есть желание сделать на одной Нане два Блинка с разными регулируемыми частотами.
Пока на втором Таймере получилась пищалка.
с Наступающим!
Сделай всё то же самое, но на одном таймере, я разрешил
А как переделать Ваш калькулятор для рассчёта параметров для Timer2.
Ну, калькулятор - игрушка, а делать расчёты для всех таймеров позволяет вот такая библиотека. Прелесть её в том, что она ВСЕ вычисления делает на этапе компиляции и в код попадают уже готовые цифири 0 никаких расчётов во время выполнения. Там на гитхабе есть ссылка на обсуждение и подробности на этом форуме.
Сделай всё то же самое, но на одном таймере, я разрешил
На гитхабе в описании к библиотеке написано, что с вопросами и предложениями лучше обращаться на форум arduino.ru. Если на форуме есть своя тема по этой библиотеке, может имеет смысл на гитхабе дать не нее ссылку?
Сама библиотека вызывает двоякое впечатление. С одной стороны мне было интересно и полезно посмотреть в коде, как на практике используются разные приемы программирования. С другой стороны, "поломка" работы millis (ибо кого волнует точность?) отталкивает от желания использовать на практике.
Еще вопрос. В операторе "--" вы разрешаете прерывания перед вызовом fCallback();. Насколько это допустимо? Ведь этот оператор используется внутри обработки прерывания ISR(TIMER0_COMPA_vect).
А как переделать Ваш калькулятор для рассчёта параметров для Timer2.
Ну, калькулятор - игрушка, а делать расчёты для всех таймеров позволяет вот такая библиотека. Прелесть её в том, что она ВСЕ вычисления делает на этапе компиляции и в код попадают уже готовые цифири 0 никаких расчётов во время выполнения. Там на гитхабе есть ссылка на обсуждение и подробности на этом форуме.
а Важгад не к этой библиотеке добавляли?
Так я ж и не настаиваю. :)
В последней версии millis() не врёт, используется такая конструкция
OCR0A += TIMER_ONE_MS;
вместо
TCNT0 = 0xFF;
А я вообще сторонник не накрученности. Чем проще, чем понятнее, тем лучше. Или нет?
Вапще-то, правила хорошего тона, в низкоуровневом программировании, требуют разрешать прерывания при заходе в обработчик, за исключением случаев, критичных ко времени обработки. Зачем создавать очередь отложенных прерываний, если оне друг другу не мешают? Но, тут нужна еще культура написания самого обработчика, чтоб он выполнялся как можно быстрее и не делал ничего лишнего. Поэтому, в последних версиях я отказался от колбэков, сработавший таймер просто кладёт в очередь сообщение о событии, а оно потом уже штатно обрабатывается диспеччером в loop(). И никто никаво не тормозит.
В последней версии millis() не врёт, используется такая конструкция
OCR0A += TIMER_ONE_MS;
вместо
TCNT0 = 0xFF;
Может мы о разных библиотека говорим?
Я говорю о той, на которую вы дали ссылку
https://github.com/DetSimen/Arduino_TimerList/blob/master/TimerList.cpp
В ней TCNT0 = 0xFF;
Поэтому, в последних версиях я отказался от колбэков, сработавший таймер просто кладёт в очередь сообщение о событии, а оно потом уже штатно обрабатывается диспеччером в loop(). И никто никаво не тормозит.
+100500!
Может мы о разных библиотека говорим?
Я говорю о той, на которую вы дали ссылку
https://github.com/DetSimen/Arduino_TimerList/blob/master/TimerList.cpp
В ней TCNT0 = 0xFF;
На гитхабе старая. Но, для несложных задач падёт, типа 2-х независимых блинков, как нужно было вопрошающему. Я поправлю, как руки дойдут. :)
а делать расчёты для всех таймеров позволяет вот такая библиотека. Прелесть её в том, что она ВСЕ вычисления делает на этапе компиляции и в код попадают уже готовые цифири 0 никаких расчётов во время выполнения. Там на гитхабе есть ссылка на обсуждение и подробности
ConstTimersComplexTest:
ConstTimersPartialTest:
Функционирует. Но, как я понял это для Timer1 ?
Но не все результаты совпадают с выданными калькулятором.
Функционирует.
Т.е. с int24 разобрались? Надо,, блин, убрать её оттуда, это Ворота выпендрился.
Но, как я понял это для Timer1 ?
Блин, ну там же в начале файла библиотеки полная документация, все написано!
Это для любого таймера, номер таймера задаётся в первом параметре "timerTicksByFrequency(1, ..." и "prescalerBitsByFrequency(1, ..."
Но не все результаты совпадают с выданными калькулятором.
Не обязано.
Спрошу здесь, дабы не плодить темы.
Можно ли заменить micros другой конструкцией в данном примере?
Это работает на Ардуино, и на других атмегах, но упорно не хочет работать на Attiny13. Кроме того, зачем использовать две переменные unsigned long, когда мне нужно измерять интервалы времени до 200 микросекунд с точностью +-5 микросекунд.
Как я это вижу: при каждой проверке сравниваем значение счётчика с интервалом, и сразу же обнуляем счётчик, и так далее.
Мучаюсь уже сутки, но не получаю ожидаемого.
Как я это вижу: при каждой проверке сравниваем значение счётчика с интервалом, и сразу же обнуляем счётчик, и так далее.
это вы микрос хотите обнулять? - не выйдет, обходитесь без обнуления
Нет, не микрос обнулять. Можно ли обойтись без микрос вообще?
https://www.avrfreaks.net/forum/millis-and-micros-attiny-1-series
Подходит?
attiny-1-series очень далеки от attiny13, это сравнительно новое поколение AVR, для них есть готовое ядро, поддерживающее в том числе и микрос, и на них у меня тоже всё работает. Также работает и на старушке attiny25, а на attiny13 отлично компилируется, но не отрабатывает микрос нормально, пробовал с несколькими разными ядрами (MicroCore и ещё три).
Объясню ещё раз свою задумку: таймер-счетчик Т0 (например) работает с предделителем, обеспечивающим переключение, скажем, каждые 2 микросекунды, прерывание по совпадению обнуляют таймер-счетчик Т0, к примеру, раз в 6 микросекунд, при каждом прерывании МОЙ СЧЁТЧИК (не таймер-счетчик) прибавляет значение. В основном цикле программы я в любой момент могу считать значение МОЕГО СЧЁТЧИКА, а также обнулить его. Таким образом, я смогу считать с дискретностью 6 мкс, что даёт интервалы до 255*6=1530 мкс, что меня вполне устраивает.
На самом деле у меня не получается
1 заставить таймер-счетчик сбрасываться по совпадению менее чем каждые 5 мкс, и цифры не соответствуют даташитам
2 МОЙ СЧЁТЧИК тоже ведёт себя не так как нужно.
Все опыты на Ардуино нано, прошивать каждый раз attiny13 задолбаешься.
Green, это всё у меня есть, на ардуино именно так и работает
Каждые 6 мкс по совпадению... Боюсь, не успеете.
Нужна полная схема и софт. Тогда только возможна помощь.
Нужна полная схема и софт. Тогда только возможна помощь.
и лучше это сделать отдельной темой в разделе Программирования. Думаю что в теме для начинающих про миллис этот вопрос явный оффтоп
Вот привожу испытательный код
Запускаю таймер-счетчик Т0 без делителя, значит он прибавляет своё значение каждые 62,5 наносекунд. По достижении значения 31 происходит прерывание, переменная а увеличивается на единицу, а таймер-счетчик обнуляется. В основном цикле я проверяю значение переменной а, если больше 10, инвертирую порт. Логическим анализатором проверяю выходы, вижу там меандр с периодом примерно 80 микросекунд. Хотя по моим расчётам должно быть 20 мксек. Но и это не всё. OCR0A можно увеличивать вплоть до 255, период импульсов тоже увеличивается примерно пропорционально. Но при уменьшении OCR0A меньше 31 период не уменьшается, а может даже увеличиваться почти в два раза, это мне не понятно. При уменьшении if (a > 10) до if (a > 1) тоже период уменьшается не сильно. Минимальный период 10 мксек удаётся получить при if (a > 0) и OCR0A= 31, меньше никак.
Это не совсем то, что мне нужно, но я уже вижу немного другое решение с тем же таймер-счетчиком Т0, о результатах напишу.
Вот то, что я применил в итоге.
Запускаю таймер-счетчик Т0 с делителем 64, он увеличивается каждые 4 мксек, в основном цикле просто сравниваю значение счётчика с заданным, при необходимости таймер-счетчик обнуляю. Можно измерять интервалы до 255*4=1020 мксек с дискретностью 4 мксек, что меня вполне устраивает.
Если предделитель установить 8, дискретность будет 0,5 мксек, измерять интервалы до 255*0,5=120 мксек.
seri0shka, а какая собссно конечная цель, что должно выполняться раз в 100 тактов? Вполне возможно что сама конечная задача не успеет отработаться за 100 тактов, и ситуация if (TCNT0 > 100) никогда не наступит или будет работать абы как. Поэтому принято, работая с переполняющимся регистром проверять соответствующие флаги переполнения в регистре TIFR. Флаг никуда не убежит, и будет терпеливо ждать пока его прочтут.
Ситуация if (TCNT0 > 100) никогда не наступит, если задача не успеет отработаться за 255 тактов. А вообще надо подумать, я не знал об этом флаге. Флаг поднимется после 99 такта от нулевого состояния счётчика или от момента снятия флага?
Ещё интересный момент: Все скетчи со счётчиком у меня не хотят работать с написанием
но работают с написанием
Ещё интересный момент: Все скетчи со счётчиком у меня не хотят работать с написанием
но работают с написанием
Действительно, интересный момент.
Помнится, у Ваенги тоже подобный был :-)
Ага, похоже абсент... Сначала миллис - "а, это я знаю", затем 6 мкс по совпадению, затем main()... Ужос!(
На американском форуме Вы задаете вопрос и Вам дают ответ.
На еврейском форуме Вы задаете вопрос и Вам задают встречный вопрос.
На русском форуме Вы задаете вопрос и Вам долго объясняют почему Вы такой мудак.
Именно поэтому я вопросы на форумах задаю крайне редко.
Ты бы для начала свою тему создал, нафиг чужую засирать?
...Вам долго объясняют почему Вы такой мудак.
Именно поэтому я вопросы на форумах задаю крайне редко.
Ну, если Вы и без форума это знаете, зачем тогда вообще вопросы задавать?
На американском форуме Вы задаете вопрос и Вам дают ответ.
Это точно, и у нас в песочнице есть пример такого ответа.