零. 概述

主要介绍下用正点原子的战舰(STM32F103ZET6)外接我们的蓝牙扩展版跑蓝牙协议栈的初始化以及搜索演示

一. 声明

本专栏文章我们会以连载的方式持续更新,本专栏计划更新内容如下:

第一篇:蓝牙综合介绍 ,主要介绍蓝牙的一些概念,产生背景,发展轨迹,市面蓝牙介绍,以及蓝牙开发板介绍。

第二篇:Transport层介绍,主要介绍蓝牙协议栈跟蓝牙芯片之前的硬件传输协议,比如基于UART的H4,H5,BCSP,基于USB的H2等

第三篇:传统蓝牙controller介绍,主要介绍传统蓝牙芯片的介绍,包括射频层(RF),基带层(baseband),链路管理层(LMP)等

第四篇:传统蓝牙host介绍,主要介绍传统蓝牙的协议栈,比如HCI,L2CAP,SDP,RFCOMM,HFP,SPP,HID,AVDTP,AVCTP,A2DP,AVRCP,OBEX,PBAP,MAP等等一系列的协议吧。

第五篇:低功耗蓝牙controller介绍,主要介绍低功耗蓝牙芯片,包括物理层(PHY),链路层(LL)

第六篇:低功耗蓝牙host介绍,低功耗蓝牙协议栈的介绍,包括HCI,L2CAP,ATT,GATT,SM等

第七篇:蓝牙芯片介绍,主要介绍一些蓝牙芯片的初始化流程,基于HCI vendor command的扩展

第八篇:附录,主要介绍以上常用名词的介绍以及一些特殊流程的介绍等。

另外,开发板如下所示,对于想学习蓝牙协议栈的最好人手一套。以便更好的学习蓝牙协议栈,相信我,学完这一套视频你将拥有修改任何协议栈的能力(比如Linux下的bluez,Android下的bluedroid)。

-------------------------------------------------------------------------------------------------------------------------

CSDN学院链接(进入选择你想要学习的课程):https://edu.csdn.net/lecturer/5352?spm=1002.2001.3001.4144

蓝牙交流扣扣群:970324688

Github代码:https://github.com/sj15712795029/bluetooth_stack

入手开发板:https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w4004-22329603896.18.5aeb41f973iStr&id=622836061708

蓝牙学习目录:https://blog.csdn.net/XiaoXiaoPengBo/article/details/107727900

--------------------------------------------------------------------------------------------------------------------------

二. STM32蓝牙协议栈封装使用AT command实现搜索

使用步骤操作如下:(正点原子开发板外接蓝牙扩展点击链接)!!!!!!!!!!!!!!!!!!!!

步骤 1)准备好代码,从github下载下来最新的代码(在上面有介绍Github连接)

步骤 2)连接好硬件

分为以下几个小的步骤:

① UART2 TX/RX的接线

首先我们把原子的战舰开发板的P7的两个跳帽拔掉,分别把模组的丝印的TX接到P7的3pin上,然后把模组的RX接到P7的4 pin上

另外由于我们蓝牙协议栈跑的是Transport h4,所以需要流控功能,所以需要接CTS/RTS,所以我们还需要把模组的CTS接到原子战舰的PA0,模组的RTS接到原子战舰的PA1

② 电源,GND接线

原子有单独的VOUT,因为我们的模组是5V供电,所以我们把模组的5V接到VOUT2的5V上,把GND接到战舰的VOUT2的GND上

整个正点原子接线位置如下

步骤 3)打开Keil工程文件夹下的project\stm32f10x_bb_csr8x11_bt\stm32f10x_bb_csr8x11.uvprojx,然后编译下载

注意几点:

① 设备类型修改为F103ZET6

② 下载的时候要勾选Use micro lib

步骤4)打开串口工具(我用的是XCOM),然后做初始化动作,在发送串口敲BT_START,点击发送,出来以下log就证明初始化通过了,我们就可以来进行搜索动作了注意一点:不能勾选发送新行,否则会解析错误

步骤5)然后敲BT_INQUIRY就能搜索到设备了

三.使用我们自己写的上位机来实现搜索

步骤跟AT的1)2)3)一样,我们从第四步开始讲解

