Например TDA7294

РадиоКот >Статьи >

Теги статьи: Добавить тег

О работе с Bluetooth модулями семейства BL65х фирмы Laird

Автор: Сергей Безруков (aka Ser60)
Опубликовано 31.07.2020
Создано при помощи КотоРед.

Предварительное знакомство

На момент написания, фирма Laird Connectivity выпускает 4 модуля в этом семействе: BL651, BL652, BL653, и BL654. Все они основаны на микроконтроллерах семейства nRF52 с архитектурой ARM Cortex-M4 фирмы Nordic Semiconductor. Первый из модулей построен на чипе начального уровня nRF52810, не содержашим кэш и FPU, в то время как микроконтроллер nRF52840 в последнем модуле свободен от этого ограничения и оснащён самым широким набором функций и периферии. Модуль BL653, помимо Bluetooth, может работать с безпроводными протоколами группы 802.15.4. Каждый из модулей может также функционировать как NFC tag. Настоящая статья посвящена модулю BL652 на основе микроконтроллера nRF52830, являющимся младшим братом флагмана семейства - nRF52840. Модуль имеет размеры 14×10 мм и выпускается в двух модификациях. Именно, BL652-SA, с установленной на плате чиповой антенной, и BL652-SC без встроенной антенны, но с U.FL коннектором для подключения внешней антенны. При желании, внешнюю антенну можно подключить и к модулю BL652-SA, распаяв U.FL коннектор на имеющиеся контактные площадки на плате. Аналогично, чиповую антенну можно установить и на модуль BL652-SC.

 

Программированию микроконтроллеров семейства nRF52 на языке С посвящено много статей в Интернете. Однако, особенность модулей BL652 – BL654, которой их оснастила фирма Laird, - это наличие встроенного в них на фабрике интерпретатора специально разработанного фирмой языка smartBasic. Язык этот кардинально отличается от классического Basic, а его мощный набор API и средств отладки позволяют быстро разрабатывать IoT устройства без всяких объёмных программных средств и даже без специальных дорогостоящих программаторов. Далее в статье будут представлены примеры разработки приложений на этом языке, а пока поговорим об аппаратной части.

Загрузку кода в модуль можно производить как через стандартный ARM-овский SWD интерфейс, так и через USB-UART конвертер. Самым простым и быстрым способом для начала работы с модулями является приобретение платы разработки DVK-BL652-SA / SC-0x. На этой плате, помимо самого модуля, имеется несколько кнопок, светодиодов, USB-UART конвертер, J-Link отладчик, многочисленные джамперы для коммутирования периферии, и несколько переключателей на разные источники питания, включая держатели для 3×ААА и CR2032 батарей на обратной стороне платы.

На плате также установлены стандартные разъёмы для Arduino шилдов. Мы воспользуемся одним из них для подключения к модулю сенсора температуры и влажности SI7021 наряду с подтягивающими I2C резисторами, как показано ниже.

Для дальнейших экспериментов я распаял отдельный модуль на небольшой печатной плате и установил её на безпаячную макетку. Модуль имеет 39 выводов с шагом 0.75мм, расположенных по периферии, и легко паяется паяльником в домашних условиях. На макетке помимо платы с модулем установлен сенсор Si7021 с подтягивающими резисторами и светодиод индикации соединения с нашим устройством. Файл платы под модуль для Eagle прилагается.

Схема устройства на макетке приведена ниже. Светодиод и сенсор подключены к тем-же выводам модуля, что и на отладочной плате фирмы. Красный джампер J2 замкнут для проведения экспериментов, а J1 разомкнут. Об их назначении подробнее рассказано ниже. Плата подключается через 6-штырьковый разъём к внешнему USB-UART конвертеру на основе CP2104. Можно использовать и любой другой конвертер с уровнями сигналов 3.3В, например, на основе FT232, как на отладочной плате фирмы. SWD коннектор на моей плате модуля я пока решил не устанавливать.

Первым делом следует произвести апгрейд ПО модуля. Это можно сделать как через SWD интерфейс, так и через UART [2], [3]. В обоих случаях регистрируемся на вебсайте модуля [1] и скачиваем оттуда последнюю версию ПО (на момент написания v28.10.7.2). В папке Firmware скачанного архива кликаем на файл _DownloadFirmwareUart.bat (соответственно, на _DownloadFirmwareJlink.bat в зависимости от интерфейса) и следуем инструкциям в открывающихся окнах. При апгрейде через UART появится следующее окно:

