delayMicroseconds- ошибка?

запускаем очень короткую программу на мега, просто чтобы генерировать тактовый импульс шириной 8 микросекунд на выводе 18 каждые 250 микросекунд — Ближайшие значения задержки , которые я могу получить, — это значение задержкиMicroсекунды(3), а (83) выключено, дает импульс шириной 7,5 микросекунд каждые 249 микросекунд. Есть предложения по лучшему способу?

вот что работает:

int i=0;
int req=18;

void setup(){
Serial.begin(115200);
 DDRD = DDRD | B10000010;
 interrupts();
pinMode(req,OUTPUT);
}

void loop(){
i=1;
digitalWrite(req, HIGH);
delayMicroseconds(3); //дает импульс длительностью 7,5 микросекунд?
digitalWrite(req, LOW);

while(i<83){//дает 249 микросекунд от начала импульса до начала следующего импульса?
 delayMicroseconds(1);
 i=(i+1);}
 }

, 👍0

Обсуждение

Есть ли какая-то конкретная причина, по которой вы не хотите использовать ШИМ?, @Ignacio Vazquez-Abrams

Насколько я понимаю, частота ШИМ «примерно» 490 Гц, мне нужно именно 4000 Гц. есть ли где-нибудь опубликованный список времени обработки инструкций для расчета накладных расходов? Micros даст все это, но не только цикл while, @Tim

Только если вы будете придерживаться того, что дает вам Arduino. Выход за рамки стандартного делает вещи более гибкими., @Ignacio Vazquez-Abrams

Попробуйте библиотеку TimerOne., @Gerben

спасибо, ребята, переосмысление, чтение Micros в различных частях программы может позволить мне сдвигать время по мере необходимости для чтения следующего бита в следующем байте - будет работать только для статических условий, но на данный момент это нормально. Спасибо за предложение ШИМ - да, стандартный, он тактирует очень медленно, но он точен - длительность импульса 1% просто дает тик 8 микросекунд, запуская отправку устройства - чрезвычайно долгое время ожидания не возражало. спасибо за комментарии — все это для меня в новинку, но я вижу огромный потенциал для создания инструментов для ремонта наших компонентов с ЧПУ :), @tc429


2 ответа


1

Если вам не нужен программный таймер ШИМ, как предложено в комментарии, тогда для коротких задержек вам нужно рассчитать, сколько командных циклов необходимо, чтобы сделать такую задержку на основе тактовой/кристаллической частоты, и сделать эту задержку во встроенном ассемблере, чтобы иметь контроль над кодом. Для управления цифровым выводом используйте запись данных в PINx (что эквивалентно xoring PORTx).

Чтобы обеспечить точные 250 мс, вам необходимо компенсировать ошибки из-за округления. Функции задержки/тикания Arduino делают это. Для больших задержек нужен простой планировщик, чтобы не тратить все время процессора на генерацию импульсов.

,

2

Это очень частичный ответ. Я не знаю ваших требований, или ШИМ не может выполнить эту работу и т. д. Я просто хотел отметить, что вы можете создайте импульс длительностью ровно 8 мкс следующим образом:

#include <util/delay.h>
#include <util/atomic.h>

// Импульсный PD3 (цифровой 18 на Mega 2560)
// ровно 8 мкс (128 тактов @ 16 МГц)
static void pulse() {
    ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
        PORTD |= 1 << 3;
        _delay_us(8 - 0.125);
        PORTD &= ~(1 << 3);
    }
}

Функция _delay_us() из avr-libc на самом деле работает с точностью до цикла линейная сборка. 0,125 мкс, которые я вычел, — это время, необходимое для реальный порт пишет: и инструкции sbi, и cbi выполняются по два такта (0,125 мкс), но эту задержку следует учитывать только один раз. digitalWrite() всегда следует избегать в коде, критичном ко времени.

Задержку в 242 мкс между импульсами было бы сложнее создать без ШИМ. Прерывание по таймеру на частоте 4 кГц кажется самым простым вариантом, но это неточно с точностью до цикла.

Изменить: вот трассировка области, показывающая довольно точное время:

трассировка осциллографа

,