Как и какие сигналы обрабатываются в микроконтроллере? Что такое аналоговый сигнал? Чем отличается от цифрового? На представленной ниже схеме указаны возможные сигналы на выходе и входе микроконтроллера. Аналоговый сигнал - непрерывный сигнал, значение которого мы знаем в любой момент времени. Цифровой сигнал - значения известны через равные промежутки времени и значений только два - 0 и 1.
На выше представленной схеме рассмотрены штатные команды (функции) языка Wiring
На официальном сайте пишут: "...is programmed using the Arduino programming language (based on Wiring)".
Фактически — нет никакого особого языка программирования и программы пишутся на C/C++, а компилируются и собираются с помощью широко известного avr-gcc (в версии для Windows — WinAVR).
Все особенности сводятся к тому, что имеется набор библиотек, включающий
в себя некоторые функции (вроде pinMode) и объекты (вроде Serial), а
при компиляции Вашей программы среда разработки создает временный .cpp
файл, в который кроме Вашего кода включается еще несколько строчек, и
полученный результат скармливается компилятору а затем линковщику с
нужными параметрами.
К сожалению за все нужно платить, за универсальность тоже. Расплата это размер и скорость выполнения программы. Иногда штатные функции нам не всегда на 100% полезны, иногда возникают ситуации что они избыточны. Именно для этого мы рассмотрим альтернативные способы работы с сигналами в микроконтроллере. Начнем с цифровых сигналов.
В микроконтроллере Arduino UNO, имеются 3 порта работы с цифровыми сигналами B, C, D.
Каждый порт представляет собой три 8-ми битный регистр, в котором каждый бит имеет свой вывод(ногу, пин), два доступных для записи чтения и один только для чтения. Регистр DDRx (где х имя порта) отвечает за представления ножки как выхода или входа в зависимости от того что записано в данный бит 1- выход 0- вход. Таким образом записывая в соответствующий бит регистра 0 или 1 мы определяем его как вход или выход. Регистр PORTx ответственно отвечает зато что находится на выходе высокий или низкий уровень сигнала. Регистр PINx доступен только для чтения и позволяет считывать уровень сигнала на соответствующем выходе. Например:
DDRD = 0xff;
PORTD= 0b11000010;
Двумя строчками мы определили все выводы порта D (pin 0..7), как выходы где высокий уровень(HIGH) на pin 1,6,7 на остальных выводах низкий (LOW)
Иногда обращаться ко всему порту бывает затруднительно, поэтому вместо digitalWrite() можно использовать:
PORTD |= 1<<3; // УСТАНАВЛИВАЕМ НА pin_2 высокий уровень сигнала
PORTD &= ~(1<<3); //устанавливаем на pin_2 низкий уровень сигнала
В Н И М А Н И Е
команда PORTD = 1<<3; ЗАПИШЕТ в регистр 0b00000100, будьте осторожны. Соответственно PORTD = ~(1<<3) ----> 0b111110111.
Теперь что касается чтения с выводов порта. Условие которое определяет уровень сигнала на выводе (PIND & (1<<PD3)) если истинно то HIGH, ложно LOW.
С цифровыми сигналами разобрались. Теперь аналоговый сигнал.
Для работы с аналоговым сигналом необходимо преобразовать его в цифровой, для этого используется аналого-цифровой преобразователь (АЦП)
АЦП Arduino UNO имеет разрешение 10 бит, т.е. позволяет выводить значения в десятичном виде от 0 до 1023. В относительных единицах деление шкалы 5/1024 = 4.9 мВ;
analogRead(pin) -- Функция считывает значение с указанного аналогового входа. Возвращает: int (0 to 1023).
Считывание значение с аналогового входа занимает примерно 100
микросекунд (0.0001 сек), т.е. максимальная частота считывания
приблизительно 10,000 раз в секунду.
analogReference(type) -- определяет
опорное напряжение относительно которого происходят аналоговые
измерения. Type принимает одно из следующих значений:
DEFAULT: стандартное опорное
напряжение 5 В (на платформах с напряжением питания 5 В) или 3.3 В (на
платформах с напряжением питания 3.3 В).
INTERNAL: встроенное опорное напряжение 1.1 В на микроконтроллерах ATmega168 и ATmega328, и 2.56 В на ATmega8.
EXTERNAL: внешний источник опорного напряжения, подключенный к выводу AREF (рекомендуется подключать к выводу AREF через резистор 5 кОм).
Примеч.: Опорное напряжение можно установить, используя функцию analogReference или при помощи битов REFT[1:0] в регистре ADMUX.
Используйте внутреннее опорное напряжение 1.1 В для точных измерений внешних напряжений:
analogReference(INTERNAL1V1); // выбираем внутреннее опорное напряжение 1.1В
Разовая выборка - это на самом деле то, что Arduino делает при вызове функции analogRead().
Непрерывная выборка:
Хорошей идеей при непрерывной выборке сигнала является использование прерываний.
Микроконтроллеры ATMega328 и ATMega2560 могут быть переведены в
режим непрерывной выборки (free running mode). В этом режиме АЦП
запускается автоматически после завершения предыдущей обработки. Для включения режима непрерывной выборки необходимо установить три регистра: ADMUX, ADCSRA и ADCSRB.
ADCSRB = 0x00;
ADMUX = 0b01100000;//A0
ADCSRA = 0b11101111;//делитель 128
//функция для работы с АЦП по прерыванию
volatile int result;
ISR(ADC_vect)
{
result = ADCH;
}
Продолжение следует