Предыстория. Есть индуктивный датчик который считывает скорость первичного вала кпп. Т.к. шестерня с которой эта скорость считывается изменена, возникла потребность преобразовать сигнал одной частоты в сигнал немного другой частоты. Блочно программа разделена на 2 части: генератор сигнала на таймере 1, и дешифратор входящего сигнала на компараторе. Входящий сигнал ограничивается стабилитроном по верхнему срезу и шотки по нижнему (т.к. индуктивный датчик очень даже может выдать переменное напряжение в 7-8В). Выход управляет драйвером шаговика, который в данном сетапе работает как генератор модифицированной синусоиды.
Имеется следующий код (не обращайте внимание на некоторые рудименты, они ни на что не влияют и компилятором отсекаются. Просто переписывал его уже раз 10):
Этот код отлично работает, но есть нюанс. Если коробка перестаёт вращаться, то эбу ожидает остановки импульсов, а как видно, генератор на таймере в этой программе будет долбить последнюю прилетевшую с компаратора частоту. Для исправления этого я решил в самый конец лупа добавить строчку:
С точки зрения эбу это обороты на которые уже можно не обращать внимания и кпп для него как бы уже остановилась. Но тут вылезает странность, если залить такой код:
то на выходе получаем только импульсы с с периодом 65500, не зависимо от того, что подаём на вход.
Более того, если вставить тупо такие строчки:
то период импульсов по таймеру 1 становится другим!
Если вставить любое другое условие не содержащие millis/micros то всё работает как часики.
И собственно главный вопрос, почему вызов millis/micros в лупе влияет на то, на что по идее вообще никак влиять не должен?
Имеется следующий код (не обращайте внимание на некоторые рудименты, они ни на что не влияют и компилятором отсекаются. Просто переписывал его уже раз 10):
C++:
#include <directADC.h>
#include <GyverTimers.h>
void setup() {
pinMode(9, OUTPUT);
pinMode(A0, INPUT);
TCCR1A = 0;
TCCR1B = 0;
OCR1A = 65500; // первичный период счетчика
TCCR1B |= (1 << WGM12);//Сброс по совпадению
TCCR1B |= (1 << CS10);//Предделитель 1
digitalWrite(9, !digitalRead(9));
TIMSK1 |= (1 << OCIE1A);
ADC_disable(); // если используем мультиплексор для компаратора - обяательно выключаем ацп
ACOMP_attachInterrupt(func, FALLING_TRIGGER);
}
volatile uint32_t tmr0;
uint32_t tmr1, tmr3, tmr4;
uint16_t sum;
volatile bool flag = false;
bool flag1;
ISR(TIMER1_COMPA_vect)
{
PINB |= bit(1);
}
void func() {
tmr0 = micros();
flag = true;
}
uint32_t tmr2;
void loop() {
static byte var;
if (flag) {
sum = (((tmr0 - tmr1) * 562) >> 8) - 1;
tmr1 = tmr0;
tmr3 = sum + tmr3;
var = var + 1;
flag = false;
}
if (var >= 255) {
if (tmr3 >= 864359)OCR1A = ((tmr3 >> 8))+335;// корректур холостого хода
else if (tmr3 >= 432180 && tmr3 < 864359) OCR1A = (tmr3 >> 8); // после 1000 начинаем ступенчато снижать период
else if (tmr3 >= 288120 && tmr3 < 432180) OCR1A = (tmr3 >> 8) -25;
else if (tmr3 < 288120) OCR1A = (tmr3 >> 8)-20;
tmr3 = 0;
var = 0;
}
}
C++:
if (micros()- tmr0 >= 4096) OCR1A = 65500;
C++:
#include <directADC.h>
#include <GyverTimers.h>
void setup() {
pinMode(9, OUTPUT);
pinMode(A0, INPUT);
TCCR1A = 0;
TCCR1B = 0;
OCR1A = 65500; // первичный период счетчика
TCCR1B |= (1 << WGM12);//Сброс по совпадению
TCCR1B |= (1 << CS10);//Предделитель 1
digitalWrite(9, !digitalRead(9));
TIMSK1 |= (1 << OCIE1A);
ADC_disable(); // если используем мультиплексор для компаратора - обяательно выключаем ацп
ACOMP_attachInterrupt(func, FALLING_TRIGGER);
}
volatile uint32_t tmr0;
uint32_t tmr1, tmr3, tmr4;
uint16_t sum;
volatile bool flag = false;
bool flag1;
ISR(TIMER1_COMPA_vect)
{
PINB |= bit(1);
}
void func() {
tmr0 = micros();
flag = true;
}
uint32_t tmr2;
void loop() {
static byte var;
if (flag) {
sum = (((tmr0 - tmr1) * 562) >> 8) - 1;
tmr1 = tmr0;
tmr3 = sum + tmr3;
var = var + 1;
flag = false;
}
if (var >= 255) {
if (tmr3 >= 864359)OCR1A = ((tmr3 >> 8))+335;// корректур холостого хода
else if (tmr3 >= 432180 && tmr3 < 864359) OCR1A = (tmr3 >> 8); // после 1000 начинаем ступенчато снижать период
else if (tmr3 >= 288120 && tmr3 < 432180) OCR1A = (tmr3 >> 8) -25;
else if (tmr3 < 288120) OCR1A = (tmr3 >> 8)-20;
tmr3 = 0;
var = 0;
}
if (micros()- tmr0 >= 4096) OCR1A = 65500;
}
Более того, если вставить тупо такие строчки:
C++:
volatile uint32_t tmp; //volatile чтобы компилятор не оптимизировал и не удалил нафиг
if (micros()- tmp >= 1) tmp=tmp
Если вставить любое другое условие не содержащие millis/micros то всё работает как часики.
И собственно главный вопрос, почему вызов millis/micros в лупе влияет на то, на что по идее вообще никак влиять не должен?