Nop arduino uno

Arduino.ru

Время исполнения кода.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Есть кусок кода.

NOP — то же самое, что и asm(«nop»); — задержка на 62.5ns. (на Ардуино 16MHz)

Собственно говоря, какое количество времени займет исполнение этого кода на Arduino Duemilanove либо Uno? Пробовал измерять время с помощью Micros(), но там низкая точность — мне нужно узнать время в микросекундах с точностью до десятых.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

хотя в ардуине там еще таймера тикают.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Если не секрет, то как это считается? :)

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

ну вы же как-то посчитали что «nop» это 62.5ns.

а вобще в отладчиках такое считается. например, в том же avrstudio.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

А запись в порт сколько занимает?

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

А запись в порт сколько занимает?

Произвел рассчет в AtmelStudio 6.0: Atmega168, 16MHz — заняло 0,06мкс. Это хорошо, я думал, что писать в порт — долго. :)

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Чистая запись значение в порт — два такта:

Однако, как верно заметили выше, еще есть таймеры, которые внутри прерывания натикивают сколько-то тактов.

Пробовал измерять время с помощью Micros(), но там низкая точность — мне нужно узнать время в микросекундах с точностью до десятых.

Если время одного события слишком мало для того, чтобы его замерить — естественный способ — замерить суммарное время N событий и разделить его на N.

Источник

Nop arduino uno

Motivation

Learning inline assembly language on the Arduino AVR 8-bit platform is a daunting task for many (at least it was for me). Besides the cryptic syntax and the high level of understanding the semi-official documentation assumes, there exists very little information about GCC inline assembler coding. The main focus of existing documentation is the “Cookbook”, which dates from 2002. Trust me, any neophyte needs to spend hours searching and studying piece-meal examples while possessing overwhelming patience in order to crack the code. Again, at least I did. Hopefully this series of tutorials will help alleviate many of the discouraging troubles I encountered while teaching myself inline assembly coding. An Arduino Inline Assembly Tutorial, like this was long overdue!

In the Beginning

An inline assembly statement is a string of characters which specifies assembler code. The string can contain any instructions recognized by the assembler, including directives, but we will not discuss assembler directives here. GCC does not parse the assembler instructions and does not know what they mean or even whether they are valid. Multiple assembler instructions can be placed together in a single asm string.

Simply Inline Assembly

Here is the most basic example of an inline assembler statement:

NOP is the opcode, or instruction for “No Operation”. This statement simply inserts a NOP into your program. NOP does nothing except take up program memory and waist processor time. NOP might seem worthless, however it does come in handy in several ways.

Mainline Inline

The general form of an inline assembler statement is:

The assembly code is encased in parenthesis preceded by the compiler keyword asm or __asm__. Each assembler instruction is enclosed inside quotations and terminated with the escape sequence for the linefeed character, “\n“. Sometimes you will see the line terminated with “\n\t“. The tab sequence is added after the linefeed simply to format the output.

The compiler takes each assembly string, strips off the quotation characters and passes the code verbatim onto the assembler. The avr-as assembler requires a single instruction per line, hence the need for the linefeed.

The Fine Print

Do not expect a sequence of multiple asm statements to remain perfectly consecutive after compilation. If certain instructions need to remain consecutive in the output, put them in a single multi-instruction asm statement. GCC’s optimizers can move asm statements relative to other code, including across jumps.

asm statements may not perform jumps into other asm statements. GCC does not know about these jumps, and therefore cannot take account of them when deciding how to optimize. Jumps from asm to C labels are only supported under extended asm.

Under certain circumstances, GCC may duplicate (or remove duplicates of) your assembly code when optimizing. This can lead to unexpected duplicate symbol errors during compilation if your assembly code defines symbols or labels. And since GCC does not parse the Assembler instructions, it has no visibility of any symbols it may reference.

The compiler pre-processor does not perform macro expansion within strings. This is the reason why you can’t use macro definitions, like so:

Instructions Sans Operands

