Как увеличить переключение распиновки?
Рассмотрите этот код:
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