В нём выбираем COM порт связи с модулем и нажимаем OK. Вся процедура занимает чуть более минуты. Апгрейд через SWD интерфейс происходит быстрее, но нам спешить некуда и далее будет рассматриваться работа с модулем только через UART. Для этого нам потребуется установить на компьютере кросс-платформленное приложение UwTerminalX, которое легко найти через Google. Модуль дефолтно поддерживает набор из 20 AT-команд [4]. Одну из них (at i 3) можно использовать для чтения версии установленного в модуле ПО:

Как видно, апгрейд на последнюю версию ПО произведён успешно. Теперь напишем в любом текстовом редакторе тестовую программу производства измерения параметров среды с помощью сенсора Si7021 и выдачи их в окно терминала. Я использую Notepad++ с настройкой цветовой конфигурации распознавания синтаксиса, описанной в [5]. Ещё следует предварительно ознакомиться в [6] с основами языка smartBasic и его базисными API.

В строках 1 – 4 производится декларирование рабочих переменных, каждое из которых начинается служебным словом DIM (язык smartBasic не делает различия между заглавными и прописными буквами). Сенсору требуется не более 50мс для производства измерения, что контролируется таймером и его обработчиком прерывания в строках 6 – 10. В строке 12 мы инициализируем I2C интерфейс, при этом выводы модуля автоматически конфигурируются на работу с ним. Далее, в строках 14 – 19 посылаем в сенсор запрос на производство измерения (см. детали в ДШ на Si7021) и ожидаем его окончание. Как только это произойдёт, в строках 21 – 29 читаем данные влажности и температуры, и вычисляем их значения в процентах и градусах Цельсия, согласно формулам из ДШ. Эти значения выводятся на экран в строке 33. Как видно, код на языке smartBasic пока мало чем отличается от кода на С. Каждая строка кода содержит отдельное выражение языка. Двоеточия разделяют несколько выражений, помещённых в одну строку, а точки с запятой в print объединяют элементы вывода. SmartBasic поддерживает всего 3 типа данных: числовые данные, строки символов, и массивы. Если имя переменной заканчивается знаком $, то это строковая переменная. Слово OnEvent определяет обработчик прерывания соответствующего события. Оператор WaitEvent останавливает код до наступления какого-либо события, по наступлению которого вызывается соответствующий обработчик (если он присутствует в коде). Если обработчик возвращает 0 (наш случай в строке 8), то передаётся управление на следующую строку кода после WaitEvent (у нас выход в интерактивный режим). В противном случае производится ожидание следующего события. Всё это более подробно с примерами и в картинках описано в [6].

Компиляция кода пользователя и загрузка его в модуль, производится приложением UwTerminalX. Для этого кликаем правой кнопкой мыши в его окно и в открывшемся меню выбираем опцию Xcompile+Load наряду с файлом, содержащим исходный код программы (у нас I2C.sb). Успешное окончание компиляции и загрузки отображается в окне приложения. Далее подаем команду at+run “I2C” для начала выполнения кода и любуемся результатом.

Для автоматического начала выполнения кода пользователя каждый раз после ресета или подачи питания служит вывод 28 модуля. Этот вывод дефолтно притянут к земле встроенным резистором. При этом, после инициализации модуль проверяет наличие в своей файловой системе файла с именем $autorun$, и при его наличии начинает его выполнение без подачи соответствующей АТ команды. Переименуем файл с исходным кодом нашей программы в $autorun$.I2C.sb и произведём его компиляцию и загрузку. В результате в файловой системе модуля окажутся 2 файла с именами I2C и $autorun$ (все символы после префикса $autorun$ в имени файла при загрузке удаляются), и второй из них будет выполняться автоматически при размыкании красного джампера J2 на нашей плате. На демо-плате аналогичная роль возложена на джампер J12 и галку DTR в окне UwTerminalX, см. детали в User Manual на демо-плату. Таким образом, ПО модуля работает в следующих трёх режимах: интерактивный режим AT-команд, режим загрузки приложения пользователя, и режим выполнения приложения. По окончании второго и третьего режима происходит переход модуля в первый режим. Этот режим является дефолтным после сброса если только файловая система модуля не содержит файл с именем $autorun$ и уровень напряжения на выводе 28 модуля соответствует лог. 0. В таком случае дефолным режимом по подаче питания будет третий, и его можно сделать невозвратным, как будет показано ниже. Таким образом, загруженные в модуль приложения могут выполняться либо автоматически ($autorun$), либо контролироваться внешним МК посредством AT-интерфейса (команда at+run).

