Библиотеки timerone и timerthree для arduino

Дребезг контактов

Очевидно, что при подаче на вход внешнего прерывания сигнала, искаженного дребезгом контактов, обработчик прерывания будет выполнен несколько раз. В некоторых случаях дребезг не является проблемой, например, если мы ожидаем нажатия на кнопку для выполнения в программе каких-либо действий: достаточно отключить отслеживание данного прерывания при входе в обработчик, а после выполнения нашего кода снова включить (подразумевается, что время выполнения наших действий превышает длительность дребезга контактов). Таким образом мы пропустим дребезг и обработчик будет выполнен только один раз. Другое дело, когда прерывания используются для регистрации событий. Хороший пример — механический энкодер вращения. В этом случае мы не можем отключить отслеживание прерываний, поскольку рискуем пропустить событие (импульс от энкодера). Принять решение о том, ложный это импульс или нет, обработчик не может, да и просто это не та задача, которой он должен заниматься. Поэтому единственным рациональным решением является применение аппаратных подавителей дребезга. Данной теме посвящены несколько моих публикаций, ссылки на них ниже:

Устранение дребезга контактов. Часть 1 — триггер ШмиттаУстранение дребезга контактов. Часть 2 — микросхема MC14490Устранение дребезга контактов. Часть 3 — микросхемы MAX6816/MAX6817/MAX6818

Step 1: Prescalers and the Compare Match Register

The Uno has three timers called timer0, timer1, and timer2.  Each of the timers has a counter that is incremented on each tick of the timer’s clock.  CTC timer interrupts are triggered when the counter reaches a specified value, stored in the compare match register.  Once a timer counter reaches this value it will clear (reset to zero) on the next tick of the timer’s clock, then it will continue to count up to the compare match value again.  By choosing the compare match value and setting the speed at which the timer increments the counter, you can control the frequency of timer interrupts.
The first parameter I’ll discuss is the speed at which the timer increments the counter.  The Arduino clock runs at 16MHz, this is the fastest speed that the timers can increment their counters.  At 16MHz each tick of the counter represents 1/16,000,000 of a second (~63ns), so a counter will take 10/16,000,000 seconds to reach a value of 9 (counters are 0 indexed), and 100/16,000,000 seconds to reach a value of 99.
In many situations, you will find that setting the counter speed to 16MHz is too fast.  Timer0 and timer2 are 8 bit timers, meaning they can store a maximum counter value of 255.  Timer1 is a 16 bit timer, meaning it can store a maximum counter value of 65535.  Once a counter reaches its maximum, it will tick back to zero (this is called overflow).  This means at 16MHz, even if we set the compare match register to the max counter value, interrupts will occur every 256/16,000,000 seconds (~16us) for the 8 bit counters, and every 65,536/16,000,000 (~4 ms) seconds for the 16 bit counter.  Clearly, this is not very useful if you only want to interrupt once a second.
Instead you can control the speed of the timer counter incrementation by using something called a prescaler.  A prescaler dictates the speed of your timer according the the following equation:(timer speed (Hz)) = (Arduino clock speed (16MHz)) / prescaler
So a 1 prescaler will increment the counter at 16MHz, an 8 prescaler will increment it at 2MHz, a 64 prescaler = 250kHz, and so on.  As indicated in the tables above, the prescaler can equal 1, 8, 64, 256, and 1024.  (I’ll explain the meaning of CS12, CS11, and CS10 in the next step.) 
Now you can calculate the interrupt frequency with the following equation:interrupt frequency (Hz) = (Arduino clock speed 16,000,000Hz) / (prescaler * (compare match register + 1))
the +1 is in there because the compare match register is zero indexed
rearranging the equation above, you can solve for the compare match register value that will give your desired interrupt frequency:compare match register = [ 16,000,000Hz/ (prescaler * desired interrupt frequency) ] — 1
remember that when you use timers 0 and 2 this number must be less than 256, and less than 65536 for timer1
so if you wanted an interrupt every second (frequency of 1Hz):
compare match register = [16,000,000 / (prescaler * 1) ] -1
with a prescaler of 1024 you get:
compare match register = [16,000,000 / (1024 * 1) ] -1
= 15,624
since 256 < 15,624 < 65,536, you must use timer1 for this interrupt.

Выполнение задач FreeRTOS в Arduino IDE

