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

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

[复制链接]
ziziran 发布时间:2020-5-23 16:48
0 前言& F/ u" l& |* F$ n7 k* i
自己的主要目的是学习BLE相关的知识,以及其具体的应用。因此不会像前一小节那样,组成那么长链路的系统。为最佳的学习BLE,就需要组成最小的闭环回路。
  D  n( D4 a9 `$ ?2 f2 g% U' ]- E4 W8 A
1 最小闭环回路7 A& |( ~1 M: B
最小闭环系统,就是STM32WB的开发板和笔记本组成的系统。现在基本的笔记本自带蓝牙。9 C" \9 N- r! d) t# E$ y8 X$ t

1

1
( }0 F- n+ v2 O' v
3 K6 y, B' R0 f' C
7 c2 h* {1 H0 g# A8 a' E! _; i
9 C8 _) F- h: A# U

% I) t1 `7 h- m) ?. k1 H8 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项目工程。
! h- y- B2 k# D8 m+ L. }: C: q笔记本使用上位机是自己编写的python代码。/ d/ t! z4 E) Z$ `0 S9 }4 B+ m3 ~

2

2
0 z6 l8 C. V5 z' \, b/ @, \

* l3 X1 ~8 j, M5 Y1 B' O我们将开发板当作外围设备。将笔记本作为中心设备。. w9 H  ?5 w3 |# {+ t4 |

5 m% o# H/ L6 y" d! m3 连接实验
; E6 g, R, O# I1 N1 Y& a/ D3.1 发现设备
2 }! U% ~$ a" o$ Q' Y8 |8 p/ O下载好单片机程序,给单片机上电。
* M7 e$ Q) u( t# k9 {在笔记本设置中打开蓝牙,并点击添加蓝牙。
( _- ^& R& G; w* O( K% p

3

3
5 v* Q/ c* y3 e7 v9 t1 u

% n" {; H2 O6 A6 x) \
$ r& V. U" B& o9 x6 C8 @可以看到我们的设备HRSTM8 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():
5 _6 Y) u: b, c3 A2 F    devices = await Discovery.discover()6 R4 k! i, U3 b$ W# y6 l
    for d in devices:; w% x5 j0 ^, ?
        print(d)
* q6 j/ l2 ~: m& a# s2 j9 q; Cloop = asyncio.get_event_loop()! z1 c  x4 k; T1 g+ N8 \
loop.run_until_complete(run())# q8 j7 W9 V- b/ I5 M

; F7 V% c: R+ ~$ R  e; I1 I$ q在输出窗口可以看到可以被发现了的蓝牙:) S" v$ C: N$ F5 A8 b! u/ ]9 I
B8:7C:6F:47:81:BF: MiKettle
/ D8 t! M+ ]# U( q2 c6B:96:A5:AF:06:A7: Apple, Inc. (b'\x10\x05Q\x1c\x82.\xec')
6 \/ u! y* b5 r) C80:E1:26:00:68:7C: HRSTM6 S8 g3 e  L+ v' a  Q

