Программируем Arduino. Основы работы со скетчами
Шрифт:
Функция receiveEvent принимает единственный параметр — количество байт, готовых для чтения. В данном случае это число игнорируется. Цикл while читает по очереди все доступные символы и выводит их в монитор последовательного порта. Затем выполняются чтение единственного однобайтного числа в конце сообщения и его вывод в монитор порта. Использование println вместо write гарантирует, что значение байта будет выведено как число, а не символ с соответствующим числовым кодом (рис. 7.7).
Рис. 7.7.
Платы со светодиодными индикаторами
Еще один широкий спектр устройств I2C — разного рода дисплеи. Наиболее типичными представителями этих устройств являются светодиодные матрицы и семисегментные индикаторы, производимые компанией Adafruit. Они содержат светодиодные дисплеи, смонтированные на печатной плате, и управляющие микросхемы с поддержкой интерфейса I2C. Такое решение избавляет от необходимости использовать большое число контактов ввода/вывода на плате Arduino для управления светодиодным дисплеем и позволяет обойтись всего двумя контактами, SDA и SCL.
Эти устройства (верхний ряд на рис. 7.1) используются вместе с библиотеками, имеющими исчерпывающий набор функций для отображения графики и текста на светодиодных дисплеях компании Adafruit. Больше информации об этих красочных и интересных устройствах можно найти на странице www.adafruit.com/products/902.
Библиотеки скрывают все взаимодействия через интерфейс I2C за своим фасадом, давая возможность пользоваться высокоуровневыми командами, как демонстрирует следующий фрагмент, взятый из примера, входящего в состав библиотеки:
#include <Wire.h>
#include "Adafruit_LEDBackpack.h"
#include "Adafruit_GFX.h"
Adafruit_8x8matrix matrix = Adafruit_8x8matrix;
void setup
{
matrix.begin(0x70);
matrix.clear;
matrix.drawLine(0, 0, 7, 7, LED_RED);
matrix.writeDisplay;
}
Часы реального времени DS1307
Еще одно распространенное устройство I2C — модуль часов реального времени DS1307. Для этого модуля также имеется удобная и надежная библиотека, упрощающая взаимодействие с модулем и избавляющая от необходимости иметь дело с фактическими сообщениями I2C. Библиотека называется RTClib и доступна по адресу https://github.com/adafruit/RTClib.
Следующие фрагменты кода тоже взяты из примеров, поставляемых с библиотекой:
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 RTC;
void setup
{
Serial.begin(9600);
Wire.begin;
RTC.begin
if (! RTC.isrunning) {
Serial.println("RTC is NOT running!");
// записать в модуль дату и время компиляции скетча
RTC.adjust(DateTime(__DATE__, __TIME__));
}
}
void loop {
DateTime now = RTC.now;
Serial.print(now.year, DEC);
Serial.print('/');
Serial.print(now.month, DEC);
Serial.print('/');
Serial.print(now.day, DEC);
Serial.print(" (");
Serial.print(daysOfTheWeek[now.dayOfTheWeek]);
Serial.print(") ");
Serial.print(now.hour, DEC);
Serial.print(':');
Serial.print(now.minute, DEC);
Serial.print(':');
Serial.print(now.second, DEC);
Serial.println;
delay(1000);
}
Если вам интересно увидеть, как в действительности выполняются взаимодействия через интерфейс I2C, просто загляните в файлы библиотеки. Например, исходный код библиотеки RTClib хранится в файлах RTClib.h и RTClib.cpp. Эти файлы находятся в папке libraries/RTClib.
Например, в файле RTClib.cpp можно найти определение функции now:
DateTime RTC_DS1307::now {
Wire.beginTransmission(DS1307_ADDRESS);
Wire.write(i);
Wire.endTransmission;
Wire.requestFrom(DS1307_ADDRESS, 7);
uint8_t ss = bcd2bin(Wire.read & 0x7F);
uint8_t mm = bcd2bin(Wire.read);
uint8_t hh = bcd2bin(Wire.read);
Wire.read;
uint8_t d = bcd2bin(Wire.read);
uint8_t m = bcd2bin(Wire.read);
uint16_t y = bcd2bin(Wire.read) + 2000;
return DateTime (y, m, d, hh, mm, ss);
}
Функция Wire.read возвращает значения в двоично-десятичном формате (Binary-Coded Decimal, BCD), поэтому они преобразуются в байты с помощью библиотечной функции bcd2bin.
В формате BCD байт делится на два 4-битных полубайта. Каждый полубайт представляет одну цифру двузначного десятичного числа. Так, число 37 в формате BCD будет представлено как 0011 0111. Первые четыре бита соответствуют десятичному значению 3, а вторые четыре бита — значению 7.
В заключение
В этой главе вы познакомились с интерфейсом I2C и приемами его использования для организации взаимодействий плат Arduino с периферийными устройствами и другими платами Arduino.
В следующей главе мы исследуем еще одну разновидность последовательного интерфейса, используемого для взаимодействий с периферией. Он называется 1-Wire. Этот интерфейс не получил такого широкого распространения, как I2C, но он используется в популярном датчике температуры DS18B20.
8. Взаимодействие с устройствами 1-Wire
Шина 1-Wire служит целям, похожим на цели шины I2C (глава 7), то есть она обеспечивает возможность взаимодействий микроконтроллеров с периферийными устройствами посредством минимального количества линий передачи данных. Стандарт 1-Wire, разработанный в компании Dallas Semiconductor, свел потребность в линиях до логического минимума — всего одной. Шина имеет более низкое быстродействие, чем I2C, но обладает интересной особенностью — паразитным питанием (parasitic power), позволяющее подключать периферийные устройства к микроконтроллеру всего двумя проводами: GND (ground — земля) и комбинированным проводом питания и передачи данных.