|
0 前言 自己的主要目的是学习BLE相关的知识,以及其具体的应用。因此不会像前一小节那样,组成那么长链路的系统。为最佳的学习BLE,就需要组成最小的闭环回路。 1 最小闭环回路6 Q0 [+ n, j; V X9 m 最小闭环系统,就是STM32WB的开发板和笔记本组成的系统。现在基本的笔记本自带蓝牙。 1
: {3 G" p4 b9 X9 k # Q4 ~' e6 k: K/ b3 o- J( j 2 系统软件环境% N8 L( u4 @* p- r 在开发板中的软件使用的是:P-NUCLEO-WB55.Nucleo\Applications\BLE\BLE_HeartRate项目工程。 笔记本使用上位机是自己编写的python代码。 2
8 a. R: J( Q$ v* @9 d; m9 r( ?/ W 我们将开发板当作外围设备。将笔记本作为中心设备。$ W+ | G% h0 w3 i" \# g, {4 M 3 连接实验4 K2 {3 V$ O, R, \! o- [ 3.1 发现设备4 T* Z- j3 ^. X+ K" Q9 n1 [- | 下载好单片机程序,给单片机上电。( K+ Y7 N; m$ }+ [, r 在笔记本设置中打开蓝牙,并点击添加蓝牙。 3
) R: z( V& j f7 x, p# f) S5 F+ A! S ! A; ?8 i; U3 y b 可以看到我们的设备HRSTM。2 X6 N' N- o+ X1 l: p* {3 Z9 V 接下来使用我编写好代码:7 Z" s1 t6 N8 p+ e! u2 B" S import bleak.backends.dotnet.discovery as Discovery import asyncio async def run():# {* M( _% x' @9 q$ |9 ]3 T0 J devices = await Discovery.discover() for d in devices: print(d)3 G8 y4 y! s9 E loop = asyncio.get_event_loop()4 M8 [1 I7 X. T/ a" p loop.run_until_complete(run())! ]8 B- k8 _' h3 V1 j/ O 在输出窗口可以看到可以被发现了的蓝牙: B8:7C:6F:47:81:BF: MiKettle; A C* B/ B& A' l! b 6B:96:A5:AF:06:A7: Apple, Inc. (b'\x10\x05Q\x1c\x82.\xec') 80:E1:26:00:68:7C: HRSTM : b) F0 h- w+ h' ?8 B( i 我们也可以看到我们的蓝牙应用HRSTM。其中,一个很重要的东西就是设备的ID,这个是我们连接的一个关键,就和电话号码一样,而HRSTM就是持有人的别名。8 T$ w! k! }# z+ f & p" Q, a# A+ c9 o; [/ @ 3.2 连接和发现服务8 E m- c) b- J8 z$ s) L6 Z 接下来,我们应用上面的地址,来连接和发现一下HRSTM有哪些服务:, M$ W. l2 E1 D6 H8 S- _3 n6 U async with BleakClient(address, loop=loop) as client: x = await client.is_connected() log.info("Connected: {0}".format(x))- ]5 a6 X+ | K1 o" Z log.info("[Service] {0}: {1}".format(service.uuid, service.description))" U' C. Z2 Z, f; a$ k for char in service.characteristics:- ^) L$ M+ i- k* ]1 D# e, E2 h if "read" in char.properties: try: value = bytes(await client.read_gatt_char(char.uuid)) except Exception as e: value = str(e).encode()3 w% g* | c" h3 @ else: value = None log.info(* K6 S; Q) |: H. @; U4 w4 k "\t[Characteristic] {0}: ({1}) | Name: {2}, Value: {3} ".format(7 V1 x# i4 N' ^; S8 ~: B2 ^. V char.uuid, ",".join(char.properties), char.description, value ) )1 S( J& k1 s+ q4 k/ U for descriptor in char.descriptors:: _! a. {3 v5 O2 v1 c/ b' O! p value = await client.read_gatt_descriptor(descriptor.handle) log.info( "\t\t[Descriptor] {0}: (Handle: {1}) | Value: {2} ".format(5 n& n' Y! u$ N) l! k) Y descriptor.uuid, descriptor.handle, bytes(value)2 [# |" i. E. \& | ) )4 d& l# q2 X) l' u: y 输出的结果: Connected: True" r7 w1 o$ H" z" p [Service] 00001801-0000-1000-8000-00805f9b34fb: Generic Attribute Profile [Characteristic] 00002a05-0000-1000-8000-00805f9b34fb: (indicate) | Name: , Value: None [Descriptor] 00002902-0000-1000-8000-00805f9b34fb: (Handle: 4) | Value: b'\x02\x00' [Service] 00001800-0000-1000-8000-00805f9b34fb: Generic Access Profile- J9 f) Q4 M* l* T$ K [Characteristic] 00002a00-0000-1000-8000-00805f9b34fb: (read,write-without-response,write,authenticated-signed-writes) | Name: , Value: b'STM32WB' [Characteristic] 00002a01-0000-1000-8000-00805f9b34fb: (read,write-without-response,write,authenticated-signed-writes) | Name: , Value: b'@\x03' [Characteristic] 00002a04-0000-1000-8000-00805f9b34fb: (read) | Name: , Value: b'\xff\xff\xff\xff\x00\x00\xff\xff'; y/ Z1 i* a: X8 u' Z/ T) W, L; J [Service] 0000180a-0000-1000-8000-00805f9b34fb: Device Information [Characteristic] 00002a29-0000-1000-8000-00805f9b34fb: (read) | Name: , Value: b'STM\x00'! v1 v( w* v9 ^$ i% M7 ?7 S [Service] 0000180d-0000-1000-8000-00805f9b34fb: Heart Rate [Characteristic] 00002a37-0000-1000-8000-00805f9b34fb: (notify) | Name: , Value: None$ Z/ w% R. X/ W! \7 }- }6 f1 C: B6 _ [Descriptor] 00002902-0000-1000-8000-00805f9b34fb: (Handle: 18) | Value: b'\x00\x00'# H' D6 D) t# N; x; O [Characteristic] 00002a38-0000-1000-8000-00805f9b34fb: (read) | Name: , Value: b'\x04'% A0 x: o$ R, P2 B+ A5 A" z+ C [Characteristic] 00002a39-0000-1000-8000-00805f9b34fb: (write) | Name: , Value: None 观察,返回的信息,我们大致可以通过,服务、特性、描述等知道其性能和功能。其中,发现UUID都是单片机中定义好的,在UUID.h 文件目录下:6 F7 L3 r7 \. q) x* @8 s /* UUIDs for Heart Rate Service */4 D& B7 S% w: h% E- D% L #define HEART_RATE_SERVICE_UUID (0x180D) #define CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID (0x2902) #define HEART_RATE_MEASURMENT_UUID (0x2A37); ^5 A- k& x* V' e4 L #define SENSOR_LOCATION_UUID (0x2A38)$ t3 d9 ]% z/ J' J: m! t #define CONTROL_POINT_UUID (0x2A39), p4 N% Y; b+ J; R; U0 o 3.3 通知和获取数据 通过STM的蓝牙软件,发现软件是有数据传递的。+ l5 ]' }) r" e 4
+ a1 |* w O& S! I( N/ q* J, ] 其采用的方式是通知的方式,我是用了一下程序: l# G ~/ C1 L def notification_handler(sender, data):& r3 I# D' E/ ^0 K, E4 S" [8 ? # strs=data.hex6 J! f2 v& q/ |. B print(f"{sender}: {data}") byarray = bytearray(data) print(byarray.hex())) \9 w/ b4 Y) ~7 h async def run(address, loop, debug=False): async with BleakClient(address, loop=loop) as client: x = await client.is_connected() await client.start_notify(CHARACTERISTIC_UUID, notification_handler)+ Z+ w) R# t9 z4 p% I) q. e await asyncio.sleep(5.0, loop=loop) T6 D- q- e+ s, Y4 x1 k await client.stop_notify(CHARACTERISTIC_UUID) if __name__ == "__main__":/ d- P% D8 Q0 n if __name__ == "__main__": address = ('80:E1:26:00:68:7C') #你的地址 loop = asyncio.get_event_loop() loop.run_until_complete(run(address, loop, True)) k2 c q/ w: C% F6 f! m! o! P. m7 } 返回了一下数据:# E) ~" k7 t7 A/ |) a5 a; [ 00002a37-0000-1000-8000-00805f9b34fb: bytearray(b'\x1f7\x00\x14\x00\x00\x04')) Q+ {7 [6 E" G# | 1f370014000004/ S6 M4 G V* U 00002a37-0000-1000-8000-00805f9b34fb: bytearray(b'\x1f6\x00\x1e\x00\x00\x04')2 u( A1 q, x# j# W/ ~3 d: t; ] 1f36001e000004% V8 _% u/ m% V& `6 H/ t% f" e 00002a37-0000-1000-8000-00805f9b34fb: bytearray(b'\x1f4\x00(\x00\x00\x04') 1f340028000004 其中00002a37是HEART_RATE_MEASURMENT_UUID ,数据是十六进制的1f36001e000004,其中0x36是心跳,1e是能量消耗,我将能量变化修改为,每次+10,从每次读回的值就可以看到。0 t3 `% c4 c [" x, l" f HRSAPP_Context.MeasurementvalueChar.EnergyExpended += 10;2 E) r' t3 Y. V4 O! g $ H0 U$ j6 |! |* y! @ 4 小结 以上步骤,从发现蓝牙,连接蓝牙,获取蓝牙服务,以及获取数据。其实,实验中还有许多的小问题,比如指示灯的闪烁,为啥STM官方的APP可以直接连接,自己的却不行?9 I, b W! v* c! y4 J- n) n 我相信,在后面一步一步的代码解析,就会解释这些现象。% q5 X- j3 S0 {( @, R5 d9 X5 K 2 q! b F1 P6 [$ t; V- h1 B" L * P" X8 A1 U8 v* P# M |
低功耗蓝牙无线升级: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 落地指南
微信公众号
手机版