5 K4 m, k1 D1 ?3 `7 h3 I我们也可以看到我们的蓝牙应用HRSTM。其中,一个很重要的东西就是设备的ID,这个是我们连接的一个关键,就和电话号码一样,而HRSTM就是持有人的别名。
2 q* `* x) ^" s" c! A, S/ r9 D  _$ o* l6 g% z4 d( M! @% o
8 A& i3 F- N4 R4 g1 c* d: ^
3.2 连接和发现服务
0 V' i& O5 h/ S. Q% V' l接下来,我们应用上面的地址,来连接和发现一下HRSTM有哪些服务:3 }8 L5 Z6 _" T! o4 J1 p
async with BleakClient(address, loop=loop) as client:
1 H! O, e9 {0 ]    x = await client.is_connected()* z2 ]1 x( |' @
    log.info("Connected: {0}".format(x))
' W. G' f" I  G. e* H7 ^        log.info("[Service] {0}: {1}".format(service.uuid, service.description))
) K3 m: U+ g0 }" m        for char in service.characteristics:! d0 J/ ^& L: t, I
            if "read" in char.properties:% W$ N( @- g6 p$ N0 {# J
                try:
4 R& I4 [  P3 s" K/ K& k/ Y' e                    value = bytes(await client.read_gatt_char(char.uuid))
9 g, B/ U; Y  D                except Exception as e:
  ^9 M" U4 r- o0 H+ N                    value = str(e).encode()8 F6 {3 C, E8 P' |1 f
            else:
3 K4 {4 l8 [; Z5 u                value = None
3 \( P6 f, k' Y5 Hlog.info(
6 k( J) q1 Q5 u9 D8 T/ T                "\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
                )
  ]' }6 Q2 _! j% w+ V( m            )  o8 W4 m  W" t4 B
            for descriptor in char.descriptors:
& B. x& c3 H: X0 z9 N                value = await client.read_gatt_descriptor(descriptor.handle)
, Z# f/ ]8 {' g5 s                log.info(
. t# C# n6 w$ b+ o! ^: s) ~1 H- q) L                    "\t\t[Descriptor] {0}: (Handle: {1}) | Value: {2} ".format(
! O( T6 ~# x! r+ V' F, f                        descriptor.uuid, descriptor.handle, bytes(value)
  }; e, y3 A$ h; ^6 B, r) P                    )
8 y: B4 p" j2 x# M4 i                )
3 P5 N$ X2 t3 ]" S$ O7 i& [# ]% 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'
/ F  ~+ M9 L+ M[Service] 00001800-0000-1000-8000-00805f9b34fb: Generic Access Profile
* P2 q" c- x, g! n         [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'
( I9 A  a7 ^# g; o, @, L[Service] 0000180a-0000-1000-8000-00805f9b34fb: Device Information
3 b4 m  h4 E2 W$ r9 z         [Characteristic] 00002a29-0000-1000-8000-00805f9b34fb: (read) | Name: , Value: b'STM\x00'
% W1 Q- A$ Y' y1 D' Y) R: S8 `[Service] 0000180d-0000-1000-8000-00805f9b34fb: Heart Rate
/ N$ U+ |3 Z" y8 B! e7 z  S         [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'
$ j) r' P8 J; ~5 k         [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)
( S6 [$ n/ m# n4 H+ J5 U9 }. T#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)
6 p: I) _# S$ X& H( w7 I( U& q0 C! P, W8 E) V9 F
3.3 通知和获取数据+ F/ t& J  G5 M$ z
通过STM的蓝牙软件,发现软件是有数据传递的。- s' P  O6 S, c# ^+ D: @

4

4
; g1 M: U! y1 m- F
+ 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

7 ]" |! h3 z& a) r  fdef notification_handler(sender, data):
; Q- P4 n% W4 A9 h* f! x" N3 k    # strs=data.hex
7 p3 _1 S. W5 B7 H    print(f"{sender}: {data}")
7 J! N0 O$ s+ }( k0 R- f" L    byarray = bytearray(data)  J+ ?7 ^! Q$ m/ |3 J% K7 D6 _& Y
    print(byarray.hex())
9 L% \/ |3 F0 O
' W' ]' G- S2 z. \3 s; Fasync def run(address, loop, debug=False):
) Q$ r. K+ H0 \$ _. J2 E% p    async with BleakClient(address, loop=loop) as client:+ T) A2 T' e" e/ I
        x = await client.is_connected()
& j# g  k$ G- S! n' c' }        await client.start_notify(CHARACTERISTIC_UUID, notification_handler)
( D5 g% u) `7 k" P5 n' k" ~        await asyncio.sleep(5.0, loop=loop)5 a$ [) \' N- d
        await client.stop_notify(CHARACTERISTIC_UUID)
: \) m8 Y4 d0 c9 k8 }  rif __name__ == "__main__":
. B* C( n  ^( s! p! D1 R; G! Jif __name__ == "__main__":
( n6 M3 V* Y+ T    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

% |+ D3 r* C2 S; U$ L4 ^' J返回了一下数据:
" Q- A8 W; L$ L: [+ T00002a37-0000-1000-8000-00805f9b34fb: bytearray(b'\x1f7\x00\x14\x00\x00\x04')
/ T1 u8 u2 g) _; P& t1f3700140000048 n$ G8 q' U$ g% r3 S: A1 r
00002a37-0000-1000-8000-00805f9b34fb: bytearray(b'\x1f6\x00\x1e\x00\x00\x04')
" j! N% A4 m; |# y/ e4 s0 K6 f6 k1f36001e0000042 G0 Z* W3 u$ O5 s
00002a37-0000-1000-8000-00805f9b34fb: bytearray(b'\x1f4\x00(\x00\x00\x04')
$ y; e( A; o, z: Y1f340028000004
6 e$ F$ h! o! Y+ [, k6 S5 H7 x% v' A7 q% F9 g0 j" s
其中00002a37HEART_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& |

7 W7 a5 g; L! C* U8 H- t  O) N 4 小结
" g9 f  a$ w2 z# C以上步骤,从发现蓝牙,连接蓝牙,获取蓝牙服务,以及获取数据。其实,实验中还有许多的小问题,比如指示灯的闪烁,为啥STM官方的APP可以直接连接,自己的却不行?
: z! n9 }- c; {' y+ Q2 @我相信,在后面一步一步的代码解析,就会解释这些现象。' f* M. A: O; @

$ ^$ P8 p, b$ K0 M  |& z& Q
7 G' |  E) S( Q) q" j- ~' j

1 [  g" K% f5 L4 r: c. Q+ q8 z1 r
) L0 ]' E" |. j; {! \
9 p) Y- e' x& I( \: O. O; V: m/ f5 C/ z) I
收藏 评论0 发布时间:2020-5-23 16:48

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版