HC-05蓝牙串口通信模块应该是使用最广泛的一种蓝牙模块之一了。为什么呢?
: `. R- Q0 D. j8 H3 }$ x6 J$ [9 z
因为HC05模块是一款高性能主从一体蓝牙串口模块,可以不用知道太多蓝牙相关知识就可以很好的上手。说白了,只是个蓝牙转串口的设备,你只要知道串口怎么编程使用,就可以了,实现了所谓的透明传输。
. y' Y" N, X+ m9 N# ?6 {& m
但是就是这么一个很常见的模块,网上很多的博客写的都是错的,或者都是很不详细的。 ' @ O7 F0 E9 g' s1 c! R, }
所以本文就介绍一下这款蓝牙通信模块的使用,包括蓝牙模块的调试、手机与蓝牙模块之间的传输、手机蓝牙控制STM32单片机,应该是逐渐深入的一个过程。但是这仅仅是使用,以后有时间应该会对蓝牙有一个稍微深度的学习,而不能仅仅是浮于表面,只会用。 7 V3 V- U+ N4 M& X2 e0 [
模块名称:HC-05蓝牙串口通信模块 其他模块:USB转TTL模块、手机蓝牙串口助手app 手机蓝牙串口助手软件,可以点击链接下载:蓝牙串口。因为这是我见过所有手机端界面最好看的了,其他的界面都有点太糟糕了。 ~$ Y: k5 u7 Q% X: {* d* L& f
蓝牙模块的调试准备工作USB转TTL模块与HC-05蓝牙模块的接线: 两模块共地,两模块共VCC(VCC取5V);蓝牙模块的RX接转换模块的TX,蓝牙模块的TX接转换模块的RX。如下图所示:
* m8 Y1 y ^) r- @. P

* Z- W$ B. W1 g* d( m
这个时候就要将转换模块连接到电脑上,然后利用串口调试助手进行蓝牙模块的调试。 ! z* z% r) w. V! m
蓝牙模块的调试8 [7 s# E( E3 C$ i' V) @7 z, e9 E
HC-05蓝牙串口通讯模块具有两种工作模式:命令响应工作模式和自动连接工作模式。在自动连接工作模式下模块又可分为主(Master)、从(Slave)和回环(Loopback)三种工作角色。
( |4 b8 ]/ C' }9 Y; m. `
- 当模块处于自动连接工作模式时,将自动根据事先设定的方式连接的数据传输;
- 当模块处于命令响应工作模式时能执行AT命令,用户可向模块发送各种AT 指令,为模块设定控制参数或发布控制命令。8 ^6 ~- I4 _; b' }( V. E
4 P3 q; V" |1 w D) T
怎么进入命令响应工作模式? ( |, Y9 M* R$ @9 O `' F. |0 O
进入命令响应工作模式有两种方法:
6 A, M3 Y' S8 U7 a( _. h
- 模块上电,未配对情况下就是AT模式,波特率为模块本身的波特率,默认:9600,发送一次AT指令时需要置高一次PIO11;
- PIO11 置高电平后,再给模块上电,此时模块进入AT 模式,波特率固定为:38400,可以直接发送AT指令。
- V% \1 j& k4 F/ F$ l6 Q H; q/ @( `
; m J) [- G0 o+ W8 o" \1 O/ B2 `' r. i6 i$ P
什么叫做置高一次PIO11? ( d5 _) W. {; `+ i; y& Q% f
在蓝牙模块中有一个小按键,按一下就置高一次PIO11。也就是说,第一种方法需要每发送一次AT指令按一次;而第二种方式是长按的过程中上电,之后就无需再管了,直接发送AT命令即可。
! P% `3 H& l+ a; W9 C- p
需要注意一下,两种进入命令响应工作模式的方式使用的波特率是不一样的,建议使用第二种方式。
& @, L! l# {6 W# a" F' M9 E/ P
怎么区分进了命令响应工作模式呢? ) J3 t7 p& o- F) ~
在蓝牙模块上有灯,当灯快闪的时候,就是自动连接工作模式;当灯慢闪的时候,就是命令响应工作模式。 ' Q8 Z+ b+ J8 O4 g
AT命令
# T( ~/ G6 m( m进入到命令响应工作模式之后,就可以使用串口调试助手进行蓝牙调试了。 * a2 _+ W* A9 s: f
首先有一点,AT指令不区分大小写,均以回车、换行结尾。下面介绍常用的AT指令:
* |1 F$ f0 K+ t; T8 M' ?4 E3 u , A1 q0 @5 S1 S0 i$ G
6 F1 A6 Z+ w: @ A对于AT指令,有几点注意: r3 A" c, t- s+ {
- AT+NAME?:获得设备名称,这个AT指令有很大可能性是没有返回的,因为我也看到了很多的例子……,但是其他的指令都是没有问题的,直接设置设备名称就行了;+ s3 x# o. D! i) O7 p. W. X' S) J; V
6 v. K$ f4 Y) Y. J, G5 n
7 h8 s/ ]6 |- `; x) ^. S- AT+UART?:获得串口参数,串口的参数一共有三个,波特率、停止位、检验位。其取值如下:
/ ?/ `2 Y6 v* c6 \! G I0 J
$ a" o* W+ c# p8 N+ M
* u$ g% Z, ?4 g$ }* j8 h6 }4 x8 O
串口参数
& U2 P4 [- ^6 Q) J- c8 L5 C" L+ C# ]4 M9 P4 F9 Y8 v) j" H+ K( g7 X5 s
参数名称 | 取值 | 波特率 | 2400、4800、9600、19200、38400、5760、 115200、230400、460800、921600、1382400 | 停止位 | 0:1位 1:2位 | 校验位 | 0:NONE 1:Odd 2:Even |
, x( g1 i6 q) s, k其默认值为:9600,0,0。 - f; ?) Y# N7 W& I; r, y( ^4 I
例子: 
' P# L: w; A2 D# @
本文中,蓝牙串口的波特率设置成115200。之后的内容,就会采用这个波特率来进行通讯了。
; O0 O5 c, n0 k- Q+ S手机与蓝牙模块之间的传输
6 y M/ F) n# R) Q直接将蓝牙模块与转换模块连接,再讲其连接到电脑上,蓝牙模块直接进入自动连接工作模式。
4 Q6 r7 ` W \" ^. K
此时手机打开蓝牙串口调试应用,用其来连接蓝牙模块。手机蓝牙串口助手软件,可以点击链接下载:蓝牙串口。万分推荐这款,因为界面脱离了那种黑不溜秋的感觉,比较简洁、清爽。
, m. @! H+ @. f8 J9 `# s. o
这个软件的使用:点击界面右下角蓝牙的标志,选择蓝牙进行连接。 ) ~0 N+ W$ z4 L y% Y% C( b) G$ i- t
然后在电脑上的调试助手和手机的蓝牙串口调试应用之间就可以相互传输了,比如: & W4 y' r. c% `6 Q