Получив первое представление о работе модуля, рассмотрим подробнее его начинку. Общая для всех модулей диаграмма слева посвящена аппаратной части. На ней показаны периферийные модули МК, доступные из smartBasic (ядро BL652 должно быть CM4F и следует указать блок NFC). К сожалению, на борту модуля отсутствует часовой криталл, но можно подключить внешний к выводам 24 и 25. Однако, во многих случаях он может и не понадобится, поскольку встроенный RC генератор модуля на 32 Кгц периодически программно (и прозрачно для пользователя) калибруется с помощью основного кварцевого генератора на 32 Мгц, что обеспечивает точность установки частоты первого в пределах ±250 ppm. Этого вполне достаточно для стабильной работы нижних уровней стека Bluetooth. Период калибровки можно устанавливать программно. Структура ПО модуля представлена на диаграмме справа. Оно включает драйверы коммуникационных интерфейсов (I2C, SPI, UART, и пр.), интерпретатор языка smartBasic, Bluetooth стек, и программы пользователя. Последние хранятся в специальной области энерго-независимой флеш-памяти модуля, сконфигурированной под проприетарную файловую систему. В этой системе, помимо программ, также могут храниться данные пользователя. Следует отметить, что при удалении файла из системы, освобождённое им место не может быть сразу использовано под другие файлы. Таким образом, многократные создания файлов и их удаления могут исчерпать файловую систему. Её физическое очищение требует подачи AT-команды реформатирования (at&f 1). В модуле BL652 объём доступной пользователю файловой системы для хранения smartBasic приложений и данных составляет 82Кб и 4Кб, соответственно.

Приложение Bluetooth сервера

Следующей нашей целью будет превратить вышеприведённый код работы с сенсором Si7021 в приложение Bluetooth сервера, так чтобы при соединении с ним можно было прочитать данные температуры и влажности. Исходный текст этого проекта находится в папке Server в прилагаемом архиве. Проект создан на основе примеров, разработанных производителем и состоит из двух файлов – debugHdr.sb и $autorun$.server.sb. В первом из них находятся определения переменных для отладки, и я оставлю его без комментариев. Этот файл вообще можно исключить из проекта без потери функционирования, удалив ссылки на него в строках 1, 35, 40, 46, 52, и 55 второго файла, где запрограммирована вся логика приложения. Второй файл начинается с определений констант и глобальных переменных.

Первым делом определяется базовый 128-битный идентификатор UUID для Bluetooth сервисов и характеристик приложения (строка 6). Это можно сделать, например, с помощью утилиты [8], но я просто использовал UUID фирмы Laird. На основе этого UUID будут формироваться остальные UUID приложения путём замены нулей в битах 16 – 31 на 16-битные значения в строках 7 – 9 кода. Нам потребуется один сервис с двумя характеристиками для температуры и влажности. Константа GPIO_LED полагается равной номеру пина модуля, к которому подключён светодиод, сигнализирущий о соединении клиентов с нашим сервером. Этот пин выбран таким-же, как и на демо-плате фирмы. В строке 17 приведён синтаксис объявления переменной и её инициализации, разделённые двоеточием. Как мы уже знаем, переменные с суффиксом $ дефолтно соответствуют строкам символов, а остальные - числовым значениям.

Далее следует прописать определения сервисов и их характеристик. Это делается в процедуре CreateServices(). В строке 34 определяется, так называемый, «GAP-сервис» Generic Access. Он является обязательным для всех Bluetooth устройств и содержит имя устройства, границы периода коммуникации с ним, определяет какие устройства могут с ним соединяться, и пр. В нашем случае устройство проектируется как видимое и доступное к соединению для любого клиента с периодом коммуникации от 7.5 до 100мс (устанавливается клиентом). Для этого вызывается API функция BleGapSvcInit(). Поскольку эта функция возвращает значение (см. [7]), согласно синтаксису smartBasic, она должна обязательно появиться в правой части оператора присваивания, даже если возвращаемое ей значение не используется. В нашем случае возвращаемое ей значение rc (Result Code) используется в строке 35 для отладки. Именно, если это значение будет ненулевым (что соответствует ошибке), в окно терминала процедурой DbgAssertRC() выдастся соответствующее сообщение с кодом ошибки и номером строки (34), где она произошла. Вызов этой функции не будет вставлен в код проекта если значение после слова #cmpif (у нас 0х100) не соответствует маске, определённой в строке 17 файла debugHdr.sb.