You may be surprised to learn that the Basic asm statement uses only assembly instructions without operands. An operand is the part of a computer instruction which specifies what data is to be manipulated or operated on. Basic assembly is limited to just pure instructions. That’s it. To take advantage of more advanced features and processing, or any of the ‘%’ operators, one must use the “extended asm” (more on the Extended Assembler later).

What’s An Inline To Do?

So what can we do with the basic inline asm statement besides insert NOPs? There are 24 assembly instructions without operands, 16 of which deal with clearing and setting bits inside the Status Register (SREG). We will cover the Status Register in greater detail later. Beside the 16 SREG specific instructions, the other instructions are NOP, BREAK, SLEEP, WDR, ICALL/IJMP, RET/RETI.

ICALL, IJMP, RET and RETI are advanced instruction dealing with program flow, and we will also cover them at a later time. WDR resets the Watchdog timer and is rarely used in the Arduino. SLEEP instructs the Arduino to go into a low power sleep mode.

However, two operand-less instructions are very useful. These two instructions enable or disable global interrupts. CLI, which is the mnemonic for “CLear global Interrupt flag”, clears the Global Interrupt flag (I) in the Status Register (SREG). No interrupts will be executed after the CLI instruction, or even if the interrupt occurs simultaneously with the CLI instruction.

SEI is the reverse of CLI, and sets the interrupt flag.

Both CLI and SEI are defined as C MACROS inside the AVR and Arduino libraries, similarly like so:

So far we have discovered only minimal usefulness for the inline assembler. But we now know the fundamentals of the inline assembler syntax. In the next tutorial we will expand upon these basics by studying the extended inline assembler.

Reference

Also available as a book, with greatly expanded coverage!


[click on the image]

Источник

Arduino. Ассемблер AVR8

Иногда бывает так, что только ассемблер способен помочь создать эффективный код для скетча Arduino. И тогда на помощь приходит встроенный (inline) ассемблер AVR-GCC .

Пожалуй, простейший пример — мы хотим, чтобы микроконтроллер подождал четыре такта в промежутке между изменением состояния вывода. С помощью встроенных функций delay() или delayMicroseconds() мы этого сделать не можем, для этого нам требуется использовать команду ассемблера NOP:

PORTD |= _BV( 1 );

