LOADING

加载过慢请开启缓存 浏览器默认开启

JDY-31模块

2022/12/19 单片机

Abstract: 尝试自己写了蓝牙模块JDY-31的代码


目录:


JDY-31模块介绍

JDY-31 蓝牙基于蓝牙 3.0 SPP 设计,这样可以支持 Windows、 Linux、 android 数据透传,工作频段 2.4GHZ,调制方式 GFSK,最大发射功率 8db,最大发射距离30 米,支持用户通过AT 命令修改设备名、 波特率等指令,方便快捷使用灵活。

购买链接和详细:蓝牙3.0模块 SPP透传 兼容HC-05/06从机 JDY-31蓝牙模块-tmall.com天猫

AT指令

指令 功能 参数 返回 备注
AT+VERSION 获取版本信息 +VERSION=…
AT+RESET 复位 +OK
AT+DISC 断开连接 +OK 只在蓝牙连接后有效
AT+LADDR 获取BLE蓝牙MAC地址 +LADDR=…
AT+BAUD[参数] 波特率查询/设置 4-9600;5-19200;6-38400;7-57600;8-115200;9-128000 +OK 一般默认9600
AT+PIN[参数] 密码匹配码查询/设置 4位密码 +OK 默认1234
AT+NAME[参数] 广播名称查询/设置 广播名称,18字节以下 +OK 默认JDY-31-SPP
AT+DEFAULT 恢复出厂设置 +OK
AT+ENLOG 获取串口输出使能状态 +ENLOG=… 1:打开 0:关闭,默认为1

一些经验

1.新买的模块对AT指令无反应

  • 尝试不同的波特率,一般默认9600

  • 模块供电后,用手机连接模块,用串口助手查看,第一次连接成功后可正常使用AT指令,默认配对码为1234

2.接收到ERR-1003/ERR-1002

  • 确保AT指令末尾有\r\n,对应十六进制的0A 0D
  • 确保连线无松动

3.模块没有反应/蓝牙发送数据后被原样或乱码传回

  • 检查代码
  • 尝试模块断电重启
  • 用电脑串口助手测试

代码部分

JDY31.h

#ifndef __JDY31_H

extern char JDY31_RxString[100];

void JDY31_Init(void);
uint8_t JDY31_GetRxFlag(void);

void JDY31_GetVersion(void);
void JDY31_Reset(void);
void JDY31_Disc(void);
void JDY31_GetLaddr(void);
void JDY31_GetBaud(void);
void JDY31_SetBaud(char* String);
void JDY31_GetPin(void);
void JDY31_SetPin(char* Pin);
void JDY31_GetName(void);
void JDY31_SetName(char* String);
void JDY31_Defult(void);
void JDY31_GetEnlog(void);
void JDY31_SendStr(char* String);
void JDY31_SendNum(uint32_t Number, uint8_t Length);

#define __JDY31_H

#endif

JDY31.c

#include "stm32f10x.h"                  // Device header

/**
JDY-31蓝牙模块库
Date: 12/18,2022

使用USART1,TXD为PA9,RXD为PA10

注意:
不建议同时使用多个发送命令的函数
若需要更改设置,建议用串口助手调试
支持收发中文,但不建议
**/



char COMMAND_VERSION[]="AT+VERSION"; //查询版本号
char COMMAND_RESET[]="AT+RESET"; //复位
char COMMAND_DISC[]="AT+DISC"; //断开链接
char COMMAND_LADDR[]="AT+LADDR"; //BLE蓝牙MAC地址
char COMMAND_BAUD[]="AT+BAUD"; //波特率
char COMMAND_PIN[]="AT+PIN"; //配对码
char COMMAND_NAME[]="AT+NAME"; //广播名
char COMMAND_DEFAULT[]="AT+DEFAULT"; //恢复出场设置
char COMMAND_ENLOG[]="AT+ENLOG"; //串口状态使能查询

uint8_t JDY31_RxFlag;
char JDY31_RxString[100]; //接收的字符串

/**
  * @brief  USART初始化
  * @param  无
  * @retval 无
  */