Хорошей практикой считается анализ возвращаемых API функциями значений. Однако, для прозрачности кода в нашем демонстрационном проекте я делаю это только в процедуре CreateServices(). Создание каждого нового сервиса производится в два этапа. Первый из них состоит в вызове двух API функций в строках 38 – 39, в результате чего в переменной hSvc получим ссылку на создаваемый сервис, используемую далее при определении его характеристик. На втором этапе после определения всех характеристик данного сервиса вызывается API функция в строке 54, которая приводит к транзакции сервиса в базу данных сервера. Определение всех характеристик сервиса должно производиться в промежутке между первым и вторым этапами его создания. Для определения каждой характеристики используются две API фукции, в строках 43, 45 для температуры и 49, 51 для влажности. Первый параметр API в строках 43, 49 (0х02) определяет свойства характеристики – в нашем случае “read only”. Назначение остальных параметров см. в документации [7]. Возвращаемые значения ссылок hTempChar и hHumiChar на характеристики можно использовать в коде при работе с ними, как показано ниже.

Следующим этапом является определение репортов клиентам при обнаружении и сканировании сервера в процедуре MakeAdvertReports(). Именно эта информация будет доступна клиентам при пассивном и активном сканировании, соответственно. Создание репортов производится в строках 65 и 68, в соответствии с комментариями. Репорты возвращаются в переменных advRpt$ и scnRpt$ и используются при завершении их создания API функцией в строке 81.

Мы уже близки к завершению – осталось лишь определить обработчики событий стека и периферии. Из событий стека нас здесь интересуют лишь два – момент создания соединения с клиентом, и момент разрыва соединения. В первом случае включаем светодиод LEO0, инициализируем I2C интерфейс, и запускаем таймер Timer0 для производства периодических измерений температуры и влажности. Во втором – соответственно выключаем светодиод, останавливаем таймер, возобновляем посылку оповещений (advertisements), и де-инициализируем интерфейс I2C для минимизации токопотребления.

При генерации события от таймера Timer0 посылаем в сенсор Si7051 запрос на производство измерений и включаем таймер Timer1 на 50мс. Этого времени более чем достаточно сенсору для завершения измерений перед их чтением. Последний параметр в API в строке 110 говорит о том, что таймер этот одноразовый, в отличии от Timer0, который периодический.

Генерация события от Timer1 говорит о готовности данных сенсора для чтения и записи в соответствующие характеристики базы данных сервера. Для записи характеристики сначала преобразуем её в string в строках 122, 129, что требуется для API в строках 123 и 130. Поскольку значения этих характеристик однобайтные, в строках 122 и 129 используем API с суффиксом 8.

Наконец, всё готово для, собственно, вызова всех нами созданных процедур и запуску приложения. Делать это следует в самом конце исходника после определения обработчиков прерываний на события (строки 136 – 138), поскольку функция, аналогичная по функционалу функции main() в С, в языке smartBasic не определена. По выполнении строки кода 145 наш сервер становится видимым клиентам для установки соединения. Поскольку обработчики всех прерываний возвращают значение отличное от 0, строка 150 кода делает приложение сервера невозвратным в интерактивный режим. Таким образом, получаем рабочий Bluetooth сервер всего за 150 строк кода.

Компилируем приложение и загружаем его в модуль программой UwTerminalX. Из статистики файловой системы следует, что оно занимает в ней всего 2.48 Кб из 82 возможных. С помощью системы CySmart убеждаемся, что Advertisement Report

и Scan Report скомпонованы в соответствии с нашим кодом.

Обратим внимание на MAC адрес сервера F4A031C97012, который пригодится нам для приложения клиента. При соединении с сервером также увидим в окне CySmart ожидаемую картину наличия трёх сервисов в профиле. Из них обязательный для всех Bluetooth устройств сервис Generic Attribute формируется стеком автоматически. Остальные два сервиса сконфигурированы в полном соответствии с вышеизложенным. При чтении температуры и влажности получаем 0x19 = 25°C и 0х39 = 57%, соответственно (показаны на голубом фоне ниже).