Исходя из основных принципов использования FreeRTOS в Arduino, рассмотренных в предыдущем разделе статьи, первым делом в программе мы подключим заголовочный файл библиотеки FreeRTOS. Затем создадим прототипы функций. Поскольку у нас будет три задачи то, соответственно, создадим для них три прототипа.

Arduino

#include <Arduino_FreeRTOS.h>
void TaskBlink1( void *pvParameters );
void TaskBlink2( void *pvParameters );
void Taskprint( void *pvParameters );

1
2
3
4

#include <Arduino_FreeRTOS.h>

voidTaskBlink1(void*pvParameters);

voidTaskBlink2(void*pvParameters);

voidTaskprint(void*pvParameters);

Далее в функции void setup() мы инициализируем последовательную связь со скоростью 9600 бит/с и создадим три задачи используя API-функцию xTaskCreate(). Первоначально, установим приоритет для всех задач равный ‘1’, и запустим планировщик (scheduler).

Arduino

void setup() {
Serial.begin(9600);
xTaskCreate(TaskBlink1,»Task1″,128,NULL,1,NULL);
xTaskCreate(TaskBlink2,»Task2 «,128,NULL,1,NULL);
xTaskCreate(Taskprint,»Task3»,128,NULL,1,NULL);
vTaskStartScheduler();
}

1
2
3
4
5
6
7

voidsetup(){

Serial.begin(9600);

xTaskCreate(TaskBlink1,»Task1″,128,NULL,1,NULL);

xTaskCreate(TaskBlink2,»Task2 «,128,NULL,1,NULL);

xTaskCreate(Taskprint,»Task3″,128,NULL,1,NULL);

vTaskStartScheduler();

}

Запрограммируем функцию для первой задачи task1 мигания светодиодом.

Arduino

void TaskBlink1(void *pvParameters)
{
pinMode(8, OUTPUT);
while(1)
{
digitalWrite(8, HIGH);
vTaskDelay( 200 / portTICK_PERIOD_MS );
digitalWrite(8, LOW);
vTaskDelay( 200 / portTICK_PERIOD_MS );
}
}

1
2
3
4
5
6
7
8
9
10
11

voidTaskBlink1(void*pvParameters)

{

pinMode(8,OUTPUT);

while(1)

{

digitalWrite(8,HIGH);

vTaskDelay(200portTICK_PERIOD_MS);

digitalWrite(8,LOW);

vTaskDelay(200portTICK_PERIOD_MS);

}
}

Аналогично запрограммируем функцию для выполнения задачи Task2. Функция для выполнения задачи Task3 будет выглядеть следующим образом:

Arduino

void Taskprint(void *pvParameters)
{
int counter = 0;
while(1)
{
counter++;
Serial.println(counter);
vTaskDelay( 500 / portTICK_PERIOD_MS );
}
}

1
2
3
4
5
6
7
8
9
10

voidTaskprint(void*pvParameters)

{

intcounter=;

while(1)

{

counter++;

Serial.println(counter);

vTaskDelay(500portTICK_PERIOD_MS);

}
}

На этом все – мы успешно запрограммировали проект FreeRTOS для Arduino. Более подробно его работу вы можете посмотреть на видео, приведенном в конце статьи.

Чтобы проверить работу проекта, подключите два светодиода к цифровым контактам 7 и 8, загрузите код программы в плату Arduino и откройте окно монитора последовательной связи (Serial monitor) – в нем вы увидите как счетчик обновляется каждые 500 мс.

Также вы сможете наблюдать как мигают два светодиода с различными интервалами. Попробуйте изменять введенные приоритеты задач в функции xTaskCreate и посмотрите как меняется работа проекта.

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

ISR operation

So an ISR is virtually identical to a normal subroutine call. The
problem is that an ISR can be executed at any time corrupting any
existing register values.

To allow the ISR to work current register values must be stored at
the beginning and restored at the end. Fortunately this is taken care of
for you within the
compiler. All relevant flags and registers are saved before, and then restored after an interrupt.

In this way the current program is
interrupted in the middle of its operation and does not know anything about the
interrupt.

Hardware connection

Connect a push button on one side to Arduino pin D2 and on the other side to Ground.

Connect a 100nF capacitor from Arduino pin D2 to Ground. To explore
interrupts and switch debouncing and why this works see the page on switch debouncing.

Проблемы при использовании с ATtiny

