【STM32F103】JDY-31蓝牙模块(USART)

发布时间:2024年01月23日

JDY-31

JDY-31蓝牙模块,就是下面这么个小玩意。某宝买大概就七八块,超过十块的不要买。

JDY一共有6根引脚,而我们想要让它工作的话只需要接两根线即可,那就是VCC和GND,给VCC接3.6V~6V的电压(推荐是5V),GND接地,然后JDY31就开始工作了,我们的手机打开蓝牙就能找到JDY的蓝牙了。

配对后我们的手机就可以和JDY31进行通信了,但是仅仅是和JDY31通信,这没有什么意义,所以我们会将JDY31和单片机进行连接,这样我们就可以用手机通过蓝牙去控制单片机了。

我们把JDY31的RXD接到我们STM32F103的TXD,而TXD接到我们STM32F103的RXT(推荐使用USART1的资源,GPIOA的9号引脚和10号引脚,因为JDY的工作电压较高,STM32F103一般的引脚受不了,而USART1资源的引脚能够接受5V电压,具体可以参考引脚定义表)

这样,只要我们的手机通过蓝牙和JDY31连接之后,并且JDY31和STM32F103通过串口连接之后,只要手机通过蓝牙助手发送串口数据,然后JDY就会直接收到并且发送给STM32F103。而STM32F103通过串口发送的数据也会经由JDY31来传输到我们的手机上。

所以蓝牙通信没那么难,或者说是因为有像JDY31这些集成度高的模块,使得我们的蓝牙通信变得简单。

剩下两个引脚是STATE和EN,简单来说EN没有用,而我们连接上来自JDY的蓝牙之后,STATE会输出高电平,可以外接一个LED来直观的查看蓝牙是否连接。不过其实没有太大必要,因为JDY自带一个小红灯,等待连接的时候小红灯会闪烁,而连接上之后小红灯常亮。

AT命令控制JDY31

上面讲述了怎么通过JDY31来进行蓝牙通信。

而如果我们想要修改JDY的一些配置信息(例如蓝牙名称,连接的密码之类的),我们就需要使用AT命令来对JDY进行控制。

其实AT命令听起来挺酷,实际上就是一堆特定的字符串罢了。

例如我要查询版本号,那么我直接让STM32F103通过串口发送字符串“AT+VERSION\r\n”即可,也就是指令再加上“\r\n”。然后JDY31就会通过串口把版本号再通过串口发过来。本质上还是串口通信。

总的指令就上面九条没什么可说的,下面就简单说一下带参数的指令。

波特率这条指令可以加上参数来修改波特率,不过不是自由设置的,例如我要设置9600的波特率,那么我发送的指令就应该是“AT+BAUD<4>\r\n”,其他波特率的参数可以参考上面的图。

设置配对密码,默认是1234,把要修改的密码当作参数发送即可。

蓝牙名称设置,这个会稍微有些延迟,要等一等,手机上搜索到的蓝牙名称才会更新。

上面说了,一般情况下,JDY31连接上蓝牙之后,STATE会发出高电平,如果我们将这个串口状态输出失能,那么STATE就会和EN一样没有任何用处了。

通过STM32F103对JDY-31使用串口进行AT命令

?接下来的讲解配合下面代码食用。

打开串口没什么可说的,直接复制我之前关于USART的文章的代码即可。

这边为了串口输出方便,我加入了stdio库以及重写了fputc,这是为了能够直接使用printf来进行串口的输出,keil5还需要像下图这样配置。

然后我们需要做的就是直接发送AT指令即可,需要注意的是连续两条指令之间需要延时一段时间,否则JDY31反应不过来(我猜的,总之就是JDY会忽略一些指令)

得到的结果在代码下面的图中。

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include <stdio.h>

//中断函数
void USART1_IRQHandler(void){
    //判断数据接收标志位
    if(SET==USART_GetFlagStatus(USART1,USART_FLAG_RXNE)){
        uint16_t data=USART_ReceiveData(USART1);            //读取出接收的数据
        printf("%c",data);
        USART_ClearITPendingBit(USART1,USART_FLAG_RXNE);    //清除数据接收标志位
    }
}
 
void sendbyte(uint16_t Data){
    //发送数据
    USART_SendData(USART1,Data);
    //等待数据发送完毕
    while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}

//这里重写fputc使得可以直接使用printf对串口进行输出
int fputc(int ch, FILE *f){
    sendbyte(ch);
    return ch;
}
 
