Выбрать главу

При желании можно также создать файл keywords.txt и папку examples, содержащую примеры скетчей, использующих библиотеку. Структура папок для этого примера показана на рис. 15.1.

Рис. 15.1. Структура папок примера проекта

Библиотеку проще использовать, если она находится непосредственно в папке libraries в Arduino IDE, куда устанавливаются другие сторонние библиотеки. Файлы можно править прямо в этой папке. Среда разработки Arduino IDE заметит существование библиотеки только после перезапуска, но после этого любые изменения в содержимом файлов будут учитываться во время сборки проекта автоматически.

Оригинальный скетч, на котором основана библиотека, находится в файле sketch_07_01_I2C_TEA5767, а законченную библиотеку можно загрузить по адресу http://playground.arduino.cc//Main/TEA5767Radio.

Определение API

На первом этапе определяется интерфейс, которым будут пользоваться другие.

Если вам доводилось пользоваться разными библиотеками, вы наверняка заметили, что обычно они соответствуют двум шаблонам. Самый простой иллюстрирует библиотека Narcoleptic. Чтобы задействовать эту библиотеку, достаточно подключить ее и затем обращаться к ее методам, предваряя их имена именем библиотеки Narcoleptic, как в следующем фрагменте:

#include <Narcoleptic.h>

// и потом где-то в скетче

Narcoleptic.delay(500);

Этот же шаблон использует библиотека Serial. Если библиотека поддерживает только один объект, то применение этого шаблона оправданно. Но если есть вероятность, что в скетче потребуется использовать несколько объектов, то необходим другой подход. Поскольку есть шанс, что к плате Arduino будет подключено более одного радиоприемника, данный пример попадает во вторую категорию.

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

#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); // RX, TX

Когда возникнет потребность использовать данный конкретный последовательный порт (связанный с контактами 10 и 11), достаточно создать именованный объект для его обслуживания — в данном случае mySerial — и затем выполнить в него запись, как показано далее:

mySerial.begin(9600);

mySerial.println("Hello World");

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

После импортирования библиотеки было бы желательно иметь возможность создать именованный радиоприемник и определить, какой адрес I2C он будет обслуживать. Для простоты неплохо было бы иметь на выбор два варианта: первый, с использованием адреса по умолчанию 0x60, и второй, позволяющий определять нестандартный адрес:

#include <TEA5767Radio.h>

TEA5767Radio radio = TEA5767Radio();

// или TEA5767Radio radio = TEA5767Radio(0x60);

Поскольку библиотека обслуживает УКВ-радиоприемник, она должна уметь настраивать частоту, то есть пользователь должен иметь возможность написать такой код:

radio.setFrequency(93.0);

Числовой параметр здесь представляет частоту в мегагерцах. Автор скетча хотел бы задавать частоту именно в таком виде, а не в малопонятном формате int, который передается аппаратному модулю. Библиотека должна скрывать технические детали и самостоятельно выполнять необходимые преобразования.

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

Заголовочный файл

Обычно программный код библиотеки хранится в двух файлах. Один из них называется заголовочным и имеет расширение .h. Этот файл будет указываться в скетчах в инструкции #include. Заголовочный файл не содержит выполняемого программного кода, он лишь определяет имена классов и методов в библиотеке. Далее приводится заголовочный файл примера библиотеки:

#include <Wire.h>

#ifndef TEA5767Radio_h

#define TEA5767Radio_h

class TEA5767Radio

{

private:

int _address;

public:

  TEA5767Radio();

  TEA5767Radio(int address);

  void setFrequency(float frequency);

};

#endif

Команда #ifndef предотвращает многократное импортирование библиотеки и представляет стандартный прием для заголовочных файлов.

Далее следует определение класса, который имеет приватный (private) раздел с единственной переменной _address. Эта переменная хранит адрес I2C устройства.

Общедоступный раздел (public) включает две функции для создания объекта-радиоприемника, одна позволяет указать адрес устройства, а другая не позволяет и использует адрес по умолчанию. В общедоступном разделе имеется также функция setFrequncy.

Файл реализации

Код, фактически реализующий функции, находится в файле TEA5767Radio.cpp: