Пропуск такта при формировании сигнала (меандр)

Олег_Б
Offline
Зарегистрирован: 05.06.2014

Здравствуйте.

При формировании на выходе простого сигнала, например как демонстрационная программа "Blink", примерно каждую секунду или даже чаще контролер пропускает такт, что естественно ведёт с фазовому сдвигу сигнала. Я использую задержку в микросекундах, программа вроде как примитивная... То ли это загрузчик периодически обнуляет контролер, то ли ещё чего, но осциллограмма примерно такая:

П_П_П_П_ПП_П_П_П_П, где двойное П - просто единица два такта, потом опять продолжает работать. 

Программа:

/*****    Делаю генерацию на 12 выводе    *****/
 
int Ped = 12;
 
void setup()
{                
  pinMode(Ped, OUTPUT);
}
 
void loop()
{
  digitalWrite(Ped, HIGH); 
  delayMicroseconds(2);
  
  digitalWrite(Ped, LOW);
  delayMicroseconds(2);
}
 
С чем связан перезапуск?
 
 
toly
Offline
Зарегистрирован: 17.05.2014

Возможно связано с прерываниями...

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Любые задержки с помощью функций типа delay... как бы то ни было дают примерную задержку. Если нужны точные задержки/формирование импульсов, нужно использовать таймеры. Тогда никакие прерывания или еще что то не будет мешать формированию импульсов - всё аппаратно.

delayMicroseconds особая функция, которая не использует таймер для формирования задержки, потому ТОЛЬКО для этого скетча можно попробовать запретить прерывания и проверить, импульсы должны быть ровными. Но это "костыль", "затычка".

 

Олег_Б
Offline
Зарегистрирован: 05.06.2014

Здесь получается не примерная задержка, хотя длительность импульсов дребезжит примерно до 5 процентов по времени, в среднем, а просто интересно, почему пропускает целую команду. На социллографе выглядит, что команда на установку вывода в ноль периодически пропускается. 

Или в команде void setup() есть ещё какие-то установки, которые идут автоматом, ну вроде запущеного сторожевого таймера?

Дополнение: пропускаются как переключение в единицу, так и в ноль. При этом на других выводах процессора изменений нет. Какое-то прерывание, записанное "подпольно" ))).

Кстати, период следования этих пропусков переключения примерно 1,1 миллисекунды. 

Arduino UNO

Спасибо. 

Олег_Б
Offline
Зарегистрирован: 05.06.2014

Чуть по-другому напишу.

Каждую миллисекунду Ардуин игнорирует какую-нибудь команду. В данном случае каждую миллисекунду процессор делает что-то, что не написано в скетче, то есть не смотря на всю правильность кода, процессор сделает операцию, кода которой не существует.  Если программа будет больше в несколько раз, можно бесконечно перебирать код и ничего не найти?

Или достаточно описать состояние всех прерываний, не оставлять их на откуп судьбе?

tmr
Offline
Зарегистрирован: 19.05.2014

Там программа много чего делает, что в скетче не написано. Я так поступаю:
...
void loop(){
noInterrupts();
while(1){
//do something
}

Олег_Б
Offline
Зарегистрирован: 05.06.2014

В таком виде всё стало работать красиво и правильно, частота получилась 102,6 килогерца, дребезга фронтов нет, пропуска команд нет.

Спасибо за науку!

 

/*****    Делаю генерацию на 12 выводе    *****/
 
int Ped = 12;
 
void setup() {                
   pinMode(Ped, OUTPUT);
}
 
void loop(){
noInterrupts();
while(1){
 
    digitalWrite(Ped, HIGH); 
    delayMicroseconds(1);
  
    digitalWrite(Ped, LOW);
    delayMicroseconds(1);
  }
}

 

 

tmr
Offline
Зарегистрирован: 19.05.2014

Можно значительно ускориться если не использовать digitalWrite, а записывать биты непосредственно в порт PORTx = B11111111; и если время у счетчика TCNTx брать

Олег_Б
Offline
Зарегистрирован: 05.06.2014

Был интересен именно этот простейший вариант, светодиодом поморгал раз в секунду - хорошо!

Теперь всё то же самое, только моргаем чаще, а оно воно как вышло. Но я только учусь. )))