void JDY31_Init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //开启时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
    
    GPIO_InitTypeDef GPIO_InitStructure; //GPIO配置
    GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AF_PP; //复用推挽输出
    GPIO_InitStructure.GPIO_Pin= GPIO_Pin_9; //发送线
    GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;
    
    GPIO_Init(GPIOA,&GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Mode= GPIO_Mode_IN_FLOATING; //浮空输入
    GPIO_InitStructure.GPIO_Pin= GPIO_Pin_10; //接收线
    GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;
    
    GPIO_Init(GPIOA,&GPIO_InitStructure);
    
    USART_InitTypeDef USRAT_InitStructure; //USART配置
    USRAT_InitStructure.USART_BaudRate= 9600; //波特率
    USRAT_InitStructure.USART_HardwareFlowControl= USART_HardwareFlowControl_None; //流控制关
    USRAT_InitStructure.USART_Mode= USART_Mode_Rx | USART_Mode_Tx;
    USRAT_InitStructure.USART_Parity= USART_Parity_No;
    USRAT_InitStructure.USART_StopBits= USART_StopBits_1;
    USRAT_InitStructure.USART_WordLength= USART_WordLength_8b;
    
    USART_Init(USART1,&USRAT_InitStructure);
    
    NVIC_InitTypeDef NVIC_InitStructure; //NVIC配置
    NVIC_InitStructure.NVIC_IRQChannel= USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelCmd= ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority= 2;
    
    NVIC_Init(&NVIC_InitStructure);
    
    USART_Cmd(USART1,ENABLE); //使能USART1
    USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //当USART受到数据时触发中断
}

/**
  * @brief  发送一字节数据
  * @param  Byte 要发送的一字节
  * @retval 无
  */
void JDY31_SendByte(uint8_t Byte)
{
    USART_SendData(USART1,Byte);
    while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET); //发送寄存器不为空
}

/**
  * @brief  发送一个字符串
  * @param  String 要发送的字符串
  * @retval 无
  */
void JDY31_SendString(char *String)
{
    uint8_t i;
    for (i=0;String[i]!=0;i++)
    {
        JDY31_SendByte(String[i]);
    }
}

/**
  * @brief  获取接收标志,为一表示接收到数据
  * @param  无
  * @retval 标志位,0或1
  */
uint8_t JDY31_GetRxFlag(void)
{
    if (JDY31_RxFlag==1)
    {
        JDY31_RxFlag=0;
        return 1;
    }
    else
    {
        return 0;
    }
}

/**
  * @brief  发送获取版本信息的指令
  * @param  无
  * @retval 无
  */
void JDY31_GetVersion(void)
{
    JDY31_SendString(COMMAND_VERSION);
    JDY31_SendString("\r\n");
}

/**
  * @brief  发送重启命令
  * @param  无
  * @retval 无
  */
void JDY31_Reset(void)
{
    JDY31_SendString(COMMAND_RESET);
    JDY31_SendString("\r\n");
}

/**
  * @brief  发送断开连接命令
  * @param  无
  * @retval 无
  */
void JDY31_Disc(void)
{
    JDY31_SendString(COMMAND_DISC);
    JDY31_SendString("\r\n");
}

/**
  * @brief  发送获取BLE蓝牙MAC地址命令
  * @param  无
  * @retval 无
  */
void JDY31_GetLaddr(void)
{
    JDY31_SendString(COMMAND_LADDR);
    JDY31_SendString("\r\n");
}

/**
  * @brief  发送获取波特率命令
  * @param  无
  * @retval 无
  */
void JDY31_GetBaud(void)
{
    JDY31_SendString(COMMAND_BAUD);
    JDY31_SendString("\r\n");
}

/**
  * @brief  发送设置波特率命令(建议不使用)
  * @param  Baud 要设置的波特率(9600;19200;38400;57600;115200;128000)
  * @retval 无
  */
void JDY31_SetBaud(uint32_t Baud)
{
    //4-9600;5-19200;6-38400;7-57600;8-115200;9-128000
    char* String;
    
    if (Baud==(uint32_t)9600)
    {
        String="4";
    }
    else if (Baud==(uint32_t)19200)
    {
        String="5";
    }
    else if (Baud==(uint32_t)38400)
    {
        String="6";
    }
    else if (Baud==(uint32_t)57600)
    {
        String="7";
    }
    else if (Baud==(uint32_t)115200)
    {
        String="8";
    }
    else if (Baud==(uint32_t)128000)
    {
        String="9";
    }
    
    JDY31_SendString(COMMAND_BAUD);
    JDY31_SendString(String);
    JDY31_SendString("\r\n");
}