打开我们工程源码1-BLUETOOTH\mcu_bt_tool\mcu_bt_tool\mcu_bt_tool\bin\Debug中的mcu_bt_tool.exe,当然你也可以直接用VS2010打开工程

步骤 4)打开串口

步骤 5)点击蓝牙开启按钮(此步骤跟AT 命令BT_START一样的效果,就是实现蓝牙初始化)

步骤 6) 等待初始化完成点击搜索按钮,你就发现可以搜索到蓝牙了

另外:使用上位机的时候注意几点:

① mcu_bt_tool.exe你如果想把可执行文件拿到别的路径单独执行,那么必须要把Newtonsoft.Json.dll跟exe放在同一个路径下,因为上位机是跟STM32用json沟通的

② 因为目前搜索是开启的EIR,带RSSI的,所以他会重复性上来同一个设备,我没做根据同一个蓝牙地址做显示过滤,如果有兴趣的人可以加上这一块

四. 串口工具AT command以及上位机实现搜索的原理

步骤 1)Type C uart debug口的tx,rx初始化

/******************************************************************************* func name   : hw_uart_debug_init* para        : baud_rate(IN)  --> Baud rate of uart1* return      : hw_uart_debug_init result* description : Initialization of USART1.PA9->TX PA10->RX
******************************************************************************/
uint8_t hw_uart_debug_init(uint32_t baud_rate)
{GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;DMA_InitTypeDef DMA_InitStructure;/* Enable RCC clock for USART1,GPIOA,DMA1 */RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);/* Initialization GPIOA9 GPIOA10 */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);/* Data format :1:8:1, no parity check, no hardware flow control */USART_InitStructure.USART_BaudRate = baud_rate;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;/* Enable USART interrupts, mainly for idle interrupts */NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=DEBUG_PREE_PRIO;NVIC_InitStructure.NVIC_IRQChannelSubPriority = DEBUG_SUB_PRIO;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);/* Initializes USART1 to enable USART, USART idle interrupts and USART RX DMA */USART_Init(USART1, &USART_InitStructure);USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);USART_Cmd(USART1, ENABLE);/* Initializes DMA and enables it */DMA_DeInit(DMA1_Channel5);DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)uart1_rev_buffer;DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;DMA_InitStructure.DMA_BufferSize = UART1_MAX_REV;DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;DMA_Init(DMA1_Channel5, &DMA_InitStructure);DMA_Cmd(DMA1_Channel5, ENABLE);return HW_ERR_OK;
}

可以看到TX我们就是普通的实现发送,RX我们用串口空闲中断+DMA的方式来实现接受串口工具以及上位机的发送指令,然后串口中断的实现原理是这样:

/******************************************************************************* func name   : USART1_IRQHandler* para        : NULL* return      : NULL* description : Interrupt handler for usart1
******************************************************************************/
void USART1_IRQHandler(void)
{if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET){/* Without this, the interrupt cannot be cleared and continues into the interrupt */USART_ReceiveData(USART1);uart1_rev_len =UART1_MAX_REV-DMA_GetCurrDataCounter(DMA1_Channel5);if(uart1_rev_len != 0){/* Call the parse function */shell_parse(uart1_rev_buffer);hw_memset(uart1_rev_buffer,0,sizeof(uart1_rev_buffer));}/* Clear the interrupt and reset DMA */USART_ClearITPendingBit(USART1,USART_IT_IDLE);uart1_dma_enable(DMA1_Channel5);}
}

步骤2)收到串口工具或者上位机的解析函数如下:

