0 前言& F/ u" l& |* F$ n7 k* i 自己的主要目的是学习BLE相关的知识,以及其具体的应用。因此不会像前一小节那样,组成那么长链路的系统。为最佳的学习BLE,就需要组成最小的闭环回路。 2 g% U' ]- E4 W8 A 1 最小闭环回路7 A& |( ~1 M: B 最小闭环系统,就是STM32WB的开发板和笔记本组成的系统。现在基本的笔记本自带蓝牙。9 C" \9 N- r! d) t# E$ y8 X$ t 1 3 K6 y, B' R0 f' C 7 c2 h* {1 H0 g# A8 a' E! _; i 9 C8 _) F- h: A# U 8 V. i4 V2 S" D 2 系统软件环境4 ^; H h8 N5 v0 F- `5 s' r6 I" t 在开发板中的软件使用的是:P-NUCLEO-WB55.Nucleo\Applications\BLE\BLE_HeartRate项目工程。 笔记本使用上位机是自己编写的python代码。/ d/ t! z4 E) Z$ `0 S9 }4 B+ m3 ~ 2 我们将开发板当作外围设备。将笔记本作为中心设备。. w9 H ?5 w3 |# {+ t4 | 3 连接实验 3.1 发现设备 下载好单片机程序,给单片机上电。 在笔记本设置中打开蓝牙,并点击添加蓝牙。 3 可以看到我们的设备HRSTM。8 O e8 i0 w( K6 S& }, c8 E0 k 接下来使用我编写好代码:, x! e8 S3 Z% z: Z3 ~. d2 e- E; I- L import bleak.backends.dotnet.discovery as Discovery/ u: N7 o" E4 E$ @6 v/ {$ ^) n import asyncio7 W3 C# o+ a9 ^* X% Z5 V async def run(): devices = await Discovery.discover()6 R4 k! i, U3 b$ W# y6 l for d in devices:; w% x5 j0 ^, ? print(d) loop = asyncio.get_event_loop()! z1 c x4 k; T1 g+ N8 \ loop.run_until_complete(run())# q8 j7 W9 V- b/ I5 M 在输出窗口可以看到可以被发现了的蓝牙:) S" v$ C: N$ F5 A8 b! u/ ]9 I B8:7C:6F:47:81:BF: MiKettle 6B:96:A5:AF:06:A7: Apple, Inc. (b'\x10\x05Q\x1c\x82.\xec') 80:E1:26:00:68:7C: HRSTM6 S8 g3 e L+ v' a Q 我们也可以看到我们的蓝牙应用HRSTM。其中,一个很重要的东西就是设备的ID,这个是我们连接的一个关键,就和电话号码一样,而HRSTM就是持有人的别名。 9 D _$ o* l6 g% z4 d( M! @% o 8 A& i3 F- N4 R4 g1 c* d: ^ 3.2 连接和发现服务 接下来,我们应用上面的地址,来连接和发现一下HRSTM有哪些服务:3 }8 L5 Z6 _" T! o4 J1 p async with BleakClient(address, loop=loop) as client: x = await client.is_connected()* z2 ]1 x( |' @ log.info("Connected: {0}".format(x)) log.info("[Service] {0}: {1}".format(service.uuid, service.description)) for char in service.characteristics:! d0 J/ ^& L: t, I if "read" in char.properties:% W$ N( @- g6 p$ N0 {# J try: value = bytes(await client.read_gatt_char(char.uuid)) except Exception as e: value = str(e).encode()8 F6 {3 C, E8 P' |1 f else: value = None log.info( "\t[Characteristic] {0}: ({1}) | Name: {2}, Value: {3} ".format(! D6 ^9 ~- |" v- H: g4 ?" E- L char.uuid, ",".join(char.properties), char.description, value4 ]6 |. f- l/ }7 i% x; N ) ) o8 W4 m W" t4 B for descriptor in char.descriptors: value = await client.read_gatt_descriptor(descriptor.handle) log.info( "\t\t[Descriptor] {0}: (Handle: {1}) | Value: {2} ".format( descriptor.uuid, descriptor.handle, bytes(value) ) ) # ]% W: a0 x5 v& k 输出的结果:" f6 B% x% y6 E) x Connected: True( p0 C/ T f' F: ], e# H! R+ y+ Z1 e [Service] 00001801-0000-1000-8000-00805f9b34fb: Generic Attribute Profile9 d& ~: V0 o0 n6 ~5 j [Characteristic] 00002a05-0000-1000-8000-00805f9b34fb: (indicate) | Name: , Value: None8 T7 O5 \, C! Q& L" Y! X [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'6 }) i3 o& p, F/ S* b% K! g [Characteristic] 00002a01-0000-1000-8000-00805f9b34fb: (read,write-without-response,write,authenticated-signed-writes) | Name: , Value: b'@\x03'& r g/ W# ~2 i3 G* x [Characteristic] 00002a04-0000-1000-8000-00805f9b34fb: (read) | Name: , Value: b'\xff\xff\xff\xff\x00\x00\xff\xff' [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' [; }% ^! Q. C& m4 e" H8 {+ q [Descriptor] 00002902-0000-1000-8000-00805f9b34fb: (Handle: 18) | Value: b'\x00\x00'1 s6 x$ L0 c$ n- J, b [Characteristic] 00002a38-0000-1000-8000-00805f9b34fb: (read) | Name: , Value: b'\x04' [Characteristic] 00002a39-0000-1000-8000-00805f9b34fb: (write) | Name: , Value: None `8 V* N+ c1 G9 ~6 Q$ ^" m. L: t : K: B: S* u# u& e! W/ J& r 观察,返回的信息,我们大致可以通过,服务、特性、描述等知道其性能和功能。其中,发现UUID都是单片机中定义好的,在UUID.h 文件目录下:7 s8 Q, t d# V% \: M4 q* F0 m /* UUIDs for Heart Rate Service *// z& @/ a) ~! ~7 P. V #define HEART_RATE_SERVICE_UUID (0x180D) #define CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID (0x2902)% Z; ^+ v. {3 G/ N8 g, W! E t #define HEART_RATE_MEASURMENT_UUID (0x2A37)6 [) w5 W4 I5 E; @$ h #define SENSOR_LOCATION_UUID (0x2A38)7 U) E" _- B6 `: X8 H1 v3 |! R #define CONTROL_POINT_UUID (0x2A39) ( U& q0 C! P, W8 E) V9 F 3.3 通知和获取数据+ F/ t& J G5 M$ z 通过STM的蓝牙软件,发现软件是有数据传递的。- s' P O6 S, c# ^+ D: @ 4 + a6 v! x2 d0 B; C$ ^ X, r& H& }3 x & l; {) q4 S6 P5 k$ F% n 其采用的方式是通知的方式,我是用了一下程序:5 X9 f! z( ?9 K4 R0 S: y def notification_handler(sender, data): # strs=data.hex print(f"{sender}: {data}") byarray = bytearray(data) J+ ?7 ^! Q$ m/ |3 J% K7 D6 _& Y print(byarray.hex()) async def run(address, loop, debug=False): async with BleakClient(address, loop=loop) as client:+ T) A2 T' e" e/ I x = await client.is_connected() await client.start_notify(CHARACTERISTIC_UUID, notification_handler) await asyncio.sleep(5.0, loop=loop)5 a$ [) \' N- d await client.stop_notify(CHARACTERISTIC_UUID) if __name__ == "__main__": if __name__ == "__main__": address = ('80:E1:26:00:68:7C') #你的地址- X5 g1 T/ d1 R- v loop = asyncio.get_event_loop()6 j3 ~9 O3 {( g: S/ B loop.run_until_complete(run(address, loop, True)) e: I/ i {$ Q: N7 Z 返回了一下数据: 00002a37-0000-1000-8000-00805f9b34fb: bytearray(b'\x1f7\x00\x14\x00\x00\x04') 1f3700140000048 n$ G8 q' U$ g% r3 S: A1 r 00002a37-0000-1000-8000-00805f9b34fb: bytearray(b'\x1f6\x00\x1e\x00\x00\x04') 1f36001e0000042 G0 Z* W3 u$ O5 s 00002a37-0000-1000-8000-00805f9b34fb: bytearray(b'\x1f4\x00(\x00\x00\x04') 1f340028000004 7 q% F9 g0 j" s 其中00002a37是HEART_RATE_MEASURMENT_UUID ,数据是十六进制的1f36001e000004,其中0x36是心跳,1e是能量消耗,我将能量变化修改为,每次+10,从每次读回的值就可以看到。2 b8 o$ v7 I8 s/ o3 K3 F/ b# r! P HRSAPP_Context.MeasurementvalueChar.EnergyExpended += 10;/ n; e; H" u) D& | 4 小结 以上步骤,从发现蓝牙,连接蓝牙,获取蓝牙服务,以及获取数据。其实,实验中还有许多的小问题,比如指示灯的闪烁,为啥STM官方的APP可以直接连接,自己的却不行? 我相信,在后面一步一步的代码解析,就会解释这些现象。' f* M. A: O; @ 7 G' | E) S( Q) q" j- ~' j ) L0 ]' E" |. j; {! \ 9 p) Y- e' x& I( \: O. O; V: m/ f5 C/ z) I |
4月25日培训|基于ST 双核多协议STM32WB55的Matter方案开发
基于STM32WB55的配置串口打印Debug经验分享
基于创建STM32WBA BLE_Custom工程经验分享
来看直播了,就在明天 | STM32 Matter 解决方案,轻松实现智能家居无缝连接
基于STM32WB55开发之套件概述(1)
基于STM32WB55开发之监测STM32WB连接状态(1)
基于STM32WB55开发之修改蓝牙地址(2)
STM32WB基于Custom Template实现客户定制BLE私有协议
如何基于STM32WB一次性烧写FUS+STACK+APP
【STM32WB55评测】评测四 蓝牙mesh摸索(二)