目录标题

  • 控制流程
  • 硬件设计
  • 软件设计
  • 工程目录:
  • 实验效果:
  • 参考资料



先导知识

  • STM32入门笔记(02):AFIO复用端口与重映射 、NVIC中断优先级管理、外部中断、串口通信及串口实验(SPL库函数版)

控制流程

手机APP ——蓝牙通信——> 蓝牙TBO4模块 ——UART2串口通信 ——> MCU STM32F407

硬件设计

硬件准备:

  • 1.STM32F407VET6
  • 2.无线蓝牙串口透传BT04从机

Android 串口获取蓝牙码值_单片机

BL(蓝牙)

MCU (F407)

Rx

PD5 (USART2_TX)

Tx

PD6 (USART2_RX)

Android 串口获取蓝牙码值_物联网_02

软件工具:

  • 1.FlyMcu 程序串口烧录
  • 2.XCOM V2.0 串口调试助手
  • 3.蓝牙APP(用于测试遥控)

A

B

C

D

E

F

G

H

1

2

3

4

5

6

7

8


右前


右后


左后


左前

Android 串口获取蓝牙码值_物联网_03

Android 串口获取蓝牙码值_#include_04

软件设计

工程目录:

Android 串口获取蓝牙码值_stm32_05

usartx.h文件

#ifndef __USRATX_H
#define __USRATX_H 
#include "stdio.h"
#include "sys.h"
#include "system.h"
void uart2_init(u32 bound);
int USART2_IRQHandler(void);
void usart2_send(u8 data);
#endif

usartx.c文件

#include "usartx.h"
/**************************************************************************
函数功能:串口2初始化
入口参数:无
返回  值:无
**************************************************************************/
void uart2_init(u32 bound)
{  	 
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);	  //使能GPIO时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); //使能USART时钟
	
	GPIO_PinAFConfig(GPIOD,GPIO_PinSource5,GPIO_AF_USART2);	
	GPIO_PinAFConfig(GPIOD,GPIO_PinSource6 ,GPIO_AF_USART2);	 
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;            //输出模式
	GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;          //推挽输出
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;       //高速50MHZ
	GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;            //上拉
	GPIO_Init(GPIOD, &GPIO_InitStructure);  		          //初始化
	
	//UsartNVIC配置
	NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
	 //抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;
	//子优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;	
   //IRQ通道使能	
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	//根据指定的参数初始化VIC寄存器		
	NVIC_Init(&NVIC_InitStructure);	
	
	//初始化设置
	USART_InitStructure.USART_BaudRate = bound; //串口波特率
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;  //字长为8位数据格式
	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_Rx | USART_Mode_Tx;	//收发模式
	USART_Init(USART2, &USART_InitStructure);    //初始化串口2
	
	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); //开启串口接受中断
	USART_Cmd(USART2, ENABLE);                     //使能串口2 
}

