|
0 前言 自己的主要目的是学习BLE相关的知识,以及其具体的应用。因此不会像前一小节那样,组成那么长链路的系统。为最佳的学习BLE,就需要组成最小的闭环回路。 9 G, K% [4 ]4 O+ a) X% o 1 最小闭环回路 最小闭环系统,就是STM32WB的开发板和笔记本组成的系统。现在基本的笔记本自带蓝牙。 1
# b2 P- ~: a; O" J( i / ^. a5 `0 U @ |" t 2 系统软件环境 在开发板中的软件使用的是:P-NUCLEO-WB55.Nucleo\Applications\BLE\BLE_HeartRate项目工程。) F; u x6 J4 t! e 笔记本使用上位机是自己编写的python代码。 2
我们将开发板当作外围设备。将笔记本作为中心设备。 ) ?1 ^0 x: @: `$ Q 3 连接实验 3.1 发现设备 下载好单片机程序,给单片机上电。* E2 I: c" u. e% W/ E% T' C% g 在笔记本设置中打开蓝牙,并点击添加蓝牙。 3
! H* N/ \8 L, ~/ Y9 S m6 o 可以看到我们的设备HRSTM。; B+ r8 V7 G1 G! g 接下来使用我编写好代码: import bleak.backends.dotnet.discovery as Discovery import asyncio async def run(): devices = await Discovery.discover()6 R9 E t9 o( J0 } for d in devices:( G9 k# \- @, x9 C( F print(d) loop = asyncio.get_event_loop()9 S% Y% S" s2 G) T0 c loop.run_until_complete(run()) ) z9 o( |9 i! K# R7 \7 J% q 在输出窗口可以看到可以被发现了的蓝牙:, Y0 T8 {- U" |. ?9 Q B8:7C:6F:47:81:BF: MiKettle 6B:96:A5:AF:06:A7: Apple, Inc. (b'\x10\x05Q\x1c\x82.\xec'); c q; e* R2 J* @* v3 k: S 80:E1:26:00:68:7C: HRSTM 我们也可以看到我们的蓝牙应用HRSTM。其中,一个很重要的东西就是设备的ID,这个是我们连接的一个关键,就和电话号码一样,而HRSTM就是持有人的别名。 3.2 连接和发现服务& }2 W- l ^( S. X0 ]9 z: T' b% f 接下来,我们应用上面的地址,来连接和发现一下HRSTM有哪些服务:# x H$ t) f0 E/ \/ s async with BleakClient(address, loop=loop) as client: x = await client.is_connected()0 _ n# l' G! R# q* _4 [ log.info("Connected: {0}".format(x)) log.info("[Service] {0}: {1}".format(service.uuid, service.description)) for char in service.characteristics:) l! ]: [- G+ F b: f4 d- ]& y if "read" in char.properties:( G, t! L. A0 l& h2 H1 T/ s try:4 E+ I# s; n$ _ value = bytes(await client.read_gatt_char(char.uuid)). P q8 _5 a: l; |" M/ E except Exception as e:, @ q' V( ^ F- I; {9 m value = str(e).encode()" W0 i4 u w, V7 @8 z else:8 |1 V. C7 @" s! S- B- p value = None log.info( "\t[Characteristic] {0}: ({1}) | Name: {2}, Value: {3} ".format( char.uuid, ",".join(char.properties), char.description, value ) )+ S! j4 R- v' k for descriptor in char.descriptors: value = await client.read_gatt_descriptor(descriptor.handle) log.info(" P0 M; o9 y# f- I( R* O "\t\t[Descriptor] {0}: (Handle: {1}) | Value: {2} ".format(- x1 z' L& V# e8 o2 l T7 T5 s% v descriptor.uuid, descriptor.handle, bytes(value)& Q9 X+ q: U7 ~% o6 [. b )$ B% \; v1 h( T! r; N2 |1 N )7 C- I6 @. p4 C2 b# L8 Y' i5 E 2 t2 q' E, ^. Y3 ] n- D 输出的结果: Connected: True [Service] 00001801-0000-1000-8000-00805f9b34fb: Generic Attribute Profile [Characteristic] 00002a05-0000-1000-8000-00805f9b34fb: (indicate) | Name: , Value: None ^6 J3 R( }; p [Descriptor] 00002902-0000-1000-8000-00805f9b34fb: (Handle: 4) | Value: b'\x02\x00' [Service] 00001800-0000-1000-8000-00805f9b34fb: Generic Access Profile [Characteristic] 00002a00-0000-1000-8000-00805f9b34fb: (read,write-without-response,write,authenticated-signed-writes) | Name: , Value: b'STM32WB'$ m# n5 n1 E) f1 S; P [Characteristic] 00002a01-0000-1000-8000-00805f9b34fb: (read,write-without-response,write,authenticated-signed-writes) | Name: , Value: b'@\x03'# I& v4 `4 }% T) A [Characteristic] 00002a04-0000-1000-8000-00805f9b34fb: (read) | Name: , Value: b'\xff\xff\xff\xff\x00\x00\xff\xff'( e* s" z9 j+ a [Service] 0000180a-0000-1000-8000-00805f9b34fb: Device Information [Characteristic] 00002a29-0000-1000-8000-00805f9b34fb: (read) | Name: , Value: b'STM\x00' [Service] 0000180d-0000-1000-8000-00805f9b34fb: Heart Rate [Characteristic] 00002a37-0000-1000-8000-00805f9b34fb: (notify) | Name: , Value: None" P3 h: s, g: P& f [Descriptor] 00002902-0000-1000-8000-00805f9b34fb: (Handle: 18) | Value: b'\x00\x00' [Characteristic] 00002a38-0000-1000-8000-00805f9b34fb: (read) | Name: , Value: b'\x04' [Characteristic] 00002a39-0000-1000-8000-00805f9b34fb: (write) | Name: , Value: None' F0 a. Z+ r# W# S" C! d 9 M; q$ y" x( _. w3 K# k 观察,返回的信息,我们大致可以通过,服务、特性、描述等知道其性能和功能。其中,发现UUID都是单片机中定义好的,在UUID.h 文件目录下:. s: D/ c h: c i /* UUIDs for Heart Rate Service */ #define HEART_RATE_SERVICE_UUID (0x180D) #define CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID (0x2902) #define HEART_RATE_MEASURMENT_UUID (0x2A37)6 Q4 i# w" J) m4 z. e #define SENSOR_LOCATION_UUID (0x2A38)) ] s, l# `3 m T- | #define CONTROL_POINT_UUID (0x2A39) 3.3 通知和获取数据 通过STM的蓝牙软件,发现软件是有数据传递的。 4
3 ~0 J. {% z2 G" r! r* e 其采用的方式是通知的方式,我是用了一下程序:. m: t8 a2 y6 Y' S- U def notification_handler(sender, data):+ b% A7 j: _2 c2 K Y # strs=data.hex3 y/ e A% o3 X# w print(f"{sender}: {data}") byarray = bytearray(data): K5 h9 z( O. c4 h print(byarray.hex()); X8 t( w1 j" u8 T9 }+ n async def run(address, loop, debug=False):' o! L5 e+ ?/ ~' k4 u u async with BleakClient(address, loop=loop) as client:" e0 r7 N" I0 C x = await client.is_connected()/ a' ]4 k$ _/ S await client.start_notify(CHARACTERISTIC_UUID, notification_handler) await asyncio.sleep(5.0, loop=loop)% f* ?, A! G- Z5 J. ] await client.stop_notify(CHARACTERISTIC_UUID)2 l" ~3 i6 q5 T) }! n+ X; g if __name__ == "__main__": if __name__ == "__main__":% @5 ~' l' c: E4 q5 O8 q address = ('80:E1:26:00:68:7C') #你的地址, R2 J v) i) y- z& e! ]5 j6 q loop = asyncio.get_event_loop()4 ]( U% z1 [/ Q* u& _ loop.run_until_complete(run(address, loop, True)) ) m+ t" G0 p- p+ |6 c 返回了一下数据: 00002a37-0000-1000-8000-00805f9b34fb: bytearray(b'\x1f7\x00\x14\x00\x00\x04') 1f370014000004 00002a37-0000-1000-8000-00805f9b34fb: bytearray(b'\x1f6\x00\x1e\x00\x00\x04')2 d& q! A% ]1 O. N# H5 a8 h* V, m 1f36001e000004% b9 U' O, y+ [" l Y% s% Y 00002a37-0000-1000-8000-00805f9b34fb: bytearray(b'\x1f4\x00(\x00\x00\x04')' q |, Y) l4 L 1f3400280000042 b8 s/ y [5 x$ W$ N" O . w5 H7 D6 u/ K 其中00002a37是HEART_RATE_MEASURMENT_UUID ,数据是十六进制的1f36001e000004,其中0x36是心跳,1e是能量消耗,我将能量变化修改为,每次+10,从每次读回的值就可以看到。 HRSAPP_Context.MeasurementvalueChar.EnergyExpended += 10; 0 k1 c# }/ C$ Y! } 4 小结. D, L0 `3 g' R( c1 _* m O5 m 以上步骤,从发现蓝牙,连接蓝牙,获取蓝牙服务,以及获取数据。其实,实验中还有许多的小问题,比如指示灯的闪烁,为啥STM官方的APP可以直接连接,自己的却不行?4 v* S- Z- D! t$ Y 我相信,在后面一步一步的代码解析,就会解释这些现象。8 |' M5 U5 h0 B ) s7 h& x! {; [* x' p8 C+ _ $ E2 C% t$ p( p0 x& I$ X 0 c6 p( V4 c, w 3 _; i& m. {$ B0 D+ Q& V+ [5 c |
低功耗蓝牙无线升级:STM32WB OTA 固件更新技术解析
STM32WB Zigbee 自定义集群开发实战:AN5491 应用笔记深度解读
吃透:STM32WB 上 Zigbee 睡眠终端设备开发攻略
STM32 无线 MCU HSE 频率与启动时间精确调谐实战指南
深度解读:STM32WB 2.4GHz 低成本 PCB 蛇形天线设计实战指南
经验分享 | STM32WB 双核无线 MCU 开发全流程实战指南
STM32WB 基于 Custom Template 实现 BLE 私有协议 实操开发指南
详解STM32单片机的堆栈
STM32单片机进行除零运算,为何程序不崩溃?
从照明到楼宇:STM32WBx5 BLE Mesh 落地指南
微信公众号
手机版