В библиотеке для буферов используется большой объем памяти. Он включает в себя 3 разных байтовых буфера, каждый размером 32 байта. Это не большая проблема для ATmega, но ATtiny (например, ATtiny48) обладает меньшим количеством RAM (512/1K у ATmega, и 256/512 у ATtiny). Когда я попытался использовать библиотеку Wire на ATtiny, у меня появлялись случайные сбои, зависания и т.д. Как только я изменил размер буфера (в .\libraries\Wire\utility\twi.h) на 6, всё отлично заработало.

Не делайте ошибку, думая, что вы можете просто указать в своем скетче  потому, что это не работает. Способ, которым Arduino IDE компилирует ваш код, не очевиден. Библиотека компилируется отдельно от вашего скетча, а затем линкуется с ним. Поэтому вам придется изменить размер буфера в заголовочном файле библиотеки, который также включается в исходном файле библиотеки (twi.c).

Arduino Hardware Interrupt Programming:

int led1 = 8;
int led2 = 13;

void setup()
{
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
digitalWrite(led1, LOW);
digitalWrite(led2, LOW);
attachInterrupt(0, ISR1, FALLING);

}

void loop()
{
digitalWrite(led2, HIGH);
delay(1000);
digitalWrite(led2, LOW);
delay(1000);
}

