你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

[STM32WB 蓝牙探学] 2 BLE的连接与操作

[复制链接]
ziziran 发布时间:2020-5-23 16:48
0 前言2 N9 K* Y, s/ L
自己的主要目的是学习BLE相关的知识,以及其具体的应用。因此不会像前一小节那样,组成那么长链路的系统。为最佳的学习BLE,就需要组成最小的闭环回路。
2 s5 c3 w) m$ U' p/ O
2 q; t% A- Z' X2 J2 \; @/ G; M1 最小闭环回路5 o- p1 U) d) O# q. Z3 }3 A* G! \
最小闭环系统,就是STM32WB的开发板和笔记本组成的系统。现在基本的笔记本自带蓝牙。6 P" h" @) i6 y2 i! i( j$ w( _/ c# D

1

1

8 v; G2 _$ D8 w; P3 U4 t9 E5 Q
3 Y' e+ J& |( Q, }0 h% Z
/ P  X$ f8 L- \- W

+ g' F: Y/ R  O+ S3 M. x! `, J, ^! s4 P8 S) f# F
2 系统软件环境
2 T( n$ @% g7 _" p8 T" X在开发板中的软件使用的是:P-NUCLEO-WB55.Nucleo\Applications\BLE\BLE_HeartRate项目工程。5 k8 k+ e# t: }7 ~* N' u3 K3 p
笔记本使用上位机是自己编写的python代码。; P( f8 M0 i) E8 I5 G

2

2

# U  u% T& ^+ L
0 j: }1 f) y2 n; u7 n' o8 _% X我们将开发板当作外围设备。将笔记本作为中心设备。% i" e% `! i2 ^; r& a
# P! F7 U1 J1 j* A- K3 M8 f8 U& e7 L
3 连接实验7 ^7 u( F4 c3 p8 q; F# a
3.1 发现设备
" R1 u( L2 U: D; ~; b" A: f下载好单片机程序,给单片机上电。
7 D- h% y$ U9 E& ?在笔记本设置中打开蓝牙,并点击添加蓝牙。# d, O% V' x, B& V' c

3

3
( ~) V6 z$ ?% O! e

' B; ^, }8 U5 k3 P  m" H
$ ]1 i6 o; G# i; M+ H: M4 \可以看到我们的设备HRSTM。' m' _5 S  ~2 l( z
接下来使用我编写好代码:% Q# N9 Y4 f$ J0 v& u2 H
import bleak.backends.dotnet.discovery as Discovery
, M: h$ k' @4 Z/ L/ b4 y7 F/ jimport asyncio
. a8 e9 |8 f6 h! g( y  ^- u: Rasync def run():" l7 I0 I1 B7 X7 p& \. |1 B5 g
    devices = await Discovery.discover(): e7 q+ U3 n" K$ X' O9 t8 k% r
    for d in devices:
" w( }/ q& c& X# f        print(d)7 {# I% |) }3 R4 D
loop = asyncio.get_event_loop()
5 S3 t3 ]% S5 {loop.run_until_complete(run())9 E& q6 C5 }5 m  H0 B

* g; W1 x$ f8 N& J% t在输出窗口可以看到可以被发现了的蓝牙:# v6 O3 a5 d. N; X  ~
B8:7C:6F:47:81:BF: MiKettle1 t9 m  q1 `- @. S8 _
6B:96:A5:AF:06:A7: Apple, Inc. (b'\x10\x05Q\x1c\x82.\xec')7 n+ N8 R! P7 ?, M4 ?6 M
80:E1:26:00:68:7C: HRSTM
! B' V6 @6 t6 U0 @: ?0 Z% U+ d2 X4 h* L
我们也可以看到我们的蓝牙应用HRSTM。其中,一个很重要的东西就是设备的ID,这个是我们连接的一个关键,就和电话号码一样,而HRSTM就是持有人的别名。
6 o, s1 V; z0 M. W' a* ?* C( b. c1 J6 }
" ]7 O8 o# V, e5 U
3.2 连接和发现服务& o8 z1 y9 Z7 A/ |6 e4 f
接下来,我们应用上面的地址,来连接和发现一下HRSTM有哪些服务:; H( B# o+ M" F9 R( S; {) g3 z( }$ ?
async with BleakClient(address, loop=loop) as client:
; z+ G) P' ^, D7 E* |  c    x = await client.is_connected()
( {& c# d9 T3 L2 e5 h1 y" p    log.info("Connected: {0}".format(x))
4 b' \% K" X7 b0 _5 ~        log.info("[Service] {0}: {1}".format(service.uuid, service.description))0 U: d( p5 P/ [) N: n
        for char in service.characteristics:
* Q# ^/ M1 ]3 E4 l6 ^            if "read" in char.properties:
% n3 r1 B) F  y3 X0 w0 l3 q                try:
% c2 I; o, x( }3 O# h                    value = bytes(await client.read_gatt_char(char.uuid))7 E6 }# Y" L& X' s2 B) s  L
                except Exception as e:
. h0 H5 c) Q7 z4 w  E' M                    value = str(e).encode()8 H, C; Q* C. R) _- E
            else:
4 X9 m# e: p' X                value = None
2 p* o5 ]* B3 f8 C. J* nlog.info(
: r8 @, l; n/ s3 D8 m( d% H+ A  p                "\t[Characteristic] {0}: ({1}) | Name: {2}, Value: {3} ".format(2 p  @3 l( d1 {+ f) \5 E
                    char.uuid, ",".join(char.properties), char.description, value
. K: x. p3 k5 d: e                ), D& s1 P# X/ D( a) m' d
            )( X& q+ E) Z& B% |3 i' ^9 y
            for descriptor in char.descriptors:: y- b0 M& m3 `8 T. l* b3 ?
                value = await client.read_gatt_descriptor(descriptor.handle)