/**************************************************************************
函数功能:串口2接收中断
入口参数:无
返回  值:无
**************************************************************************/
int USART2_IRQHandler(void)
{	
	int Usart_Receive;
	if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //判断是否接收到数据
	{	      
		static u8 Flag_PID,i,j,Receive[50],Last_Usart_Receive;
		static float Data;
				
		Usart_Receive=USART2->DR; //读取数据
		
	   printf("Usart_Receive=%d \r\n",Usart_Receive);

		if(Usart_Receive==0x41&&Last_Usart_Receive==0x41&&APP_ON_Flag==0)// 0x41:0100 0001 
			//开机10秒之后,按下APP的前进键进入APP控制模式
		  //APP控制标志位置1,其它标志位置0
			PS2_ON_Flag=0,Remote_ON_Flag=0,APP_ON_Flag=1,CAN_ON_Flag=0,Usart_ON_Flag=0;
            Last_Usart_Receive=Usart_Receive;			
	  
		if(Usart_Receive==0x4B) //0x4B:0100 1011    -- 75
			Turn_Flag=1;   //进入APP转向控制界面
//		  printf("Turn_Flag=1 进入APP转向控制界面 \r\n");
		
	  else if(Usart_Receive==0x49||Usart_Receive==0x4A) //0x49:0100 1001 --73; 0x4A:0100 1010 --74
			Turn_Flag=0;	//进入APP方向控制界面	
//		  printf("Turn_Flag=0 进入APP方向控制界面	\r\n");
//
		if(Turn_Flag==0) 
		{
			
			//APP摇杆控制界面命令
			if(Usart_Receive>=0x41&&Usart_Receive<=0x48)  // 0x41:0100 0001--65 ; 0x48:0100 1000 --72
			{	
				Flag_Direction = Usart_Receive-0x40;   // 例如:(0x42)为01000010 - (0x40)为01000000 = 0010 = 2,也就是66-64=2
			}
			else	if(Usart_Receive<=8)   // Usart_Receive为0(即0x00=0000 0000);  2(即0x02=0000 0010) …… 7(即0x07=0000 0111);8(即0x08=0000 1000) -- 0~8
			{			
				Flag_Direction=Usart_Receive;//0、1、2、3、4、5、6、7、8 接收手机app端的方向控制指令  
			}	
			else  Flag_Direction=0;
			
		  printf("进入APP方向控制界面 Flag_Direction=%d \r\n",Flag_Direction);

		}
//	以下代码内容可选择性参考 	
		else if(Turn_Flag==1)
		{
			
			//APP转向控制界面命令
			if     (Usart_Receive==0x43) Flag_Left=0,Flag_Right=1;   //右自转
			else if(Usart_Receive==0x47) Flag_Left=1,Flag_Right=0;   //左自转
			else                         Flag_Left=0,Flag_Right=0;
			if     (Usart_Receive==0x41||Usart_Receive==0x45) Flag_Direction=Usart_Receive-0x40;
			else  Flag_Direction=0;
		}
		if(Usart_Receive==0x58)  RC_Velocity=RC_Velocity+100; //加速按键,+100mm/s
		if(Usart_Receive==0x59)  RC_Velocity=RC_Velocity-100; //减速按键,-100mm/s
	  
	 
	 //以下是与APP调试界面通讯
	 if(Usart_Receive==0x7B) Flag_PID=1;    //APP参数指令起始位
	 if(Usart_Receive==0x7D) Flag_PID=2;    //APP参数指令停止位

	 if(Flag_PID==1)  //采集数据
	 {
		Receive[i]=Usart_Receive;
		i++;
	 }
	 if(Flag_PID==2)  //分析数据
	 {
			if(Receive[3]==0x50) 	 PID_Send=1;
			else  if(Receive[1]!=0x23) 
      {								
				for(j=i;j>=4;j--)
				{
					Data+=(Receive[j-1]-48)*pow(10,i-j);
				}
				switch(Receive[1])
				 {
					 case 0x30:  RC_Velocity=Data;break;
					 case 0x31:  Velocity_KP=Data;break;
					 case 0x32:  Velocity_KI=Data;break;
					 case 0x33:  break;
					 case 0x34:  break;
					 case 0x35:  break;
					 case 0x36:  break;
					 case 0x37:  break;
					 case 0x38:  break; 	
				 }
      }		
      	
      //相关标志位清零			
			Flag_PID=0;
			i=0;
			j=0;
			Data=0;
			memset(Receive, 0, sizeof(u8)*50); //数组清零
	 }
   if(RC_Velocity<0)   RC_Velocity=0; 	 
  }
  return 0;	
}
/**************************************************************************
函数功能:串口2发送数据
入口参数:要发送的数据
返回  值:无
**************************************************************************/
void usart2_send(u8 data)
{
	USART2->DR = data;
	while((USART2->SR&0x40)==0);	
}

system.h 文件

#ifndef __SYSTEM_H
#define __SYSTEM_H

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

// extern 申明变量定义在别的文件中 system.c
//PS2手柄、蓝牙APP、航模手柄、CAN通信、串口1通信控制标志位。这5个标志位默认都为0
extern u8 PS2_ON_Flag, APP_ON_Flag, Remote_ON_Flag, CAN_ON_Flag, Usart_ON_Flag; 
extern u8 Flag_Left, Flag_Right, Flag_Direction, Turn_Flag; //蓝牙遥控相关的标志位
extern u8 PID_Send; //向蓝牙APP发送参数的标志位
extern float RC_Velocity; //遥控小车的默认速度,单位:mm/s
extern float Move_X, Move_Y, Move_Z;   //小车三轴目标运动速度,单位:m/s
extern float Velocity_KP,Velocity_KI;//速度控制PID参数
extern void systemInit(void);
//C库函数的相关头文件
#include <stdio.h> 
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "stdarg.h"

#endif

system.c文件

#include "system.h"

u8 PS2_ON_Flag=0, APP_ON_Flag=0, Remote_ON_Flag=0, CAN_ON_Flag=0, Usart_ON_Flag=0; //PS2手柄、蓝牙APP、航模手柄、CAN通信、串口1通信控制标志位。这5个标志位默认都为0,代表串口3控制模式
u8 Flag_Left, Flag_Right, Flag_Direction=0, Turn_Flag; //蓝牙遥控相关的标志位
u8 PID_Send; //向蓝牙APP发送参数的标志位
float RC_Velocity=500; //遥控小车的默认速度,单位:mm/s
float Move_X, Move_Y, Move_Z;   //小车三轴目标运动速度,单位:m/s
float Velocity_KP=700,Velocity_KI=700; //速度控制PID参数

void systemInit(void)
{       
	//延时函数初始化168MHz时钟
	delay_init(168);
	//初始化串口1 波特率设置为115200
	uart_init(115200);
	//串口2初始化,通信波特率9600,用于与蓝牙APP端通信
	uart2_init(9600);  
}

main.c文件

#include "system.h"
int main(void)
{
	systemInit();//初始化
    while(1){}
}

实验效果:

串口调试助手显示接收到的指令。

Android 串口获取蓝牙码值_stm32_06

资料下载:

  • STM32F407VET6+串口通信蓝牙+SPL固件库函数版(0402)