График токопотребления, в режиме отсылки оповещений с периодом 1 сек на всех трёх каналах при мощности 0 dBm, снятый инструментом Energy Profiler в составе Simplicity Studio IDE фирмы Silicon Labs, показывает среднее потребление на уровне 15 мкА, что весьма близко к лучшим Bluetooth модулям на рынке сегодня.

Приложение Bluetooth клиента

Теперь нашей целью будет создание приложения Bluetooth клиента, которое по нажатию кнопки соединится с разработанным выше сервером, прочитает из него 10 раз значения температуры и влажности с периодом 1 сек, выдаст их в окно терминала, и рассторгнет соединение с сервером до следующего нажатия кнопки. Для этого дополним схему на монтажке кнопкой, подсоединив её между общим проводом и выводом 29 (SIO_15) модуля, как и кнопка BUTTON1 на демо-плате.

Логика работы клиента на языке smartBasic, в общем, не отличается от таковой у продукции других производителей. В обработчике прерывания нажатия на кнопку мы начнём сканирование Bluetooth устройств с проверкой адреса каждого обнаруженного устройства с адресом нашего сервера. В случае совпадения установим соединение с ним и прочитаем значения обоих характеристик. Для упрощения кода мы не будем анализировать все представляемые сенсором сервисы и их характеристики, а просто прочитаем значения, расположенные по определённым адресам (handles) в базе данных сервера. Эти адреса показаны выше в окне CySmart: 0x0010 для температуры и 0x0012 для влажности. Всё сказанное реализуется в следующих строчках кода (см. файлы в папке Client):

Процедура "main()" как всегда начинается с декларирования обработчиков прерываний под используемые события (подробнее про них позже) и создания служебного буфера в RAM (строка 145), неявно используемого многими API клиента. Далее следует конфигурация задействованных выводов модуля и вход в цикл ожидания прерываний WaitEvent. В обработчике прерываний кнопки счачала запрещаем последующие прерывания от неё (строка 129), чтобы они не влияли на работу остальной части программы, и начинаем сканирование Bluetooth устройств (строка 130) на протяжении не более 5 сек. По окончании этого периода, если сканирование всё ещё будет разрешено, генерируется событие EVBLE_SCAN_TIMEOUT, а при обнаружении оповещений (advertisements) от каждого Bluetooth устройства генерируется событие EVBLE_ADV_REPORT. В обработчике последнего читаем в буфер принятое advertisement (строки 36, 44), содержащее, помимо всего прочего, MAC адрес периферийного устройства, возвращаемый в переменной periphAddr$. Далее сравниваем этот адрес с адресом нашего сервера, и в случае совпадения прекращаем сканирование и начинаем установку соединения с ним (строки 39 - 43). В параметрах API соединения (строка 42) устанавливаем таймаут в 5 сек и период обмена сообщений с сервером в интервале между 80 и 100 мс.

Если соединение с сервером не будет установлено до истечения таймаута, то генерируется событие EVBLE_CONN_TIMEOUT. В противном случае генерируется событие Bluetooth стека EVBLEMSG. В его обработчике мы сохраняем ссылку на соединение в переменной hConn, включаем светодиод индикации соединения, и запускаем таймер для периодического чтения характеристик среды из сервера (строки 63 – 66). Переменная count будет использована для прекращения соединения с сервером после 10 сеансов чтения данных.

Отсылка в сервер запроса на чтение значения характеристики осуществляется в обработчике прерывания таймера Timer0 функцией BleGattcRead(), второй параметр которой передаёт сылку (handle) на интересуемый нас аттрибут в базе данных сервера, а первый – ссылку на соединение, сохранённую ранее. После вызова этой функции следует ожидать наступления события EVATTRREAD (строки 111, 118), генерируемого по получении ответа от сервера. Если произведено менее 10 обращений к базе данных сервера, мы вызываем эту функцию дважды (строки 109, 116) для чтения обоих интересуемых нас характеристик. В противном случае, по достижении переменной count значения 10, мы останавливаем таймер, разрываем соединение с сервером, и выключаем светодиод (строки 101 – 104). Далее ожидаем момента отпускания кнопки (если она всё ещё нажата) и восстанавливаем реакцию на падающий уровень сигнала на выводе модуля, соединённого с ней (строки 105 – 107). После этого весь описанный процесс повторяется. В целях простоты кода предполагается, что сервер в момент сканирования клиентом активен и доступен к соединению.