void ISR1()
{
digitalWrite(led2,LOW);
while(1)
{
digitalWrite(led1, HIGH);
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

intled1=8;

intled2=13;

voidsetup()

{

pinMode(led1,OUTPUT);

pinMode(led2,OUTPUT);

digitalWrite(led1,LOW);

digitalWrite(led2,LOW);

attachInterrupt(,ISR1,FALLING);

 
}
 

voidloop()

{

digitalWrite(led2,HIGH);

delay(1000);

digitalWrite(led2,LOW);

delay(1000);

}
 

voidISR1()

{

digitalWrite(led2,LOW);

while(1)

{

digitalWrite(led1,HIGH);

}

}

What is an Interrupt?

Interrupts are a method of signaling to the microprocessor that something has happened. However, you may ask yourself, is that not what happens anyway when you use a digital input, etc.? Well quite simply — No.

When you use the likes of a digital input, you will typically read its value by issuing an instruction, then act on the read value by using some form of logic, i.e. the code is polling for a value. Depending on the complexity of your routines, and the duration of the state change on the input, it is quite possible to not see the change on the input occur at all.

By using an interrupt, the code is literally interrupted, and forced to branch off and do some other execution, i.e. the state change on the input is not ‘missed’. So interrupts are like a hardware trigger.

Introduction: Arduino Timer Interrupts

By amandaghassaeiuh-man-duh-guss-eye-dot-comFollow

More by the author:

About: I post updates on twitter and instagram: @amandaghassaei

More About amandaghassaei »

Timer interrupts allow you to perform a task at very specifically timed intervals regardless of what else is going on in your code. In this instructable I’ll explain how to setup and execute an interrupt in Clear Timer on Compare Match or CTC Mode. Jump straight to step 2 if you are looking for sample code.

Normally when you write an Arduino sketch the Arduino performs all the commands encapsulated in the loop() {} function in the order that they are written, however, it’s difficult to time events in the loop(). Some commands take longer than others to execute, some depend on conditional statements (if, while…) and some Arduino library functions (like digitalWrite or analogRead) are made up of many commands. Arduino timer interrupts allow you to momentarily pause the normal sequence of events taking place in the loop() function at precisely timed intervals, while you execute a separate set of commands. Once these commands are done the Arduino picks up again where it was in the loop().

Interrupts are useful for:

Measuring an incoming signal at equally spaced intervals (constant sampling frequency)
Calculating the time between two events
Sending out a signal of a specific frequency
Periodically checking for incoming serial data
much more…

There are a few ways to do interrupts, for now I’ll focus on the type that I find the most useful/flexible, called Clear Timer on Compare Match or CTC Mode. Additionally, in this instructable I’ll be writing specifically about the timers to the Arduino Uno (and any other Arduino with ATMEL 328/168… Lilypad, Duemilanove, Diecimila, Nano…). The main ideas presented here apply to the Mega and older boards as well, but the setup is a little different and the table below is specific to ATMEL 328/168.

Задержки

Простейшей с точки зрения использования функцией времени является задержка, их у нас две:

  • delay(time) – “Приостанавливает” выполнение кода на time миллисекунд. Дальше функции delay выполнение кода не идёт, за исключением прерываний. Использовать рекомендуется только в самых крайних или тех случаях, когда delay не влияет на скорость работы устройства. time принимает тип данных unsigned long и может приостановить выполнение на срок от 1 мс до

50 суток (4 294 967 295 миллисекунд) с разрешением в 1 миллисекунду. Работает на системном таймере Timer 0delayMicroseconds(time) – Аналог delay(), приостанавливает выполнение кода на time микросекунд. time принимает тип данных unsigned long и может приостановить выполнение на срок от 4 мкс до

70 минут (4 294 967 295 микросекунд) с разрешением 4 микросекунды. Работает на системном таймере Timer 0

Задержки использовать очень просто:

И вот мы можем делать какое-то действие два раза в секунду. А что делать, если нам нужно выполнять одно действие два раза в секунду, а другое – три? А третье – 10 раз в секунду например. Сразу привыкаем к той мысли, что задержки лучше вообще не использовать в реальном коде. Разве что delayMicroseconds, он бывает нужен для генерации каких-то протоколов связи. Нормальным инструментом для тайм-менеджмента своего кода являются функции, которые считают время со старта МК.

Внутри ATmega328

В основе данного подраздела лежит техническое описание на ATmega328 версии Rev. 8271C – 08/10. Приводимые мной страницы могут немного отличаться от текущей версии.

Для полного понимания кода библиотеке , нам необходимо понимать, что ей нужно сделать с микроконтроллером, чтобы его настроить.

Просмотр технического описания на микроконтроллер показывает нам, как работает двухпроводная (Two Wire) система. Стоит отметить:

Микроконтроллер включает в себя аппаратный модуль TWI, который обрабатывает связь через шину I2C. … Интересно, что это означает, что связь не обрабатывается библиотекой исключительно программно, как вы могли бы подумать! Другими словами, библиотека сама в программе не создает битовый поток. Библиотека взаимодействует с аппаратным компонентом, который выполняет тяжелую работу. Смотрите страницу 222 технического описания.
«AVR TWI работает с байтами и основывается на прерываниях…» (раздел 21.6 на странице 224)

Это ключевой момент; это означает, что
вы настраиваете регистры;
вы позволяете TWI модулю осуществлять связь;
вы можете делать в это время что-то еще; ваш микроконтроллер с тактовой частотой 16 МГц не занят управлением последовательной связью на 100 кГц;
TWI модуль вызывает прерывание, когда заканчивает работу, чтобы уведомить процессор об изменениях состояния (включая успешность операций и/или ошибки).

Однако обратите внимание, что библиотека блокирует ввод/вывод. Это означает, что он переходит в цикл ожидания и ждет завершения связи I2C

Ваше приложение не может ничего делать, пока модуль TWI общается по шине I2C. Обратите внимание, что это может быть не то, чего бы вы хотели: если ваша программа критична ко времени, то ваш 16-мегагерцовый процессор, застрявший в цикле ожидания и ждущий 100-килогерцового потока связи, будет не эффективен. Возможно, вам лучше написать собственный код I2C. В исходном коде avr-libc есть пример в ./doc/examples/twitest/twitest.c (смотрите http://www.nongnu.org/avr-libc/). Вы можете найти версию avr-libc, используемую вашей конкретной IDE Arduino, посмотрев файл versions.txt в каталоге установки Arduino IDE. Это будет где-то в Java/hardware/tools/avr. На Mac полный путь будет следующим /Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/versions.txt; путь у вас будет другим, но схожим.

Часто используемые термины в RTOS

Задача (Task) – кусок кода, который выполняется в процессоре по расписанию (в определенное время).

Планировщик (Scheduler) – отвечает за выбор и перевод задач из состояния готовности (ready state) в состояние выполнения (running state).

Вытеснение (Preemption) – действие, направленное на временное прерывание выполняющейся задачи с целью удаления ее из состояния выполнения.

Переключение контекста (Context Switching) — процесс переключения процессора на другую задачу (процесс, поток) (например, при обработке прерывания), обычно сопровождающийся операциями сохранения в стеке состояния текущего потока (регистров и другой информации), восстановлением ранее сохранённого состояния другого потока и передачей ему управления. Во время работы в моменты прерывания планировщик сравнивает приоритет задач, которые находятся в состоянии готовности, с приоритетом выполняемой задачи. Если приоритет какой-нибудь задачи, находящейся в состоянии готовности, выше, чем приоритет выполняемой задачи, происходит событие переключения контекста. Состояние задачи, выполнение которой прерывается, обычно сохраняется в стеке.

Типы политики (плана действий) планировщика:

  • приоритетное планирование (Preemptive Scheduling) – в этом случае все задачи выполняются примерно одинаковую часть времени независимо от их приоритетов;
  • планирование на основе приоритетов (Priority-based Preemptive) – задачи с высоким приоритетом выполняются в первую очередь;
  • совместное планирование (Co-operative Scheduling) – операция переключения контекста случается только при взаимодействии (сотрудничестве) выполняемых задач.

Объекты ядра (Kernel Objects) – для информирования задач о том, что они должны выполнить определенную работу, используется процесс синхронизации. Для осуществления этого процесса и используются объекты ядра, такие, к примеру, как события (Events), семафоры (Semaphores), очереди (Queues), флаги/мьютексы (Mutex), почтовые ящики (Mailboxes) и т.д.

Program Example 2


#define LED1 9
#define LED2 10
#define SW1 2
#define SW2 3

void toggle(byte pinNum) { 
  byte pinState = !digitalRead(pinNum);
  digitalWrite(pinNum, pinState); 
}

void setup()  {
  pinMode(LED1, OUTPUT);  
  pinMode(LED2, OUTPUT);
  digitalWrite(LED1, 0); // LED off
  digitalWrite(LED2, 0); // LED off
  pinMode(SW1, INPUT);
  pinMode(SW2, INPUT);
  attachInterrupt(0, ISR0, FALLING);  
  // interrupt 0 digital pin 2 connected SW0
  attachInterrupt(1, ISR1, RISING); 
  // interrupt 1 digital pin 3 connected SW1
}

void loop() {
  // do nothing
} 

// can't use delay(x) in IRQ routine
void ISR0() { 
  toggle(LED1); 
} 

void ISR1() { 
  toggle(LED2);
} 

The above program introduces several new concepts. There are no «volatile» variables defined or needed. Both INTR0 (DP2) and INTR1 (DP3) both have their own separate ISR routines ISR0() and ISR1() respectively. There is a separate non-interrupt subroutine toggle().

In this case either ISR routines will simply call toggle() and will let toggle() do the work.

Certain functions such as delay() won’t work inside a ISR function so it’s a good idea to use separate subroutines as long as they are not overly complex or time consuming — another interrupt rolling onto an ISR called subroutine that hasn’t finished could be interesting.

In addition functions that use interrupts such as delay() will not work if called from an ISR routine. For example the modified version of toggle() that follows won’t work if called by an ISR but works fine if called from loop() or another non-interrupt subroutine. The selected LED will come on for two seconds then go off.

The ISR routine maintains control of the interrupts until it’s finished and executes a «return» from interrupt command.


void toggle(byte pinNum) { 
  byte pinState = !digitalRead(pinNum);
  digitalWrite(pinNum, pinState); 
  delay(2000);
  pinState = pinState ^ 1;
  digitalWrite(pinNum, pinState); 
} // last brace is understood as return. 

The real solution is not to use the Arduino delay() function but write your own. the delayMicroceconds() doesn’t require the use of interrupts but is limited to about 16,000 — 1000uSec. = 1mSec.; 1,000,000uSec. — 1 Sec. Simply use a for loop:


void myDelay(int x)   {
  for(int i=0; i<=x; i++)   
  {
    delayMicroseconds(1000);
  }
}

Use myDelay(5000) for delay(5000) and the program will work.

Синтаксис define ардуино

Синтаксис использования инструкции достаточно прост:

#define <что меняем>  <на что меняем>

  • Знак # означает начало инструкции препроцессора.
  • define – название инструкции.
  • <что меняем>  – имя макроса: словосочетание, которое будет находить препроцессор
  • <на что меняем> – тело макроса: строка, которая будет подставлена в то место, где будет найдено <что меняем>

Обратите внимание, что в конце строки не нужно ставить знак точки с запятой

Примеры использования define:

  • #define PIN_LED 13
  • #define RED 1
  • #define BUTTON_LEFT   5
  • #define test Serial.println(“test”)
  • #define test(a) Serial.println(a)

Большой интерес вызывает  последний пример. Мы можем попросить ардуино подставить во фрагмент кода тот аргумент, который мы указали в качестве аргумента для параметра <что меняем>. Мы поговорим об этом в статье ниже.

Тело макроса должно заканчиваться в той же строке. Но если мы хотим сделать многострочный блок, то добавляем символ “/” в конце. Например:

#define LONG_STRING "Очень длинный текст \
Который мы смогли разбить на две части"

Программирование Ардуино

Язык программирования устройств Ардуино основан на C/C++. Он прост в освоении, и на данный момент Arduino — это, пожалуй, самый удобный способ программирования устройств на микроконтроллерах.

Базовые и полезные знания, необходимые для успешного программирования под платформу Arduino:

  • Начало работы с Arduino в Windows
  • Работа с Arduino Mini
  • Цифровые выводы
  • Аналоговые входы
  • Широтно-импульсная модуляция
  • Память в Arduino
  • Использование аппаратных прерываний в Arduino
  • Переменные
  • Функции
  • Создание библиотек для Arduino
  • Использование сдвигового регистра 74HC595 для увеличения количества выходов
  • Прямое управления выходами через регистры микроконтроллера Atmega

Справочник языка Ардуино

Язык Arduino можно разделить на три раздела:

Операторы

  • setup()
  • loop()
Управляющие операторы
  • if
  • if…else
  • for
  • switch case
  • while
  • do… while
  • break
  • continue
  • return
  • goto
Синтаксис
  • ; (semicolon)
  • {} (curly braces)
  • // (single line comment)
  • /* */ (multi-line comment)
Арифметические операторы
  • = (assignment)
  • + (addition)
  • — (subtraction)
  • * (multiplication)
  • / (division)
  • % (modulo)
Операторы сравнения
  • == (equal to)
  • != (not equal to)
  • < (less than)
  • > (greater than)
  • <= (less than or equal to)
  • >= (greater than or equal to)
Логические операторы
  • && (И)
  • || (ИЛИ)
  • ! (Отрицание)
Унарные операторы
  • ++ (increment)
  • — (decrement)
  • += (compound addition)
  • -= (compound subtraction)
  • *= (compound multiplication)
  • /= (compound division)

Данные

Константы
  • HIGH | LOW
  • INPUT | OUTPUT
  • true | false
  • Целочисленные константы
  • Константы с плавающей запятой
Типы данных
  • boolean
  • char
  • byte
  • int
  • unsigned int
  • word
  • long
  • unsigned long
  • float
  • double
  • string — массив символов
  • String — объект класса
  • массив (array)
  • void
Преобразование типов данных
  • char()
  • byte()
  • int()
  • long()
  • float()
Область видимости переменных и квалификаторы
  • Область видимости
  • static
  • volatile
  • const

Функции

Цифровой ввод/вывод
  • pinMode()
  • digitalWrite()
  • digitalRead()
Аналоговый ввод/вывод
  • analogRead()
  • analogReference()
  • analogWrite()
Дополнительные фунции ввода/вывода
  • tone()
  • noTone()
  • shiftOut()
  • pulseIn()
Работа со временем
  • millis()
  • micros()
  • delay()
  • delayMicroseconds()
Математические функции
  • min()
  • max()
  • abs()
  • constrain()
  • map()
  • pow()
  • sq()
  • sqrt()
Тригонометрические функции
  • sin()
  • cos()
  • tan()
Генераторы случайных значений
  • randomSeed()
  • random()
Внешние прерывания
  • attachInterrupt()
  • detachInterrupt()
Функции передачи данных

Serial

Библиотеки Arduino

Servo — библиотека управления сервоприводами.EEPROM — чтение и запись энергонезависимой памяти микроконтроллера.SPI — библиотека, реализующая передачу данных через интерфейс SPI.Stepper — библиотека управления шаговыми двигателями.

Сначала … когда вы используете «изменчивые» переменные?

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

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

например.

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

Просыпаться процессор

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

Пин-переменные прерывания могут использоваться для разбухания процессора, если клавиша нажата на клавиатуре или аналогичной.

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

Включение /выключение прерываний

Прерывание «сброса» не может быть отключено. Однако другие прерывания можно временно отключить, очистив флаг глобального прерывания.