uint8_t shell_parse(uint8_t *shell_string)
{uint8_t result = HW_ERR_OK;cJSON* parse_json = cJSON_Parse((const char *)shell_string);uint8_t* func_value = (uint8_t*)((cJSON *)cJSON_GetObjectItem(parse_json,"FUNC"))->valuestring;uint8_t* operate_value = (uint8_t*)((cJSON *)cJSON_GetObjectItem(parse_json,"OPERATE"))->valuestring;uint8_t* para1 = (uint8_t*)((cJSON *)cJSON_GetObjectItem(parse_json,"PARAM1"))->valuestring;uint8_t* para2 = (uint8_t*)((cJSON *)cJSON_GetObjectItem(parse_json,"PARAM2"))->valuestring;uint8_t* para3 = (uint8_t*)((cJSON *)cJSON_GetObjectItem(parse_json,"PARAM3"))->valuestring;uint8_t* para4 = (uint8_t*)((cJSON *)cJSON_GetObjectItem(parse_json,"PARAM4"))->valuestring;uint8_t* para5 = (uint8_t*)((cJSON *)cJSON_GetObjectItem(parse_json,"PARAM5"))->valuestring;uint8_t* para6 = (uint8_t*)((cJSON *)cJSON_GetObjectItem(parse_json,"PARAM6"))->valuestring;if(hw_strcmp((const char *)func_value,"BT") == 0){result = shell_json_parse(operate_value,para1,para2,para3,para4,para5,para6);}else{result = shell_at_cmd_parse(shell_string);}cJSON_Delete(parse_json);return result;}

在这里我们分两种方式来解析:①AT command(串口工具采用这种方式) ②Json(上位机采用这种方式),如果解析不是我们定义的json格式,那么就自动转变为AT指令的解析

步骤3)AT command解析执行BT_START,以及BT_INQUIRY

uint8_t shell_at_cmd_parse(uint8_t *shell_string)
{if(hw_strcmp("BT_START",(const char*)shell_string) == 0){HW_DEBUG("SHELL:operate bt start\n");bt_start(&bt_app_cb);return HW_ERR_OK;}........if(hw_strcmp("BT_INQUIRY",(const char*)shell_string) == 0){HW_DEBUG("SHELL:operate bt inquiry\n");bt_start_inquiry(0x30,HCI_INQUIRY_MAX_DEV);return HW_ERR_OK;}
}

步骤4)接受上位机json指令解析

uint8_t shell_json_parse(uint8_t *operate_value,uint8_t *para1,uint8_t *para2,uint8_t *para3,uint8_t *para4,uint8_t *para5,uint8_t *para6)
{if(hw_strcmp((const char *)operate_value,"BT_START") == 0){HW_DEBUG("UART PARSE DEBUG:operate BT_START\n");bt_start(&bt_app_cb);operate_stauts_oled_show("BT",operate_value,"SUCCESS",0,0,0,0,0,0);return HW_ERR_OK;}.....if(hw_strcmp((const char *)operate_value,"BT_START_INQUIRY") == 0){HW_DEBUG("UART PARSE DEBUG:operate BT_INQUIRY\n");bt_start_inquiry(0x30,HCI_INQUIRY_MAX_DEV);return HW_ERR_OK;}
}

以上步骤3)4)其中bt_start以及bt_start_inquiry就是协议栈函数了,这样就实现了AT command或者json上位机跟蓝牙协议栈的对接。