! b8 Y) t) b, p( { Z

* V+ S% x/ P% ?1 R. g6 p5 b
可以清楚的看到:电脑向手机发送了“hello you”,手机向电脑发送了“hello world”。 5 x: d* n1 w% b# D) W& a- D
手机蓝牙控制STM32单片机
% `6 `0 \" A, }; a之前的两个例子都是相比较而言比较简单的,这个例子将会涉及到程序的内容了。
! M3 b+ Q9 |$ T* q3 q& H4 w
4 p5 C+ \6 ^/ z X5 t9 I/ O
实现功能:手机通过蓝牙,向STM32单片机发送消息,STM32接收到消息之后原封不动的返回给手机。当然如果掌握了这个例子,也可以修改成,手机发送特定的消息,然后,STM32单片机做出相对应的动作。比如:点亮LED等、发动电机等等。
' Y$ C( F% D( W4 w* m: { 连接说明
% _: ^6 H" M- ^. X. v! t* C7 q! |
使用USART1进行试验,也就是说STM32选取PA9、PA10来和HC-05进行连接。同时手机通过蓝牙来和HC-05进行连接。
* g0 W6 T1 W$ H/ }
原理就是:手机通过蓝牙传输到HC-05上,再通过串口通信和STM32通信;而之前一般都是电脑上通过USB线转串口的方式,通过串口和STM32通信。本质上没有区别的。
8 y4 `+ \- l# a2 J& R5 Z/ y% W
这个时候就应该更加深刻地体会到了本文开篇的一句话:说白了,只是个蓝牙转串口的设备,你只要知道串口怎么编程使用,就可以了,实现了所谓的透明传输。蓝牙的相关一切都被封装起来了,都不需要接触到。 - E" w' r6 o; A0 y
STM32控制程序
( I6 n4 L0 y; U# W
3 b) W+ K. E2 B$ \0 W2 O `3 H9 ?- #include "stm32f10x.h"
. Q" Q9 t" Y9 B* D3 n. k) K: d6 } -
) C* ?8 A% ]9 }. |9 N - void My_USART1_Init(void)
& G% v ?+ n' o; E4 z - { 1 J! w; I2 A9 h7 M
- GPIO_InitTypeDef GPIO_InitStrue;
" o+ ^& C9 T A) N4 T M; L) N" i - USART_InitTypeDef USART_InitStrue;
' M! [) a% T! Y T" @% ?/ j - NVIC_InitTypeDef NVIC_InitStrue;
' o) l8 S) _, M/ A+ P& O' } - 1 E" D: Q0 m( X" q
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//GPIO端口使能 4 N8 v5 D4 x0 y, ^
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//串口端口使能
9 {$ R' J% a' ? -
7 m% u( y& @5 w - GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP;
1 T, S7 E( a4 n' R4 Q - GPIO_InitStrue.GPIO_Pin=GPIO_Pin_9;
, F+ ~* C3 d$ t1 s4 X k - GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;
5 g! p" M$ u9 k" V9 \. v: j - GPIO_Init(GPIOA,&GPIO_InitStrue); + `$ w* c* L) w: N! a
-
) J% S+ ?2 ]3 \: h - GPIO_InitStrue.GPIO_Mode=GPIO_Mode_IN_FLOATING; " d/ }) C* f& ]$ L0 g4 u+ k
- GPIO_InitStrue.GPIO_Pin=GPIO_Pin_10;
d2 a- Z" S4 ^& c- t7 n ~ - GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;
( U" F, \4 M3 l: Y - GPIO_Init(GPIOA,&GPIO_InitStrue);
+ N$ e& u+ q$ s9 e# F6 S - ( j5 C$ v6 W& y/ p7 N3 {. {
- USART_InitStrue.USART_BaudRate=115200; " ^6 | p4 i# t, J5 x1 v
- USART_InitStrue.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
2 _) h( l9 x/ L ]1 R7 H5 @$ ^ - USART_InitStrue.USART_Mode=USART_Mode_Tx|USART_Mode_Rx; * y- y' O. W8 V! C& b8 r" ^% U6 h" l
- USART_InitStrue.USART_Parity=USART_Parity_No;
) U5 g y! X! x6 H% Z/ `% u( a1 { - USART_InitStrue.USART_StopBits=USART_StopBits_1; " U# @ X' | {9 n7 X" b) @. u& ?. {
- USART_InitStrue.USART_WordLength=USART_WordLength_8b;
: a7 l$ f, C0 v/ H6 G" q' x3 F -
! O3 C6 Y3 f+ B - USART_Init(USART1,&USART_InitStrue);
; a& u7 H1 ]% P% y -
7 Q$ `$ W7 M0 D+ r! }2 @ - USART_Cmd(USART1,ENABLE);//使能串口1 ( J0 \# w W% x$ d& I
- D1 b; L8 X$ T Y; o9 d) ?" S0 A
- USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//开启接收中断 9 m0 y6 N8 E4 t/ L
-
7 p! g' F! t, X. X& q9 W; W - NVIC_InitStrue.NVIC_IRQChannel=USART1_IRQn;
3 P1 a! V- U- b+ R" G( e7 B/ ?4 H - NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE; ^2 C6 d O. ?: _% _) Q1 p& ^
- NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=1;
! u0 [3 L4 ~% P1 z - NVIC_InitStrue.NVIC_IRQChannelSubPriority=1; $ p# u' v9 b2 E; k8 n( Q
- NVIC_Init(&NVIC_InitStrue);
3 L% Y! U, X* }# |, K- U - " T" @; p; N! B8 _/ i9 m9 u0 D' H
- }
3 Y/ ~2 d/ `$ ~$ O - A3 q; h, _+ g& m* n
- void USART1_IRQHandler(void) % E: \0 p( n/ A' E7 E
- { 0 `, N# ?, D/ ^5 V4 k9 z% Q$ `
- u8 res; ( ^0 ~0 B; u- b& a/ K# \) ]0 N
- if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)
, `% c0 t, I9 F# t - {
5 P O i p9 v! F$ _6 Y - res= USART_ReceiveData(USART1); + T* F4 @5 _! c: t
- USART_SendData(USART1,res); 7 Q- B7 k8 {6 r0 `4 O4 N* |
- } 6 R/ q7 ?, G4 x, G+ `
- }
2 w' C, J" S3 H5 l0 { -
8 |8 D% \' T G% m. X6 ]& v - int main(void)
* X6 k# R: V( @ - {
% v4 M( z& C; F0 d - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
9 D3 x$ @0 L2 b, t. z - My_USART1_Init();
7 Z F3 `( d& v9 j - while(1); 9 c2 W" _. s7 d
- ) d$ Q* K8 P( G! G: O) t, C; X
- }
复制代码
% k1 O9 X1 b( u& \, g& M% u/ K区别就是,在UART实验中,USART1是和USB转串口模块连接在一起的,然后与电脑上的串口调试助手进行通信;现在改成USART1是和蓝牙模块连接在一起的,然后和手机上的蓝牙串口调试助手进行通信。
5 z4 o4 P4 q8 @
+ p* Y q' g+ E1 f; L( n |