• cubeIDE开发, 物联网应用之stm32的蓝牙通信设计


    目录

    一、蓝牙通信技术

    二、MCU及蓝牙模块

     三、cubeMX配置MCU及蓝牙接口

            【1】创建工程

             【2】CubeMX配置

     四、代码设计

            【1】首先创建usart1接口的调试输出支持

            【2】创建按键驱动、LED驱动、延时函数功能的支持

            【3】创建串口驱动程序,主要是复写串口回调功能

            【4】创建蓝牙驱动

    五、编译及测试

            【1】功能调用及编译

            【2】程序测试


    一、蓝牙通信技术

            蓝牙技术是一种点对点点对面的网络构架,他可以在限制的范围内以很快的速度传输网络数据,在物联网应用中,支持网状网络的物联网短距离无线通信。目前它还被广泛用于智能可穿戴设备、智能门锁、智能医疗设备、智能照明设备、智能家电等消费电子、工业采集、汽车电子、智能建筑等所有的物联网智能产品中。

            蓝牙是无线个人局域网,最初由爱立信制作,后来由蓝牙技术联盟制定了技术标准。蓝牙产品包括小型蓝牙模块,以及支持连接的蓝牙无线电和软件。 如果两台蓝牙设备想相互交流,则需要进行配对,一台设备将成为主设备,所有其他设备都将成为从设备。 通信时,主站侧需要进行检索并开始配对,如果构建链成功,则双方需要能够发送接收数据。在通信状态下,主侧和从侧的设备都开始切断,可以切断蓝牙链接。蓝牙通信本质上就是无线电传输技术,蓝牙的工作波段为2400–2483.5MHz(包括防护频带)。这是全球范围内无需取得执照(但并非无管制的)的工业、科学和医疗用(ISM)波段的 2.4 GHz 短距离无线电频段。

    二、MCU及蓝牙模块

            本文采用STM32F103C8T6的芯片及JDY-08 蓝牙透传模块,相关引脚如下:

            MCU引脚设定:PA9、PA10作为USART1引脚,用于下载程序、调试显示,PA2、PA3作为USART2引脚,并与蓝牙模块进行通信,PA8作为GPIO_OUTPUT模式,用来控制蓝牙模块上的PWRC。

             蓝牙模块为JDY-08 蓝牙透传模块,基于蓝牙 4.0 协议标准,工作频段为 2.4GHZ 范围,调制 方式为 GFSK,最大发射功率为 0db,最大发射距离 80 米,采用 TICC2541 芯片设计,支持用户通过 AT 命令修改设备名、服务 UUID、发射功率、配对密码等指令。

            TICC2541 芯片 引脚:

             引脚功能定义,在使用串口发送命令时,请将模块的 PWRC 引脚接地,并接上模块的电源(VCC、GND),电源电压为3~ 3.3V:

             以及本文用到两个AT指令:

     三、cubeMX配置MCU及蓝牙接口

            本工程设计功能如下:

            MCU(STM32F103C8T6)的引脚PA2、PA3的与蓝牙模块(TICC2541 )的11、12引脚连接,实现数据通信;MCU的PA8引脚与蓝牙模块的22引脚连接实现,实现蓝牙模块唤醒。

            通信逻辑:电脑(com4)<->(Usart1)MCU(Usart2)<->蓝牙模块->手机(蓝牙调试器,需要开启手机蓝牙功能)。

            功能:

    •         按键功能,用于按键时向蓝牙模块发送AT指令;
    •         LED功能,用于接收蓝牙模块数据时做出闪灯响应;
    •         蓝牙功能,接收来自MCU端的串口通信,接收手机端的无线传输(即蓝牙通信);
    •         串口调试功能,MCU执行程序可以向Usart1发送信息到电脑端,既可实现日志输出,也可以实现指令转发到蓝牙模块。

            【1】创建工程

            1)新建stm32工程,选择芯片STM32F103C8T6

             2)为工程命名完成创建

             【2】CubeMX配置

            1)开启sys mode接口

             2)开启RCC

             3)开启USART1(下载、调试)、USART2(连接蓝牙模块)。

             4)开启串口USART1、USART2中断功能

             5)串口引脚参数配置

             6)蓝牙测试辅助接口及按键、LED灯GPIO引脚添加:

            7)系统 时钟配置,直接拉满STM32F103C8T6能支持到的72MHz。

              8)本工程配置页面保持默认,没有为每个外围设备驱动创建独立源文件,点击保持或生成代码按钮输出代码。

     四、代码设计

            【1】首先创建usart1接口的调试输出支持

            1)禁用syscalls.c,右键选择该文件进入属性页面设置。

             2)在工程目录下创建源码目录ICore,添加文件夹print及print.h/print.c,实现对系统printf函数的映射到usart1输出显示功能。

            print.h

    1. #ifndef INC_RETARGET_H_
    2. #define INC_RETARGET_H_
    3. #include "stm32f1xx_hal.h"
    4. #include "stdio.h"//用于printf函数串口重映射
    5. #include
    6. void ResetPrintInit(UART_HandleTypeDef *huart);
    7. int _isatty(int fd);
    8. int _write(int fd, char* ptr, int len);
    9. int _close(int fd);
    10. int _lseek(int fd, int ptr, int dir);
    11. int _read(int fd, char* ptr, int len);
    12. int _fstat(int fd, struct stat* st);
    13. #endif /* INC_RETARGET_H_ */

            print.c

    1. #include <_ansi.h>
    2. #include <_syslist.h>
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include "print.h"
    11. #if !defined(OS_USE_SEMIHOSTING)
    12. #define STDIN_FILENO 0
    13. #define STDOUT_FILENO 1
    14. #define STDERR_FILENO 2
    15. UART_HandleTypeDef *gHuart;
    16. void ResetPrintInit(UART_HandleTypeDef *huart) {
    17. gHuart = huart;
    18. /* Disable I/O buffering for STDOUT stream, so that
    19. * chars are sent out as soon as they are printed. */
    20. setvbuf(stdout, NULL, _IONBF, 0);
    21. }
    22. int _isatty(int fd) {
    23. if (fd >= STDIN_FILENO && fd <= STDERR_FILENO)
    24. return 1;
    25. errno = EBADF;
    26. return 0;
    27. }
    28. int _write(int fd, char* ptr, int len) {
    29. HAL_StatusTypeDef hstatus;
    30. if (fd == STDOUT_FILENO || fd == STDERR_FILENO) {
    31. hstatus = HAL_UART_Transmit(gHuart, (uint8_t *) ptr, len, HAL_MAX_DELAY);
    32. if (hstatus == HAL_OK)
    33. return len;
    34. else
    35. return EIO;
    36. }
    37. errno = EBADF;
    38. return -1;
    39. }
    40. int _close(int fd) {
    41. if (fd >= STDIN_FILENO && fd <= STDERR_FILENO)
    42. return 0;
    43. errno = EBADF;
    44. return -1;
    45. }
    46. int _lseek(int fd, int ptr, int dir) {
    47. (void) fd;
    48. (void) ptr;
    49. (void) dir;
    50. errno = EBADF;
    51. return -1;
    52. }
    53. int _read(int fd, char* ptr, int len) {
    54. HAL_StatusTypeDef hstatus;
    55. if (fd == STDIN_FILENO) {
    56. hstatus = HAL_UART_Receive(gHuart, (uint8_t *) ptr, 1, HAL_MAX_DELAY);
    57. if (hstatus == HAL_OK)
    58. return 1;
    59. else
    60. return EIO;
    61. }
    62. errno = EBADF;
    63. return -1;
    64. }
    65. int _fstat(int fd, struct stat* st) {
    66. if (fd >= STDIN_FILENO && fd <= STDERR_FILENO) {
    67. st->st_mode = S_IFCHR;
    68. return 0;
    69. }
    70. errno = EBADF;
    71. return 0;
    72. }
    73. #endif //#if !defined(OS_USE_SEMIHOSTING)

            【2】创建按键驱动、LED驱动、延时函数功能的支持

             1)在ICore添加delay目录,并添加delay.h/delay.c源文件

            delay.h

    1. #ifndef DELAY_DELAY_H_
    2. #define DELAY_DELAY_H_
    3. #include "stm32f1xx_hal.h" //HAL库文件声明
    4. void delay_us(uint32_t us); //C文件中的函数声明
    5. #endif /* DELAY_DELAY_H_ */

            delay.c

    1. #include "delay.h"
    2. void delay_us(uint32_t us) //利用CPU循环实现的非精准应用的微秒延时函数
    3. {
    4. uint32_t delay = (HAL_RCC_GetHCLKFreq() / 8000000 * us); //使用HAL_RCC_GetHCLKFreq()函数获取主频值,经算法得到1微秒的循环次数
    5. while (delay--); //循环delay次,达到1微秒延时
    6. }

            2)在ICore添加key目录,并添加key.h/key.c源文件

            key.h

    1. #ifndef KEY_KEY_H_
    2. #define KEY_KEY_H_
    3. #include "stm32f1xx_hal.h" //HAL库文件声明
    4. #include "main.h" //IO定义与初始化函数在main.c文件中,必须引用
    5. #include "../delay/delay.h"
    6. uint8_t KEY_1(void);//按键1
    7. uint8_t KEY_2(void);//按键2
    8. #endif /* KEY_KEY_H_ */

            key.c

    1. #include "key.h"
    2. uint8_t KEY_1(void)
    3. {
    4. uint8_t a;
    5. a=0;//如果未进入按键处理,则返回0
    6. if(HAL_GPIO_ReadPin(GPIOA,KEY1_Pin)==GPIO_PIN_RESET){//读按键接口的电平
    7. // HAL_Delay(20);//延时去抖动(外部中断回调函数调用时不能使用系统自带的延时函数)
    8. delay_us(20000);//延时去抖动
    9. if(HAL_GPIO_ReadPin(GPIOA,KEY1_Pin)==GPIO_PIN_RESET){ //读按键接口的电平
    10. a=1;//进入按键处理,返回1
    11. }
    12. }
    13. while(HAL_GPIO_ReadPin(GPIOA,KEY1_Pin)==GPIO_PIN_RESET); //等待按键松开
    14. delay_us(20000);//延时去抖动(避开按键放开时的抖动)
    15. return a;
    16. }
    17. uint8_t KEY_2(void)
    18. {
    19. uint8_t a;
    20. a=0;//如果未进入按键处理,则返回0
    21. if(HAL_GPIO_ReadPin(GPIOA,KEY2_Pin)==GPIO_PIN_RESET){//读按键接口的电平
    22. // HAL_Delay(20);//延时去抖动(外部中断回调函数调用时不能使用系统自带的延时函数)
    23. delay_us(20000);//延时去抖动
    24. if(HAL_GPIO_ReadPin(GPIOA,KEY2_Pin)==GPIO_PIN_RESET){ //读按键接口的电平
    25. a=1;//进入按键处理,返回1
    26. }
    27. }
    28. while(HAL_GPIO_ReadPin(GPIOA,KEY2_Pin)==GPIO_PIN_RESET); //等待按键松开
    29. delay_us(20000);//延时去抖动(避开按键放开时的抖动)
    30. return a;
    31. }

            3)在ICore添加led目录,并添加led.h/led.c源文件

            key.h

    1. #ifndef LED_LED_H_
    2. #define LED_LED_H_
    3. #include "stm32f1xx_hal.h" //HAL库文件声明
    4. #include "main.h" //IO定义与初始化函数在main.c文件中,必须引用
    5. void LED_1(uint8_t a);//LED1独立控制函数(0为熄灭,其他值为点亮)
    6. void LED_2(uint8_t a);//LED2独立控制函数(0为熄灭,其他值为点亮)
    7. void LED_ALL(uint8_t a);//LED1~4整组操作函数(低4位的1/0状态对应4个LED亮灭,最低位对应LED1)
    8. void LED_1_Contrary(void);//LED1状态取反
    9. void LED_2_Contrary(void);//LED2状态取反
    10. #endif /* LED_LED_H_ */

            key.c

    1. #include "led.h"
    2. void LED_1(uint8_t a)//LED1独立控制函数(0为熄灭,其他值为点亮)
    3. {
    4. if(a)HAL_GPIO_WritePin(GPIOB,LED1_Pin,GPIO_PIN_SET);
    5. else HAL_GPIO_WritePin(GPIOB,LED1_Pin,GPIO_PIN_RESET);
    6. }
    7. void LED_2(uint8_t a)//LED2独立控制函数(0为熄灭,其他值为点亮)
    8. {
    9. if(a)HAL_GPIO_WritePin(GPIOB,LED2_Pin,GPIO_PIN_SET);
    10. else HAL_GPIO_WritePin(GPIOB,LED2_Pin,GPIO_PIN_RESET);
    11. }
    12. void LED_ALL(uint8_t a)//LED1~2整组操作函数(低2位的1/0状态对应2个LED亮灭,最低位对应LED1)
    13. {
    14. if(a&0x01)HAL_GPIO_WritePin(GPIOB,LED1_Pin,GPIO_PIN_SET);
    15. else HAL_GPIO_WritePin(GPIOB,LED1_Pin,GPIO_PIN_RESET);
    16. if(a&0x02)HAL_GPIO_WritePin(GPIOB,LED2_Pin,GPIO_PIN_SET);
    17. else HAL_GPIO_WritePin(GPIOB,LED2_Pin,GPIO_PIN_RESET);
    18. }
    19. void LED_1_Contrary(void){
    20. HAL_GPIO_WritePin(GPIOB,LED1_Pin,1-HAL_GPIO_ReadPin(GPIOB,LED1_Pin));
    21. }
    22. void LED_2_Contrary(void){
    23. HAL_GPIO_WritePin(GPIOB,LED2_Pin,1-HAL_GPIO_ReadPin(GPIOB,LED2_Pin));
    24. }

            【3】创建串口驱动程序,主要是复写串口回调功能

            1)在ICore添加usart目录,并添加usart.h/usart.c源文件,实现串口驱动功能

            usart.h

    1. #ifndef INC_USART_H_
    2. #define INC_USART_H_
    3. #include "stm32f1xx_hal.h" //HAL库文件声明
    4. #include //用于字符串处理的库
    5. #include "../print/print.h"//用于printf函数串口重映射
    6. extern UART_HandleTypeDef huart1;//声明USART1的HAL库结构体
    7. extern UART_HandleTypeDef huart2;//声明USART2的HAL库结构体
    8. #define USART1_REC_LEN 200//定义USART1最大接收字节数
    9. #define USART2_REC_LEN 200//定义USART1最大接收字节数
    10. extern uint8_t USART1_RX_BUF[USART1_REC_LEN];//接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
    11. extern uint16_t USART1_RX_STA;//接收状态标记
    12. extern uint8_t USART1_NewData;//当前串口中断接收的1个字节数据的缓存
    13. extern uint8_t USART2_RX_BUF[USART2_REC_LEN];//接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
    14. extern uint16_t USART2_RX_STA;//接收状态标记
    15. extern uint8_t USART2_NewData;//当前串口中断接收的1个字节数据的缓存
    16. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);//串口中断回调函数声明
    17. #endif /* INC_USART_H_ */

            usart.c

    1. #include "usart.h"
    2. uint8_t USART1_RX_BUF[USART1_REC_LEN];//接收缓冲,最大USART_REC_LEN个字节.
    3. /*
    4. * bit15:接收到回车(0x0d)时设置HLPUSART_RX_STA|=0x8000;
    5. * bit14:接收溢出标志,数据超出缓存长度时,设置HLPUSART_RX_STA|=0x4000;
    6. * bit13:预留
    7. * bit12:预留
    8. * bit11~0:接收到的有效字节数目(0~4095)
    9. */
    10. uint16_t USART1_RX_STA=0;
    11. uint8_t USART1_NewData;//当前串口中断接收的1个字节数据的缓存
    12. uint8_t USART2_RX_BUF[USART2_REC_LEN];
    13. uint16_t USART2_RX_STA=0;
    14. uint8_t USART2_NewData;
    15. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)//串口中断回调函数
    16. {
    17. if(huart ==&huart1)//判断中断来源(串口1:USB转串口)
    18. {
    19. // printf("%c",USART1_NewData); //测试用,把收到的数据以 a符号变量 发送回电脑
    20. if(USART1_NewData==0x0d){//回车标记
    21. USART1_RX_STA|=0x8000;//标记接到回车
    22. }else{
    23. if((USART1_RX_STA&0X0FFF)
    24. USART1_RX_BUF[USART1_RX_STA&0X0FFF]=USART1_NewData; //将收到的数据放入数组
    25. USART1_RX_STA++; //数据长度计数加1
    26. }else{
    27. USART1_RX_STA|=0x4000;//数据超出缓存长度,标记溢出
    28. }
    29. }
    30. HAL_UART_Receive_IT(&huart1,(uint8_t *)&USART1_NewData,1); //再开启接收中断
    31. }
    32. if(huart ==&huart2)//判断中断来源(串口2:BT模块)
    33. {
    34. // printf("%c",USART2_NewData); //测试用,把收到的数据以 a符号变量 发送回电脑
    35. if(USART2_NewData==0x0d||USART2_NewData==0x0A){//回车标记,(手机APP“蓝牙调试器”回复数据以0x5A为结束符)
    36. USART2_RX_STA|=0x8000;//标记接到回车
    37. }else{
    38. if((USART2_RX_STA&0X0FFF)
    39. USART2_RX_BUF[USART2_RX_STA&0X0FFF]=USART2_NewData; //将收到的数据放入数组
    40. USART2_RX_STA++; //数据长度计数加1
    41. }else{
    42. USART2_RX_STA|=0x4000;//数据超出缓存长度,标记溢出
    43. }
    44. }
    45. HAL_UART_Receive_IT(&huart2,(uint8_t *)&USART2_NewData,1); //再开启接收中断
    46. }
    47. }

            【4】创建蓝牙驱动

            该驱动主要实现通过usart2向蓝牙模块写入数据,(读取数据主要通过串口usart2回调,在usart.c中实现)。在ICore添加bt目录,并添加bt.h/bt.c源文件,实现蓝牙驱动功能

            bt.h

    1. #ifndef BT_BT_H_
    2. #define BT_BT_H_
    3. #include "stm32f1xx_hal.h" //HAL库文件声明
    4. #include "main.h"
    5. #include "../usart/usart.h"
    6. #include "../delay/delay.h"
    7. #include //用于字符串处理的库
    8. #include
    9. #include
    10. #include "stdio.h"
    11. extern UART_HandleTypeDef huart2;//声明UART2的HAL库结构体
    12. void BT_WEEKUP (void);//蓝牙模块唤醒函数
    13. void BT_printf (char *fmt, ...); //BT蓝牙模块发送
    14. #endif /* BT_BT_H_ */

            bt.c

    1. #include "bt.h"
    2. //蓝牙模块唤醒函数
    3. //对蓝牙模块上的PWRC(P00)接口一个低电平脉冲,如不使用睡眠模式可忽略此函数
    4. void BT_WEEKUP (void)
    5. {
    6. HAL_GPIO_WritePin(BT_RE_GPIO_Port,BT_RE_Pin, GPIO_PIN_RESET);//PWRC接口控制
    7. delay_us(100);
    8. HAL_GPIO_WritePin(BT_RE_GPIO_Port,BT_RE_Pin, GPIO_PIN_SET);//PWRC接口控制
    9. }
    10. //蓝牙模块通信,使用UART2,这是BT蓝牙的printf函数
    11. //调用方法:BT_printf("123"); //向UART2发送字符123
    12. void BT_printf (char *fmt, ...)
    13. {
    14. char buff[USART2_REC_LEN+1]; //用于存放转换后的数据 [长度]
    15. uint16_t i=0;
    16. va_list arg_ptr;
    17. va_start(arg_ptr, fmt);
    18. vsnprintf(buff, USART2_REC_LEN+1, fmt, arg_ptr);//数据转换
    19. i=strlen(buff);//得出数据长度
    20. if(strlen(buff)>USART2_REC_LEN)i=USART2_REC_LEN;//如果长度大于最大值,则长度等于最大值(多出部分忽略)
    21. HAL_UART_Transmit(&huart2,(uint8_t *)buff,i,0xffff);//串口发送函数(串口号,内容,数量,溢出时间)
    22. va_end(arg_ptr);
    23. }
    24. //所有USART串口的中断回调函数HAL_UART_RxCpltCallback,统一存放在USART.C文件中。

    五、编译及测试

            【1】功能调用及编译

            1)在main.c文件中进行蓝牙功能调用实现,部分源码如下:

    1. /* USER CODE END Header */
    2. /* Includes ------------------------------------------------------------------*/
    3. #include "main.h"
    4. /* Private includes ----------------------------------------------------------*/
    5. /* USER CODE BEGIN Includes */
    6. #include "../../ICore/led/led.h"
    7. #include "../../ICore/key/key.h"
    8. #include "../../ICore/delay/delay.h"
    9. #include "../../ICore/print/print.h"//用于printf函数串口重映射
    10. #include "../../ICore/bt/bt.h"
    11. /* USER CODE END Includes */
    12. /* Private typedef -----------------------------------------------------------*/
    13. /* USER CODE BEGIN PTD */
    14. /* USER CODE END PTD */
    15. /* Private define ------------------------------------------------------------*/
    16. /* USER CODE BEGIN PD */
    17. /* USER CODE END PD */
    18. /* Private macro -------------------------------------------------------------*/
    19. /* USER CODE BEGIN PM */
    20. /* USER CODE END PM */
    21. /* Private variables ---------------------------------------------------------*/
    22. UART_HandleTypeDef huart1;
    23. UART_HandleTypeDef huart2;
    24. /* USER CODE BEGIN PV */
    25. /* USER CODE END PV */
    26. /* Private function prototypes -----------------------------------------------*/
    27. void SystemClock_Config(void);
    28. static void MX_GPIO_Init(void);
    29. static void MX_USART1_UART_Init(void);
    30. static void MX_USART2_UART_Init(void);
    31. /* USER CODE BEGIN PFP */
    32. /* USER CODE END PFP */
    33. /* Private user code ---------------------------------------------------------*/
    34. /* USER CODE BEGIN 0 */
    35. /* USER CODE END 0 */
    36. /**
    37. * @brief The application entry point.
    38. * @retval int
    39. */
    40. int main(void)
    41. {
    42. /* USER CODE BEGIN 1 */
    43. /* USER CODE END 1 */
    44. /* MCU Configuration--------------------------------------------------------*/
    45. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    46. HAL_Init();
    47. /* USER CODE BEGIN Init */
    48. /* USER CODE END Init */
    49. /* Configure the system clock */
    50. SystemClock_Config();
    51. /* USER CODE BEGIN SysInit */
    52. /* USER CODE END SysInit */
    53. /* Initialize all configured peripherals */
    54. MX_GPIO_Init();
    55. MX_USART1_UART_Init();
    56. MX_USART2_UART_Init();
    57. /* USER CODE BEGIN 2 */
    58. ResetPrintInit(&huart1);//将printf()函数映射到UART1串口上
    59. HAL_UART_Receive_IT(&huart1,(uint8_t *)&USART1_NewData,1);//开启串口1接收中断
    60. HAL_UART_Receive_IT(&huart2,(uint8_t *)&USART2_NewData,1); //再开启串口3接收中断
    61. /* USER CODE END 2 */
    62. /* Infinite loop */
    63. /* USER CODE BEGIN WHILE */
    64. while (1)
    65. {
    66. //demo 蓝牙02
    67. if(USART2_RX_STA&0xC000){//判断中断接收标志位(蓝牙模块BT,使用USART2)
    68. BT_printf("%c",USART2_RX_STA);
    69. if((USART2_RX_STA&0x7FFF) == 1) //判断接收数量1个(手机控制程序)
    70. {
    71. BT_printf("%c",USART2_RX_BUF[0]);
    72. switch (USART2_RX_BUF[0]){//判断接收数据的内容
    73. case 0x41:
    74. LED_1(1);//LED1控制
    75. BT_printf("Relay ON");//返回数据内容,在手机APP上显示
    76. break;
    77. case 0x44:
    78. LED_1(0);//LED1控制
    79. BT_printf("Relay OFF");//返回数据内容,在手机APP上显示
    80. break;
    81. case 0x42:
    82. LED_2(1);//LED1控制
    83. BT_printf("LED1 ON");//返回数据内容,在手机APP上显示
    84. break;
    85. case 0x45:
    86. LED_2(0);//LED1控制
    87. BT_printf("LED1 OFF");//返回数据内容,在手机APP上显示
    88. break;
    89. case 0x43:
    90. LED_1(0);//LED1控制
    91. LED_2(0);//LED1控制
    92. BT_printf("BEEP");//返回数据内容,在手机APP上显示
    93. break;
    94. case 0x46:
    95. BT_printf("CPU Reset");//返回数据内容,在手机APP上显示
    96. HAL_Delay(1000);//延时
    97. NVIC_SystemReset();//系统软件复位函数
    98. break;
    99. default:
    100. //冗余语句
    101. break;
    102. }
    103. }
    104. printf("%.*s\r\n", USART2_RX_STA&0X0FFF, USART2_RX_BUF);//BT接收内容,转发usart1
    105. USART2_RX_STA=0;//标志位清0,准备下次接收
    106. }
    107. //接收到电脑发送给(usart1)数据,转身将其发送到给usart2,进而实现送数据给BT模块
    108. if(USART1_RX_STA&0xC000){//结束标记
    109. BT_printf("%.*s\r\n",USART1_RX_STA&0X0FFF, USART1_RX_BUF);
    110. USART1_RX_STA=0;//接收重新开始
    111. HAL_Delay(100);//等待
    112. }
    113. if(KEY_1())//按下KEY1判断
    114. {
    115. LED_1(1);//LED1控制 //在蓝牙模块回复之前先将LED状态复位
    116. LED_2(0);//LED2控制
    117. BT_printf("AT+NAMEPYFREEBT");//向蓝牙模块发送AT指令(修改模块的广播名为PYFREEBT)
    118. }
    119. if(KEY_2())//按下KEY2判断
    120. {
    121. LED_1(0);//LED1控制 //在蓝牙模块回复之前先将LED状态复位
    122. LED_2(1);//LED2控制
    123. BT_printf("AT+DISC");//向蓝牙模块发送AT指令(断开与手机的连接)
    124. }
    125. /* USER CODE END WHILE */
    126. /* USER CODE BEGIN 3 */
    127. }
    128. /* USER CODE END 3 */
    129. }

           2)设置编译输出支持,右键工程进入项目属性设置页面:

              3)点击编译按钮,完成编译(整个工程需要源码修改或添加的源文件如下):

            【2】程序测试

            1)测试过程需要三个工具文件支持,读者可以自网上搜索最新版本或采用其他同功能工具替代测试:

            FlyMCU加载工具,将生成的.hex程序文件加载到板子上

            SSCOM5串口工具,连接MCU的USART1,实现调试信息显示及下行指令输入

            蓝牙调试器工具,本文用的是1.9安卓版本。

             后续补充,应读者要求,提供CSDN下载链接:        https://download.csdn.net/download/py8105/87174936

            2)加载程序,选择串口,选择程序(.hex),点击开始编程按钮:

             3)手机打开蓝牙调试器(别忘了开启手机蓝牙功能),进入界面,搜索蓝牙,点击蓝牙边上“+”按钮连接蓝牙模块,采用SSCOM串口工具连接到usart1上,就可以通过蓝牙通信实现手机(蓝牙调试器)与电脑(串口工具)的通信了,在蓝牙调试器发送数据时,十六进制时需要加上“0A”作为结尾,如果十进制发送时,注意加上换行再发送:

            注:本文连接前,点击开发板的按键1更改了蓝牙名称PYFREEBT:

    1. if(KEY_1())//按下KEY1判断
    2. {
    3. LED_1(1);//LED1控制 //在蓝牙模块回复之前先将LED状态复位
    4. LED_2(0);//LED2控制
    5. BT_printf("AT+NAMEPYFREEBT");//向蓝牙模块发送AT指令(修改模块的广播名为PYFREEBT)
    6. }

            串口发送数据:

            可以进入按钮控制页面进行指令定制设置

             至此实现了MCU(STM32F103C8T6)通过蓝牙模块与外界设备进行通信,另外通过AT指令也可以控制蓝牙模块。

  • 相关阅读:
    three.js中射线对性能的影响
    mybatis-puls使用修改语句部分字段不生效
    day5-day6【代码随想录】螺旋矩阵II
    微服务-微服务Nacos配置中心
    Linux下多个命令串联执行(管道/xargs/exec)
    HNU计网实验:实验一 应用协议与数据包分析实验(使用Wireshark)
    React核心原理与实际开发
    安装单机Hadoop
    Vue中自定义事件
    视觉检测系统可以检测太阳能电池片哪些方面的缺陷?
  • 原文地址:https://blog.csdn.net/py8105/article/details/128050646