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)
{
//处理接收到的数据
}
}
}