__asm__ __volatile__ (

«nop\n\t»

«nop\n\t»

«nop\n\t»

«nop\n\t»

PORTD &=

_BV( 1 );

или, что несколько читабельнее:

PORTD |= _BV( 1 );

__asm__ __volatile__ ( «nop» );

__asm__ __volatile__ ( «nop» );

__asm__ __volatile__ ( «nop» );

__asm__ __volatile__ ( «nop» );

PORTD &=

_BV( 1 );

Оформив таким образом все команды ассемблера AVR8 как набор inline-функций и макросов, я получил в результате заголовочный файл с говорящим названием avrasm.h ( скачать ). Файл этот следует поместить в каталог Libraries/avrasm программного обеспечения Arduino. С его использованием вышеприведённый код будет выглядеть следующим образом:

PORTD |= _BV( 1 );

PORTD &=

_BV( 1 );

Надо заметить, что в самом по себе программировании Arduino на ассемблере нет ничего сложного, но есть нюансы, которые неизбежно приходится учитывать. Например, результат команды умножения MUL помещается в пару регистров R0:R1 , которая компилятором языка программирования C используется следующим образом: регистр R0 используется как временный (temporary) регистр, а регистр R1 как нулевой (zero) регистр (теоретически его значение всегда должно быть равно нулю).

Поэтому на ассемблере удобнее всего писать совсем небольшие программы. Например, когда я делал 8-битный синтезатор, изучая взаимодействие нескольких микроконтроллеров, то один из микроконтроллеров у меня выполнял функцию UART-приёмника MIDI с буфером FIFO. Соответственно лучше всего и быстрее всего он работал с микропрограммой, целиком написанной на ассемблере (на C работал значительно медленнее, и даже иногда подвисал).

С другой стороны программы на ассемблере намного сложнее отлаживать, поскольку код программы имеет свойство довольно быстро разрастаться, и найти в программе ошибку типа опечатки — задача крайне утомительная и трудоёмкая.

Источник

Руководство по прерываниям в Arduino для начинающих

Рассмотрим быстро едущую машину. Если она в процессе своего движения сталкивается с другой машиной, акселерометр, присутствующий в машине, фиксирует значительное отрицательное ускорение (то есть замедление) и подает сигнал внешнего прерывания на микроконтроллер, присутствующий в машине. В результате этого микроконтроллер подает управляющий сигнал на немедленное срабатывание подушек безопасности. Микроконтроллер в машине в процессе ее движения выполняет множество функций – определение скорости, опрос различных датчиков, управление температурой кондиционера и т.д. Так почему же он на фоне всех этих действий может немедленно подать команду на срабатывание подушек безопасности. Все дело в использовании сигнала прерывания, который имеет наивысший приоритет среди всех выполняемых микроконтроллером действий.

Другим примером прерываний является экран современных смартфонов, реагирующий на прикосновения. Обработка прикосновения к экрану имеет наивысший приоритет среди всех действий, выполняемых микропроцессором смартфона. Почти все современные электронные устройства имеют определенные виды прерываний (в англ. – interrupts), которые «прерывают» регулярную последовательность действий чтобы выполнить какое-нибудь первоочередное действие при наступлении определенного события. Процесс выполнения регулярной последовательности действий возобновляется после обслуживания прерывания.

Фактически, прерывания представляют собой механизм, с помощью которого можно временно приостановить нормальную последовательность действий (нормальное функционирование) и вынудить его обслуживать прерывание, которое в данном случае имеет наивысший приоритет среди всех выполняемых им действий. К примеру, нормальное функционирование микропроцессора может прервать какой-нибудь датчик и запустить последовательность действий, присутствующую в программе (функции, процедуре) обслуживания прерываний (ISR — Interrupt Service Routine). После выполнения программы обслуживания прерывания микропроцессор может вернуться к нормальному функционированию.

Типы прерываний

Существует два типа прерываний:

  1. Аппаратные прерывания : возникают при наступлении какого-нибудь внешнего события, например, состояние контакта изменится с LOW на HIGH или с HIGH на LOW.
  2. Программные прерывания : возникают при выполнении каких-нибудь инструкций в теле программы. К примеру, прерывания от таймеров в Arduino являются программными прерываниями.

Прерывания в Arduino

Платы Arduino поддерживают два типа прерываний:

  • внешние прерывания;
  • прерывания, возникающие при изменении состояния контакта.

Внешние прерывания

Эти прерывания обрабатываются на аппаратном уровне, поэтому их обработка происходит очень быстро. Эти прерывания можно настроить на события увеличения или падения уровня, или просто на низкий уровень напряжения.

В следующей таблице представлены контакты для различных типов плат Arduino, на которых возможна обработка внешних прерываний.

Тип платы Arduino Номера контактов для использования внешних прерываний
UNO , NANO 2,3
Mega 2,3,18,19,20,21

Как видите из представленной таблицы, в наиболее распространенных платах Arduino (Uno и Nano) всего два контакта для обработки внешних прерываний, но в большинстве реальных задач этого хватает.

Прерывания, возникающие при изменении состояния контакта

В платах Arduino можно значительно увеличить количество задействованных контактов для обработки прерываний. В платах Arduino, построенных на основе микроконтроллеров ATmega168/328, любой из 20 сигнальных контактов можно сконфигурировать на обработку прерывания. Их также можно настроить на события увеличения или падения уровня.

Использование прерываний в Arduino

Для использования прерываний в платах Arduino необходимо понять несколько основополагающих вещей.

Программа обслуживания прерывания (ISR — Interrupt Service Routine)

Данная программа представляет собой обработчик прерывания и обычно состоит из небольшого числа инструкций. Когда поступает сигнал внешнего прерывания, микроконтроллер сначала исполняет инструкции, записанные в данном обработчике прерывания, а после этого возвращается к тому месту программы, во время исполнения которого поступил запрос на исполнение прерывания, то есть возвращается в режим «нормального функционирования».

В Arduino используется следующий формат команды для программы обслуживания прерывания (ISR):

attachInterrupt(digitalPinToInterrupt(pin), ISR, mode);

digitalPinToInterrupt(pin) : в платах Arduino Uno, NANO для обработки прерываний используются контакты 2,3, а в Arduino Mega – контакты 2,3,18,19,20,21. В этом параметре приведенной команды необходимо указать конкретный контакт (один из доступных для этого), который будет использоваться для обработки сигнала внешнего прерывания.

ISR : название функции, которая будет вызываться при поступлении внешнего прерывания.

Mode : тип перехода (изменения состояния), который будет обрабатываться, например, понижение уровня, повышение уровня и т.д. Возможны следующие значения данного параметра:

  • RISING (повышение уровня): будет срабатывать прерывание когда контакт будет переходить из состояния LOW в состояние HIGH;
  • FALLING (понижение уровня): будет срабатывать прерывание когда контакт будет переходить из состояния HIGH в состояние LOW;
  • CHANGE (изменение уровня): будет срабатывать прерывание когда контакт будет переходить из состояния LOW в состояние HIGH или из состояния HIGH в состояние LOW, то есть изменять свое состояние.

Особенности использования прерываний

  1. Функция программы обслуживания прерывания (ISR) должна быть по возможности максимально короткой.
  2. Внутри программы обслуживания прерывания не работает функция задержки Delay(), поэтому ее использование в данной программе необходимо исключить.

В данном руководстве (обучающей статье) по использованию прерываний в платах Arduino мы будем использовать два прерывания. Для срабатывания данных прерываний мы будем использовать две кнопки, подключенные к контактам D2 и D3 платы Arduino. Для индикации поступившего прерывания будет использоваться светодиод. При нажатии первой кнопки светодиод будет загораться и на ЖК дисплее будет высвечиваться надпись interrupt2 (прерывание 2). При нажатии второй кнопки светодиод будет выключаться и на ЖК дисплее будет высвечиваться надпись interrupt1 (прерывание 1).

Необходимые компоненты

  1. Плата Arduino Nano (купить на AliExpress). Можно использовать и другие типы плат Arduino.
  2. ЖК дисплей 16х2 (купить на AliExpress).
  3. Кнопки – 2 шт.
  4. Светодиод (купить на AliExpress).
  5. Резистор 10 кОм – 2 шт. (купить на AliExpress).
  6. Макетная плата.
  7. Соединительные провода.

Схема проекта

Схема проекта для демонстрации возможностей использования прерываний в плате Arduino представлена на следующем рисунке.

Необходимые соединения между платой Arduino Nano и ЖК дисплеем 16х2 представлены в следующей таблице.

ЖК дисплей Плата Arduino Nano
VSS GND
VDD +5V
V0 к средней точке потенциометра для управления контрастностью ЖК дисплея
RS D7
RW GND
E D8
D4 D9
D5 D10
D6 D11
D7 D12
A +5V
K GND

Две кнопки подключены к контактам платы Arduino Nano D2 и D3. Кнопки используются для формирования двух сигналов внешних прерываний: одно будет включать светодиод, а другое – выключать. Каждая кнопка подключена с помощью внешнего подтягивающего резистора на 10 кОм – использование подтягивающих резисторов в данном случае является обязательным чтобы исключить ложные (плавающие) изменения уровней на контактах D2 и D3. То есть когда кнопка будет нажата, на контакте, к которому она подключена, будет состояние логической 1 (HIGH), а если кнопка будет отжата, на контакте, к которому она подключена, будет состояние логического 0 (LOW).

Светодиод в схеме будет также информировать нас о том, что произошло (сработало) какое-нибудь из двух прерываний.

Объяснение программы для Arduino

Полный текст программы приведен в конце статьи, здесь же мы рассмотрим его основные фрагменты.

1. Сначала в программе нам необходимо подключить библиотеку для работы с ЖК дисплеем и инициализировать используемые контакты.

Источник

Adblock
detector