Чтение ответа сервера на запрос значения характеристики производится API функцией BleGattcReadData() в строке 77. При этом переменная aAhndl содержит handle характеристики, а at$ - её значение, выводимое в окно терминала.

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

Приложение клиента также занимает около 150 строк кода и компилируется в загрузочный модуль объёмом чуть более 2Кб.

Виртуальный последовательный порт и OTA

Интересно, что прямо «из коробки» модуль поддерживает функции виртуального последовательного порта и загрузки ПО по воздуху (OTA update), даже если в модуль не загружено никакое приложение пользователя. Эти функции активируются путём подачи лог. 1 на пин 23 модуля (SIO_02), что достигается установкой джампера J1 на нашей схеме или, соответственно, джампера J5 на демо-плате фирмы. При этом функционирование модуля зависит от положения джампера J2 на нашей схеме или джампера J12 на демо-плате, иными словами от напряжения на выводе 28 (nAutoRUN) модуля. Для введения модуля в указанные режимы после установки джамперов следует произвести его ресет, после чего, благодаря встроенному ПО, модуль становится видимым Bluetooth сканерам под именем LAIRD BL652. Оба режима функционирования схематически показаны на следующей диаграмме.

При напряжении лог. 1 на выводе SIO_02 внешним Blietooth клиентам будет доступен сервис VSP с UUID, начинающимся с 0х569А1101. У этого сервиса, среди прочих, имеются две характеристики для обмена информацией с модулем – RX и TX. Если напряжение на выводе модуля nAutoRUN в момент ресета соответствует лог. 1, то модуль окажется в режиме VSP Bridge to UART. Всё, что записывается клиентом в характеристику TX выйдет с выводов UART модуля и может быть, например, направлено в окно терминала. Аналогично, весь ввод с терминала будет доступен удалённому клиенту через характеристику RX этого сервиса. Следует только разрешить нотификации этой характеристики в её CCCD дескрипторе. Ниже показана демонстрация работы модуля в таком режиме при использовании системы CySmart и соответствующего донгла в качестве клиента.

UUID характеристики TX начинается с 0x569A2001, а RX – с 0x569A2000. Выше я записал 3 байта 0х61, 0x62, 0x63 в характеристику TX (показана на сером фоне), что соответствует ASCII кодам строки “abc”. После их отправки увидим сообщение “abc” в окне терминала, соединённого с модулем. Если при этом нажать на клавишу “h” клавиатуры (ASCII код 0х68), то этот код примется модулем в характеристике RX, показанной выше на голубом фоне.

Если-же напряжение на выводе nAutoRUN в момент ресета будет соответствовать лог. 0 (при напряжении лог. 1 на выводе SIO_02), то вся коммуникация с клиентом вместо UART порта будет направлена модулем встроенному интерпретатору AT-комманд (режим VSP Command Mode, на диаграмме выше). Это можно использовать для загрузки в модуль программ пользователя со смартфона по воздуху (OTA update) с помощью специального и свободно доступного мобильного приложения, и очень наглядно с многочисленными картинками описано в [9]. Такой функционал удобен, например, при загрузке отлаженного приложения в продукцию на модуле в устройствах, не оснащённых UART интерфейсом. Подчеркну, что, таким способом можно загрузить в модуль только программы пользователя на языке smartBasic, а не апгрейд ПО модуля.

В заключении отмечу, что возможна разработка приложений для модуля и на языке С, например, в среде Nordik SDK с загрузкой кода инструментом J-Link через интерфейс SWD. Однако, это выходит за рамки настоящей статьи, и подробно описано в [10].

Литература

1. BL652 Series Bluetooth v5 + NFC Module
2. Upgrading BL652 Firmware via JTAG
3. Upgrading BL652 Firmware via UART
4. User Guide - BL65x AT Interface Application
5. Using Notepad and Color Syntax Highlighting - BL652
6. User Guide - smartBASIC Core Functionality v3.2
7. User Guide - BL652 smartBASIC Extensions v28.10.7.2
8. Online GUID Generator
9. OTA Loading of smartBASIC Applications Using ModuleLink
10. Using the BL652 and Nordic SDK v16.0.0 with Eclipse and GCC


Файлы:
Архив ZIP


Все вопросы в Форум.




Как вам эта статья?

Заработало ли это устройство у вас?

7 0 6
1 0 0