int main(void){
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    GPIO_InitTypeDef itd;
    itd.GPIO_Mode=GPIO_Mode_AF_PP;      //复用推挽输出
    itd.GPIO_Pin=GPIO_Pin_9;            //TX引脚
    itd.GPIO_Speed=GPIO_Speed_2MHz;     //这个随意
    GPIO_Init(GPIOA,&itd);
    itd.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空输入
    itd.GPIO_Pin=GPIO_Pin_10;           //RX引脚
    GPIO_Init(GPIOA,&itd);
    
    USART_InitTypeDef uitd;
    uitd.USART_BaudRate=9600;                                       //波特率
    uitd.USART_HardwareFlowControl=USART_HardwareFlowControl_None;  //硬件流控制
    uitd.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;                    //串口模式
    uitd.USART_Parity=USART_Parity_No;                              //校验
    uitd.USART_StopBits=USART_StopBits_1;                           //停止位长度
    uitd.USART_WordLength=USART_WordLength_8b;                      //传输的字长
    USART_Init(USART1,&uitd);
    
    USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);                    //开启USART接收中断
    
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);                 //NVIC中断配置
    NVIC_InitTypeDef nitd;
    nitd.NVIC_IRQChannel=USART1_IRQn;
    nitd.NVIC_IRQChannelCmd=ENABLE;
    nitd.NVIC_IRQChannelPreemptionPriority=2;
    nitd.NVIC_IRQChannelSubPriority=2;
    NVIC_Init(&nitd);
    
    USART_Cmd(USART1,ENABLE);                                       //上电USART
    
    printf("AT+NAME\r\n");      //查询蓝牙名字
    Delay_ms(100);
    printf("AT+LADDR\r\n");     //查询mac地址
    Delay_ms(100);
    printf("AT+BAUD\r\n");      //查询波特率
    Delay_ms(100);
    printf("AT+PIN\r\n");       //查询蓝牙连接密码
    Delay_ms(100);
    printf("AT+ENLOG\r\n");     //查询状态输出使能状态
    Delay_ms(100);
    printf("AT+VERSION\r\n");   //查询版本
    Delay_ms(100);
    printf("AT+NAME<JDY>\r\n"); //更改蓝牙名称,但是反应比较慢,得等一下子才会更新
    
    while(1){
        
    }
}

忽略最后一行,那是蓝牙断开后,JDY发送的。

JDY与手机进行蓝牙通信

其实蓝牙通信听起来挺酷,实际上你手机连上蓝牙之后,所谓蓝牙通信实际上就是利用串口来发送信息。因此我们直接使用printf输出内容就行,然后手机就能收到,不过我们需要使用蓝牙助手才能看得到,我用的是某宝商家提供的,大家随便找一个都行,甚至微信小程序里都有。

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include <stdio.h>

//中断函数
void USART1_IRQHandler(void){
    //判断数据接收标志位
    if(SET==USART_GetFlagStatus(USART1,USART_FLAG_RXNE)){
        uint16_t data=USART_ReceiveData(USART1);            //读取出接收的数据
        printf("%c",data);
        USART_ClearITPendingBit(USART1,USART_FLAG_RXNE);    //清除数据接收标志位
    }
}
 
void sendbyte(uint16_t Data){
    //发送数据
    USART_SendData(USART1,Data);
    //等待数据发送完毕
    while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}

int fputc(int ch, FILE *f){
    sendbyte(ch);
    return ch;
}
 
int main(void){
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    GPIO_InitTypeDef itd;
    itd.GPIO_Mode=GPIO_Mode_AF_PP;      //复用推挽输出
    itd.GPIO_Pin=GPIO_Pin_9;            //TX引脚
    itd.GPIO_Speed=GPIO_Speed_2MHz;     //这个随意
    GPIO_Init(GPIOA,&itd);
    itd.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空输入
    itd.GPIO_Pin=GPIO_Pin_10;           //RX引脚
    GPIO_Init(GPIOA,&itd);
    
    USART_InitTypeDef uitd;
    uitd.USART_BaudRate=9600;                                       //波特率
    uitd.USART_HardwareFlowControl=USART_HardwareFlowControl_None;  //硬件流控制
    uitd.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;                    //串口模式
    uitd.USART_Parity=USART_Parity_No;                              //校验
    uitd.USART_StopBits=USART_StopBits_1;                           //停止位长度
    uitd.USART_WordLength=USART_WordLength_8b;                      //传输的字长
    USART_Init(USART1,&uitd);
    
    USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);                    //开启USART接收中断
    
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);                 //NVIC中断配置
    NVIC_InitTypeDef nitd;
    nitd.NVIC_IRQChannel=USART1_IRQn;
    nitd.NVIC_IRQChannelCmd=ENABLE;
    nitd.NVIC_IRQChannelPreemptionPriority=2;
    nitd.NVIC_IRQChannelSubPriority=2;
    NVIC_Init(&nitd);
    
    USART_Cmd(USART1,ENABLE);                                       //上电USART

    while(1){
        printf("Hello World");
        Delay_ms(2000);
    }
}

这是串口助手收到的完整信息,包括了蓝牙的连接到断开。?

这是手机的蓝牙助手里的信息,RX开头的是收到的信息,TX开头的是手机这里发送的。?

资源获取

如果大家想要蓝牙特供版的串口助手以及安卓手机版的蓝牙助手,可以关注我的公众号“折途想要敲代码”回复关键词“蓝牙”即可免费获取。

文章来源:https://blog.csdn.net/m0_63235356/article/details/135611700
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。