/**
  * @brief  发送获取配对码命令
  * @param  无
  * @retval 无
  */
void JDY31_GetPin(void)
{
    JDY31_SendString(COMMAND_PIN);
    JDY31_SendString("\r\n");
}

/**
  * @brief  发送设置配对码命令
  * @param  Pin 要设置的配对码
  * @retval 无
  */
void JDY31_SetPin(char* Pin)
{
    JDY31_SendString(COMMAND_PIN);
    JDY31_SendString(Pin);
    JDY31_SendString("\r\n");
}

/**
  * @brief  发送获取广播名称命令
  * @param  无
  * @retval 无
  */
void JDY31_GetName(void)
{
    JDY31_SendString(COMMAND_NAME);
    JDY31_SendString("\r\n");
}

/**
  * @brief  发送设置广播名称命令
  * @param  String 要设置的名称
  * @retval 无
  */
void JDY31_SetName(char* String)
{
    JDY31_SendString(COMMAND_NAME);
    JDY31_SendString(String);
    JDY31_SendString("\r\n");
}

/**
  * @brief  发送恢复默认设置命令
  * @param  无
  * @retval 无
  */
void JDY31_Defult(void)
{
    JDY31_SendString(COMMAND_DEFAULT);
    JDY31_SendString("\r\n");
}

/**
  * @brief  发送获取串口使能命令
  * @param  无
  * @retval 无
  */
void JDY31_GetEnlog(void)
{
    JDY31_SendString(COMMAND_ENLOG);
    JDY31_SendString("\r\n");
}

/**
  * @brief  发送数据
  * @param  String 要发送的数据
  * @retval 无
  */
void JDY31_SendStr(char* String)
{
    JDY31_SendString(String);
    JDY31_SendString("\r\n");
}

/**
  * @brief  JDY31次方函数
  * @retval 返回值等于X的Y次方
  */
uint32_t JDY31_Pow(uint32_t X, uint32_t Y)
{
    uint32_t Result = 1;
    while (Y--)
    {
        Result *= X;
    }
    return Result;
}

/**
  * @brief  发送数字
  * @param  无
  * @retval 无
  */
void JDY31_SendNum(uint32_t Number, uint8_t Length)
{
    uint8_t i;
    for (i = 0; i < Length; i++)							
    {
        JDY31_SendByte(Number / JDY31_Pow(10, Length - i - 1) % 10 + '0');
    }
    JDY31_SendString("\r\n");
}

/**
  * @brief  处理接收数据的中断函数
  * @param  无
  * @retval 无
  */
void USART1_IRQHandler(void)
{
    static uint8_t pRD=0; //下标
    static uint8_t RX_Status=0; //表示接收轮次
    
    if (USART_GetFlagStatus(USART1,USART_IT_RXNE) == SET) //接收寄存器不为空
    {
        uint8_t RD=USART_ReceiveData(USART1);
        if (RD != '\r' && RD != '\n' && RX_Status==0) //接收的数据不是结尾且不在结尾轮
        {
            JDY31_RxString[pRD]=RD;
            pRD++;
        }
        else
        {
            if (RD=='\r' && RX_Status==0) //在非结尾轮接收到\r
            {
                RX_Status=1;
            }
            else if (RD=='\n' && RX_Status==1) //在结尾轮接收到\n,该次数据接收结束
            {
                JDY31_RxString[pRD]='\0';
                pRD=0;
                JDY31_RxFlag=1;
                RX_Status=0;
            }
        }
    }
    USART_ClearITPendingBit(USART1,USART_IT_RXNE);
}

使用样例

例一

#include "stm32f10x.h"                  // Device header
#include "JDY31.h"

int main(void)
{
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //NVIC优先级规则设置
    
    JDY31_Init(); //初始化

    JDY31_SendStr("Start"); //发送一个字符串
    
    while(1)
    {
        if (JDY31_GetRxFlag()==1)
        {
            //处理接收到的数据
        }
    }
}

例二

#include "stm32f10x.h"                  // Device header
#include "JDY31.h"

int main(void)
{
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //NVIC优先级规则设置
    
    JDY31_Init(); //初始化

    JDY31_SetName("JDY31"); //设置广播名称
    
    while(1)
    {
        JDY31_GetName(); //获取广播名称
        if (JDY31_GetRxFlag()==1)
        {
            //处理接收到的数据
        }
    }
}