' m  w: d! ^/ Q5 r# P# c) W4 F                log.info(4 R6 x& c, K" G
                    "\t\t[Descriptor] {0}: (Handle: {1}) | Value: {2} ".format(0 o" o" R9 a! {9 B4 G
                        descriptor.uuid, descriptor.handle, bytes(value)7 S7 a( v' J+ K
                    )
) g5 Z, a, E: S: }) B                )
% O% c, R3 J# D9 J' r: h
9 O/ ^& S1 i$ `# G4 o输出的结果:
3 D) A" O6 t+ K! `* _Connected: True
! a' c# {" ^% Y  _* n; F/ b5 k$ H[Service] 00001801-0000-1000-8000-00805f9b34fb: Generic Attribute Profile
, D, P: c% V0 f1 w& P) D% C) K7 H8 _         [Characteristic] 00002a05-0000-1000-8000-00805f9b34fb: (indicate) | Name: , Value: None
# T9 o# D9 p+ ^6 E; |9 |: N/ P                   [Descriptor] 00002902-0000-1000-8000-00805f9b34fb: (Handle: 4) | Value: b'\x02\x00'
# d8 b2 G% |, J. ~! t4 Y[Service] 00001800-0000-1000-8000-00805f9b34fb: Generic Access Profile
8 W- P+ C1 @$ j2 }2 {         [Characteristic] 00002a00-0000-1000-8000-00805f9b34fb: (read,write-without-response,write,authenticated-signed-writes) | Name: , Value: b'STM32WB': @8 @# z3 S; D
         [Characteristic] 00002a01-0000-1000-8000-00805f9b34fb: (read,write-without-response,write,authenticated-signed-writes) | Name: , Value: b'@\x03'1 h( y( p4 P% S$ l" v" O
         [Characteristic] 00002a04-0000-1000-8000-00805f9b34fb: (read) | Name: , Value: b'\xff\xff\xff\xff\x00\x00\xff\xff'
( s/ G7 h3 l0 c5 e4 _, Z[Service] 0000180a-0000-1000-8000-00805f9b34fb: Device Information. V, q6 q4 P2 n( |+ X  ~! [6 W
         [Characteristic] 00002a29-0000-1000-8000-00805f9b34fb: (read) | Name: , Value: b'STM\x00'
- r# s# K% H( m" i! _7 p[Service] 0000180d-0000-1000-8000-00805f9b34fb: Heart Rate
0 j9 g) ?3 [' Q6 J/ t" _, r2 f         [Characteristic] 00002a37-0000-1000-8000-00805f9b34fb: (notify) | Name: , Value: None( h7 y4 y( H$ J
                   [Descriptor] 00002902-0000-1000-8000-00805f9b34fb: (Handle: 18) | Value: b'\x00\x00'- x. U5 {0 G4 H6 E& T$ r5 m& {' N
         [Characteristic] 00002a38-0000-1000-8000-00805f9b34fb: (read) | Name: , Value: b'\x04'# M  o; M5 k+ @, Y3 A, E
         [Characteristic] 00002a39-0000-1000-8000-00805f9b34fb: (write) | Name: , Value: None9 Z% g2 `6 P4 h0 p, D
& U( Y& ^* N! p' {6 m6 t. f# n
观察,返回的信息,我们大致可以通过,服务、特性、描述等知道其性能和功能。其中,发现UUID都是单片机中定义好的,在UUID.h 文件目录下:8 ~+ E+ m$ ]* j; q  F, _7 F. u2 f
/* UUIDs for Heart Rate Service */
1 Z/ `% U9 F9 I# Y/ ]' u! O* p#define HEART_RATE_SERVICE_UUID                                        (0x180D)
1 x7 r) L3 _+ D5 m# R2 S& Z#define CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID                   (0x2902)
0 b# A$ r8 }, M#define HEART_RATE_MEASURMENT_UUID                                   (0x2A37)
4 b4 q) d) ?3 l1 l; y  B- I7 y#define SENSOR_LOCATION_UUID                                           (0x2A38)$ x6 H, i, s" {% J
#define CONTROL_POINT_UUID                                             (0x2A39)4 j6 ^- L8 ^5 e7 n  M9 N4 e  i' A: C

6 a% O! j- v4 d1 d8 k# K5 s% o3.3 通知和获取数据; J) l' n# ^6 Q4 r' J! K/ }
通过STM的蓝牙软件,发现软件是有数据传递的。' v( j$ ]5 u* X) o) N: ]9 j

4

4
2 W1 A( M% ^) _  X/ g
  K2 |; b7 v) t, u# I- {

2 [4 h4 g" w! u3 ]6 e其采用的方式是通知的方式,我是用了一下程序:
7 q. C4 M5 B8 s; d2 v4 ]5 l+ a+ E0 o
def notification_handler(sender, data):
5 v9 I# u' n: G$ ]- T  b& G" D# {    # strs=data.hex! `+ x3 p% p6 Y7 e; a3 E
    print(f"{sender}: {data}")- L# U1 I8 W0 t
    byarray = bytearray(data)& R% L/ ~# V" n- G) z
    print(byarray.hex())
: _% t5 b3 i& l- Q! W
9 n8 f* u+ N/ t1 U8 u2 C6 V1 h( vasync def run(address, loop, debug=False):
6 e- @* `& n4 j- F6 v    async with BleakClient(address, loop=loop) as client:
! ]" @1 z: s5 ~8 c* _8 B' X2 d/ c        x = await client.is_connected()/ H2 \& d- F3 |  X
        await client.start_notify(CHARACTERISTIC_UUID, notification_handler)/ h9 {# g7 V3 O0 h# n2 s1 c$ q7 y
        await asyncio.sleep(5.0, loop=loop)- a7 I2 t* W# s9 V+ x
        await client.stop_notify(CHARACTERISTIC_UUID)" t9 G9 i6 @* y" f. l2 j
if __name__ == "__main__":- A/ N8 w1 r. k6 \: f% y: f$ h8 d
if __name__ == "__main__":
" ?# M8 t! o1 b4 j0 X# f    address = ('80:E1:26:00:68:7C')  #你的地址2 z/ g( _) g% g) E, o
    loop = asyncio.get_event_loop()
8 Y9 I& ~' h5 F/ s    loop.run_until_complete(run(address, loop, True))% Q+ n5 V* \$ b8 G; X. {1 Q% U
% t+ \; Q2 K- @& S, i1 k; o
返回了一下数据:
4 p, n# I( }4 L/ L% f8 O* T1 Z00002a37-0000-1000-8000-00805f9b34fb: bytearray(b'\x1f7\x00\x14\x00\x00\x04')
' k/ i% l- X8 Y' A1f3700140000043 n9 z' ~2 ^  s( P4 E' b
00002a37-0000-1000-8000-00805f9b34fb: bytearray(b'\x1f6\x00\x1e\x00\x00\x04')
8 h* X. B5 Q0 a! B: p7 S1f36001e000004
4 M3 k. W' O( m% S; X/ Q00002a37-0000-1000-8000-00805f9b34fb: bytearray(b'\x1f4\x00(\x00\x00\x04')
( j0 ^& b! b4 e! A1f340028000004
, I# Q# l8 E' U/ Y% m3 M$ p/ L% L+ ^& E* W
其中00002a37是HEART_RATE_MEASURMENT_UUID ,数据是十六进制的1f36001e000004,其中0x36是心跳,1e是能量消耗,我将能量变化修改为,每次+10,从每次读回的值就可以看到。
' Y* R. }* Z0 \HRSAPP_Context.MeasurementvalueChar.EnergyExpended += 10;% x) s1 ~. S7 k. `5 K  R! u1 Y3 C
6 c$ n* E$ E8 A# x1 F! w+ y
4 小结2 @$ A( @, N2 }0 q4 x6 g( g
以上步骤,从发现蓝牙,连接蓝牙,获取蓝牙服务,以及获取数据。其实,实验中还有许多的小问题,比如指示灯的闪烁,为啥STM官方的APP可以直接连接,自己的却不行?7 M- b; L8 q3 `5 H' {7 z
我相信,在后面一步一步的代码解析,就会解释这些现象。
( ]/ L9 n) n( W5 e- \2 j$ j, `) l; U$ b8 `

+ @: M. ~: t1 ~$ b5 j% N
9 h2 U2 s+ y0 D- Z

) B3 D: p7 Q: ?+ X* y+ ^  D. X5 x5 }) W" o- k
赞 收藏 评论0 发布时间:2020-5-23 16:48

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版