Как увеличить переключение распиновки?
Рассмотрите этот код:
void loop() {
digitalWrite(pinTest, HIGH);
digitalWrite(pinTest, LOW);
}
На Arduino Mega 2560, работающем на частоте 16 МГц (=0,06 мкс), я ожидаю, что ширина импульса будет где-то около 0,1 мкс.
Однако при измерении с помощью осциллографа я получаю около 4 мкс по высоте и 5-6 мкс по низкой. Я понимаю, что выполнение кода digitalWrite может занять несколько циклов, но это кажется довольно большим.
Как объясняется эта разница?
2 ответа
Лучший ответ:
Вам не нужно проходить весь путь сборки, чтобы получить
скорость. Вы можете сделать прямой доступ к порту из файла .ino:
void setup() {
DDRA |= _BV(PA0); // контакт 22 = PA0 как выход
for (;;) {
PINA |= _BV(PA0); // переключить PA0
}
}
void loop(){}
Это компилируется во что-то, что почти эквивалентно вашей сборке
код. На самом деле он немного быстрее, так как использует rjmp вместо
более медленная инструкция jmp.
ОБНОВЛЕНИЕ: несколько примечаний
Как указано в комментарии timemage, вы можете сохранить еще один ЦП. цикла, написав
PINA =вместоPINA |=.В этом коде, как и в двух ваших примерах, каждый раз возникает сбой. 1024 мкс. Это вызвано использованием периодического прерывания таймера. ядром Arduino для хронометража (
millis(),micros()иdelay()). Вы можете избежать сбоя, отключив прерывания перед входит в узкую петлю. В качестве альтернативы, если вы не используете ядра Arduino, вы можете определить функцию с именемmain()вместоsetup()иloop(): это полностью удалит Инициализация ядра Arduino для вашей скомпилированной программы.arduino-cliпомогает избавить вас от сложности Arduino. система сборки (автоматическая установка ядер и библиотек, библиотеки в нескольких местах, которые зависят от используемого вами ядра...). Если вы не используете ядро Arduino, отarduino-cliмало толку: очень простой Makefile, который вызываетavr-gccиavrdude— это все, что вам нужно потребность в базовой разработке AVR.
PINA =, а не PINA |=. Я не уверен на 100%, что произойдет с SBI, который, по-видимому, генерирует PINA |= expr; но это если на самом деле ведет себя как PINA = PINA | expr он пытается частично переключать контакты порта на основе текущего считанного значения порта. В любом случае, PINA = достаточно, и в результате генерируется OUT, который равен 1 циклу по сравнению с двумя циклами SBI. Это арахис. Но тогда они идут на скорость., @timemage
@timemage: Вы правы, PINA = здесь быстрее. sbi безопасен, так как это настоящий побитовый доступ, а не побайтовое чтение-модификация-запись. PINA |=, с другой стороны, безопасен только тогда, когда вы знаете, что PINA находится в битовой адресуемой части пространства ввода-вывода., @Edgar Bonet
Я подозревал, что насчет sbi просто потому, что в противном случае он был бы гораздо менее полезен. Ре. Пространство ввода-вывода: Да, я не расшифровал это, но PINH/PINJ/PINK/PINL (любопытно, что нет PINI; возможно, это слишком похоже на 1) все результаты lds ,ори,сц, @timemage
Я исправил это, используя ассемблерный код для запуска программы. Поскольку я использую Linux, я не мог использовать Atmel Studio, но вы можете легко использовать сборку AVR с arduino-cli.
Сделайте файл .ino следующим образом:
extern "C" void myAssemblyMain();
void setup() {
myAssemblyMain();
}
void loop() {
}
затем добавьте файл pulse.S с ассемблерным кодом:
#define __SFR_OFFSET 0
#include "avr/io.h"
.global myAssemblyMain
myAssemblyMain:
sbi DDRA, 0 ; Set PA0 as output
blink:
sbi PINA, 0 ; Toggle PINB
jmp blink
Используя этот код, я получаю импульс ~ 400 нс. Этого более чем достаточно для моих нужд.
вы можете сделать то же самое с Arduino IDE. нет необходимости в CLI, @Juraj
пожалуйста, обновите свой вопрос, потому что это не отвечает на вопрос, который вы задали, @jsotola
@jsotola согласился, что не ответил на точный вопрос, но дает другой способ достижения той же цели., @Bart Friederichs
@Juraj спасибо, я проверю это. Но я много работаю с Visual Studio Code, поэтому предпочтительнее оставаться в одном и том же инструменте., @Bart Friederichs
- Отправка цифрового сигнала с одного Arduino на другой для запуска события
- Nano: все цифровые контакты ничего не выводят
- Цифровые выходные контакты Arduino Micro с плавающим / высоким Z
- Быстрый цифровой ввод-вывод
- Есть ли способ воспроизводить звуки с Arduino без использования звукового экрана?
- В чем разница между analogWrite и digitalWrite?
- Что означает “LSB на градус в секунду” (LSB per degree per second)?
- Как преобразовать ШИМ 0-5В в ШИМ 0-12В
digitalWrite не оптимизирован для преобразования значения
pinTestв правильную комбинацию порт/бит. Если вам это нужно, сделайте это один раз заранее. Ваш код будет аппаратно-зависимым для целей avr-gcc., @DataFiddler@DataFiddler какие-нибудь ресурсы о том, как это сделать заранее?, @Bart Friederichs
Посмотрите этот youtube [Почему я переключаюсь с замечательной среды разработки Arduino на Atmel Studio](https://www.youtube.com/watch?v=648Tx5N9Zoc), @hcheung
Спасибо всем. Жаль, что я работаю в Linux, поэтому Atmel Studio не вариант, но я обнаружил, что нужно подождать, чтобы собрать код сборки с использованием
arduino-cliи Visual Studio Code., @Bart Friederichs