Подведите итоги по последовательному порту Bluetooth, изученному за последние два дня. По человеческой версии информации не так много, поэтому в основном полагаюсь на просмотр чужих складов и документов.
Если у вас есть какие-либо вопросы по этой статье, или если вы все еще что-то не поняли, вы можете связаться через личное сообщение.
Часть Bluetooth была завершена производителем оборудования, и для связи с хостом доступны только несколько проводов. Протокол, используемый HC08 для связи с хостом, — это последовательный порт. Для управления модулем последовательного порта Bluetooth нет необходимости опрашивать 0011. Вам нужно только отправлять команды подчиненному устройству HC08 через последовательный порт.
Подключение и отключение осуществляются периферийными устройствами. После успешного соединения появляется последовательный порт. Данные, отправленные Bluetooth через последовательный порт, будут прозрачно передаваться на другой конец, и на входящие данные также будет отвечать последовательный порт. Настройка HC08 — это фактически настройка UART. Его также можно подключить к компьютеру через USB-TTL.
Теперь найдите, где находятся контакты на схеме.
PA9 и PA10 также являются входными и выходными контактами USART.
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1|RCC_APB2Periph_TIM1,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_10);
Этот stm32 имеет интегрированное оборудование USART, и для инициализации ему требуется только вызов библиотечных функций. Конкретные значения параметров представлены в предыдущих статьях.
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate=9600;
USART_InitStructure.USART_HardwareFlowControl=ENABLE;
USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
USART_InitStructure.USART_Parity=USART_Parity_No;
USART_InitStructure.USART_StopBits=USART_StopBits_1;
USART_InitStructure.USART_WordLength=USART_WordLength_8b;
USART_Init(USART1,&USART_InitStructure);
Аппаратное обеспечение выполняет только операции чтения и чтения.,При получении изменения уровня от последовательного порта,Автоматически помещать 1 байт данных в сдвиговый регистр.,ВоляUSART_IT_RXNE
Положение флага - высокий уровень。
Если установлено высокое значение, запускается прерывание, считывается один байт данных и флаг прерывания очищается. Если он не очищен, следующий байт данных не будет получен.
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_InitStructure);
Отправляемые данные часто состоят из нескольких байтов. Как определить, закончилось ли сообщение?
Общие практики включают в себя,Согласен напоследок хорошие новости,Например, когда концовка\r\n
Отметить текущее сообщение как завершенное。
В этой статье используется метод: прерывание по таймеру. Если в течение определенного периода времени нет новых данных, это означает, что текущие данные закончились.
void TIM1_UP_IRQHandler(){
if(rxBufferPointer&&millis-lastTime>10){
rxBufferPointer=0;
isOK=1;
}
millis++;
TIM_ClearITPendingBit(TIM1,TIM_IT_Update);
}
Прерывание таймера срабатывает каждую миллисекунду, и значение таймера сохраняется.
rxBufferPointer
указывает на следующий байтданныеуказатель。
Когда текущее сообщение закончится,Этот указатель должен быть сброшен на0
,логотипisOK
Установить один。Внешний мир определяет, закончилось ли сообщение,Просто взглянув наisOK
логотип的状态。
void USART1_IRQHandler(){
if(USART_GetFlagStatus(USART1,USART_IT_RXNE)==SET){
lastTime=millis;
rxBuffer[rxBufferPointer++]=USART_ReceiveData(USART1);
rxSize=rxBufferPointer;
USART_ClearITPendingBit(USART1,USART_IT_RXNE);
}
}
Если сообщение не окончено,自动Воля当前接收的данные ДепозитrxBufferPointer
указывает на следующую позицию байта。
Поместите переменные, модифицированные extern, в файл заголовка, и затем вы сможете прочитать их непосредственно после импорта этого файла заголовка.
Размер массива — 256, указатель — 8 бит и может указывать до 256 адресов памяти.
传递的消息没有结束логотип,Чтобы отметить конечное положение,нужно пройтиrxSize
Длина сообщения, когда хранилище заканчивает чтение。
Для сравнения строк требуетсяstrcmp
,Вместо использования простого==
。
Эта часть была кратко объяснена. Настройка последовательного порта Bluetooth фактически представляет собой настройку USART, поскольку методом связи между stm32 и HC08 является последовательный порт. Более подробный процесс настройки вы можете прочитать в моем предыдущем блоге.
Если у вас есть опыт создания небольших программ, вы можете пропустить эту часть.
Создать апплет WeChat
Если у вас нет AppID, вы можете зарегистрировать его и настроить так, как он будет выглядеть. Это вряд ли повлияет на последующую разработку. Мой выбор: не использовать облачные сервисы и базовые шаблоны JS.
Установить глобальный единый стиль
Поместите этот кодCVприезжатьapp.wxss
середина:
page {
font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica,
Segoe UI, Arial, Roboto, 'PingFang SC', 'miui', 'Hiragino Sans GB', 'Microsoft Yahei',
sans-serif;
}
С помощью этого кода достигается одинаковая ситуация отображения на разных устройствах.
Избавьтесь от неиспользуемых страниц
удалитьlogs
папка。
существоватьapp.json
серединаудалить"pages/logs/logs"
эта линия。
(На самом деле, если вы не удалите его, это не повлияет на ваше использование)
Чистые App() и Page()
удалитьapp.js
、index.wxml
、index.wxss
、index.js
середина的全部内容。
Затем выберите поле с□的инициализация模板。,инициализацияapp.js
иindex.js
。
В этой статье настраиваются всего три страницы, а инициализация двух других страниц аналогична описанной выше.
"pages": [
"pages/index/index",
"pages/BLE/Services/Services",
"pages/BLE/control/control"
],
Цель этого шага — отобразить отсканированные устройства Bluetooth на индексной странице. Согласно официальным требованиям WeChat, этот процесс выглядит следующим образом:
Bluetooth的可用状态и扫描状态可以существоватьwx.onBluetoothAdapterStateChange()
回调серединаполучать。
扫描的设备可以существоватьwx.onBluetoothDeviceFound()
回调серединаполучать。
Чтобы облегчить отладку:
fail
。onBluetoothAdapterStateChange
的通知结果打印существовать页面上。app.js монтирует глобальный метод обработки сбоев
App({
fail:(res)=>{
wx.showToast({
title: res.errMsg,
icon:"none"
})
}
})
index.js реагирует на события изменения состояния адаптера
Поместите сюдаonBluetoothAdapterStateChange
Отдельно упаковано,Установлен под этим. сделать структуру кода более понятной,避免существоватьonLoad()
Вложенные слои отображаются ниже。
Page({
data: {
available: false,
discovering: false
},
onLoad: function (options) {
this.onBluetoothAdapterStateChange();
},
onBluetoothAdapterStateChange() {
wx.onBluetoothAdapterStateChange(({
available,
discovering
}) => {
this.setData({
available,
discovering
})
})
}
})
Отобразите некоторые значения во внешнем интерфейсе, чтобы облегчить последующую отладку.
После включения адаптера необходимо запустить проверку. функция обработки после обнаружения устройства.
Решение здесь — добавить обнаруженное устройство в массив. Если сообщается о дублирующих устройствах,那么нужно пройти数组的.splice()
метод,Заменить новым оборудованием.
Чтобы было проще определить, есть ли дубликаты,Вы можете создать массив_deviceIds
挂载существоватьthis
Вниз,Уникальный идентификатор запоминающего устройстваdeviceId
。
Чтобы упростить структуру кода и избежать слоев вложенности, код инкапсулируется отдельно и монтируется под ним.
Событие щелчка для начала поиска:onTapDiscover
。
<button bind:tap="onTapDiscover">{{discovering?"Завершить поиск":"Начать поиск"}}</button>
Это событие требует реализации различных стратегий в зависимости от текущей ситуации:
В первых двух случаях вам необходимо очистить список сканируемых устройств перед выполнением, чтобы убедиться, что сканируемые устройства актуальны и действительны.
onTapDiscover() {
if (this.data.discovering) {
wx.stopBluetoothDevicesDiscovery();
} else {
this.setData({
devices: []
})
this._deviceIds = []
if (this.data.available) {
wx.startBluetoothDevicesDiscovery({
allowDuplicatesKey: true
})
} else {
this.openBluetoothAdapter();
}
}
},
openBluetoothAdapter() {
wx.openBluetoothAdapter({
success: () => {
wx.startBluetoothDevicesDiscovery({
allowDuplicatesKey: true
})
},
fail: getApp().fail
})
}
Для внешнего интерфейса,Суть статьи не в этом,Проведено на короткое время,специфическийwxss
Настройка переводимого кода,Настройте в соответствии с потребностями.
проходитьonTapDevice
функция,Обработка событий подключения,проходитьdata-deviceId
входящий。проходитьdeviceId
получать Служитьсписок。
После успешного подключения следует прекратить сканирование и отключить эту ресурсоёмкую операцию.
Операции со списком услуг завершаются на новой странице.
onTapDevice(e){
let deviceId=e.currentTarget.dataset.deviceid
wx.showModal({
title: 'Connected or not',
content: deviceId,
success (res) {
if (res.confirm) {
getApp().Toast("connecting");
wx.createBLEConnection({
deviceId,
success:()=>{
wx.stopBluetoothDevicesDiscovery();
wx.navigateTo({
url: `/pages/BLE/Services/Services?deviceId=${deviceId}`
})
}
})
}
}
})
}
На этом этапе относительно мало операций.,所以可以直接Воляполучать Служитьсписок的метод定义существоватьonLoad
внутри。
Если вы вернетесь на предыдущую страницу,意味着середина断连接。所以需要существоватьonUnload
методсередина断开当前连接。
onUnload
метод会существовать当页面的生命周期结束时自动执行。
Конкретный код будет представлен в исходном коде позже. В этом проекте не используются сторонние библиотеки компонентов, это родной Аплет. WeChat, совместимый с большинством сред.
Это самая сложная часть статьи. (Это не сложно, когда вы это поймете)
Вначале я просканировал несколько сервисов, каждый с несколькими подписями, и не знал, что делать. Хотя некоторые функции имеют атрибут уведомления, при попытке уведомления по-прежнему выдается сообщение об ошибке. Или нет ответа от чтения или записи. Текущее решение состоит в том, чтобы просмотреть характеристики службы, попробовать прочитать/записать/уведомить и установить текущие успешные характеристики службы в обратном вызове успеха. В настоящее время нормальная связь возможна на HC08. Раньше я понимал, что нужно одновременно выполнять чтение/запись/уведомление о функции. Но на самом деле он может быть разбросан по нескольким функциям, работающим вместе для выполнения одной и той же услуги.
Для упрощения структуры кода принят командный режим. Каждая кнопка выполняет один и тот же метод, но передаваемые параметры команды различны.
HC08ОтправилданныесуществоватьonBLECharacteristicValueChange
середина处理。вместоread,Я не знаю, что делает Рид в данный момент.
Отправляется ArrayBuffer, и при отправке его необходимо преобразовать в ArrayBuffer. Его необходимо реализовать:
str — это строка,hex - это шестнадцатеричный код,Окончательная форма выражения также является строкой,abдаArrayBuffer,Этот видданные Потоковая форма。2
就даto
,Чтобы избежать неприятностей,То же произношение,Просто пишу2
。
Пожалуйста, обратитесь к исходному коду конкретного процесса.
репозиторий кода:https://github.com/WuShFeng/BLE
Первый молодой полноприводный автомобиль на новой энергии
Эта статья написана в начале учебного года, и ее много раз прерывали. Я хотел написать много вещей, но забыл. Добавлю еще, когда вспомню.