正点原子战舰(STM32F103ZET6) 跑蓝牙协议栈 --传统蓝牙搜索演示以及实现原理相关推荐

  1. 蓝牙协议栈模组在linux ubuntu 跑蓝牙协议栈 --传统蓝牙搜索演示以及实现原理

    零. 概述 主要介绍下用Linux ubuntu虚拟机外接我们的蓝牙扩展版跑蓝牙协议栈的初始化以及搜索演示 一. 声明 本专栏文章我们会以连载的方式持续更新,本专栏计划更新内容如下: 第一篇:蓝牙综合 ...

  2. 蓝牙协议栈开发板 STM32F1 跑蓝牙协议栈 --传统蓝牙串口协议SPP演示以及实现原理

    零. 概述 主要介绍下蓝牙协议栈开发板跑传统蓝牙串口协议SPP AT指令以及上位机操作步骤,以及原理 一. 声明 本专栏文章我们会以连载的方式持续更新,本专栏计划更新内容如下: 第一篇:蓝牙综合介绍 ...

  3. 蓝牙协议栈开发板 STM32F1 跑蓝牙协议栈 --传统蓝牙搜索演示以及实现原理

    零. 概述 主要介绍下蓝牙协议栈开发板跑传统蓝牙搜索AT指令以及上位机操作步骤,以及原理 一. 声明 本专栏文章我们会以连载的方式持续更新,本专栏计划更新内容如下: 第一篇:蓝牙综合介绍 ,主要介绍蓝 ...

  4. STM32下载程序至SRAM——基于正点原子精英STM32F103ZET6开发板

    STM32下载程序至SRAM--基于正点原子精英STM32F103ZET6开发板 如题,由于STM32的FLASH烧写寿命在1万次左右,对于本人这样的改一行代码都想下载到开发板中测试的强迫症患者,真是 ...

  5. BLE蓝牙和传统蓝牙的区别

    在移动设备上使用的蓝牙协议大多都是4.0,而蓝牙的4.0又有两个分支,经典4.0蓝牙和BLE4.0蓝牙,经典4.0就是传统的3.0蓝牙升级而成,向下兼容.而BLE4.0蓝牙是一个新的分支,不向下兼容. ...

  6. BLE低功耗蓝牙和传统蓝牙的五大区别

    现在移动设备上使用的蓝牙大多是4.0,而蓝牙 4.0 有两个分支,经典 4.0 和 BLE4.0,经典 4.0 就是传统的3.0 蓝牙升级而成,向下兼容.而 BLE 4.0 是一个新的分支,不向下兼容 ...

  7. 正点原子mysql_正点原子战舰开发板硬件原理图与PCB

    [实例简介] 正点原子的STM32F103新战舰开发板的硬件原理图与PCB,且PCB含三维元器件封装. [实例截图] [核心代码] 1d489e5a-fad4-4456-aeb8-6225947162 ...

  8. C语言蓝牙协议栈讲解,蓝牙协议栈记录—BTStack

    TSTack User Guid 翻译过来的 1.简介 2.BTStack 架构 BTStack在所实现的协议和服务之间采用很多状态机实现相互作用,特点: <1>单线程.BTStack只有 ...

  9. STM32工作笔记001---认识开发板资源-以正点原子战舰版开发板为例

    技术交流QQ群[JAVA,C++,Python,.NET,BigData,AI]:170933152 这里只把不太明白的写上. 1.DS18B20是湿度传感器 DS18B20是常用的数字温度传感器,其 ...

  10. 接上一篇的正点原子战舰读取sd卡文本文件的主程序。

    #include "sys.h" #include "delay.h" #include "usart.h" #include " ...

最新文章

  1. java timer.schedule如何控制执行次数_Java 分布式任务调度平台:PowerJob 快速开始+配置详解...
  2. 6大理由,告诉你为什么这个大会你不能错过! | 文末有福利
  3. 【转】删除过期数据通用程序
  4. js页面排序-----基础篇
  5. python random包含尾部吗_你真的了解Python的random模块吗?
  6. 23中设计模式之抽象工厂模式
  7. swift 雨燕 新手教程
  8. 游戏卡牌半小时拍出8700万天价,法院紧急叫停!
  9. 智慧女人——你懂吗?
  10. android拦截黑名单电话和短信
  11. 低功耗电波钟的制作 - 电子设计竞赛
  12. 新型 EGFR 小分子抑制剂(克服 L858R/T790M 突变)
  13. mysql8.0压缩包安装
  14. linux 打开网页 看不清网页上的字体呈现出框,电脑浏览器打开网页字体显示模糊如何解决...
  15. 使用Cplex求解均值方差模型
  16. 如何在博客园中自定义背景
  17. 图片服务器之详解打war包
  18. 曾为面试官的我也有今天,面试百度Android被按地上血虐
  19. java 链表 深拷贝_单链表深拷贝的实现
  20. WordPress 简约主题mkBlog v2.2下载

热门文章

  1. 微信小程序登录界面的代码html,微信小程序用户登录组件
  2. 全国省市区行政编码数据表 sql格式
  3. CentOS下IOZone编译安装
  4. 黑域助手连接服务器才能用吗,黑域app怎么使用?进入黑域详细教程[图]
  5. 【深度学习】图像超分实验:SRCNN/FSRCNN
  6. CoreUI: RunTimeThemeRefForBundleIdentifierAndName() couldn't find Assets.car in bundle...
  7. linux测试硬盘读写速度
  8. JSP开发模型(JavaWed)
  9. TCP/UDP常用端口号,大家快收藏
  10. 可见光植被指数,RGB影像植被指数