# BluetoothVehicle
**Repository Path**: fuquanyuo/bluetooth-vehicle
## Basic Information
- **Project Name**: BluetoothVehicle
- **Description**: 基于HC-06蓝牙模块驱动F103系32板的智能小车
- **Primary Language**: C
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2023-10-30
- **Last Updated**: 2024-02-22
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# BluetoothVehicle
#### 介绍
基于HC-06蓝牙模块驱动F103系32板的智能小车
硬件支持:stm32f103c8t6,HC-06,TB6612,面包板,电池
#### 软件架构
1.Middle层:主要数据的发送接收,及处理,串口初始化
```c
/*接收数据*/
void get_slave_data(uint8_t data)
该函数用来接收蓝牙发送的数据,对该数据进行保存,
数据包格式:0xA5(1b,头) key1.key2(2b,自定义数据) 0x(1b.效验位) 0x5A(1b,尾)
具体的数据报说明请在蓝牙调试助手查阅
//中断接收数据
void USART3_IRQHandler(void)
{
uint8_t data;
if(USART_GetITStatus(USART3,USART_IT_RXNE)!=RESET)
{
USART_ClearITPendingBit(USART3,USART_IT_RXNE);
data = USART_ReceiveData(USART3);
get_slave_data(data); //获取数据
if(uart_flag==1)
{
uart_flag=0;
lanya_receive(); //数据解析
}
}
}
```
2.Handler层:该层初始化了PWM,GPIOX。配置了PWM的输出频率10Khz,设置了TB6612电机供电板的输出由PA_3.4.5.6输出控制。
```c
void TIM2_PWM_Init(u16 arr, u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStrue;
TIM_OCInitTypeDef TIM_OCInitTypeStrue;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // 使能定时器2时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 使能GPIO外设
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2; // 定时器引脚PA1 CH2 PA2 CH3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出模式,A0引脚复用
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化GPIO
TIM_TimeBaseInitStrue.TIM_Period = arr; // 计数周期
TIM_TimeBaseInitStrue.TIM_Prescaler = psc; // 预分频系数
TIM_TimeBaseInitStrue.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数模式
TIM_TimeBaseInitStrue.TIM_ClockDivision = TIM_CKD_DIV1; // 一般不使用,默认TIM_CKD_DIV1
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStrue); // 初始化定时器TIM2
TIM_OCInitTypeStrue.TIM_OCMode = TIM_OCMode_PWM1; // PWM模式1,定时器计数小于 TIM_Pulse时,输出有效电平
TIM_OCInitTypeStrue.TIM_OCPolarity = TIM_OCNPolarity_High; // 输出有效电平为高电平
TIM_OCInitTypeStrue.TIM_OutputState = TIM_OutputState_Enable; // 使能PWM输出
TIM_OCInitTypeStrue.TIM_Pulse = 0; // 设置待装入捕获比较寄存器的脉冲值
TIM_OC2Init(TIM2, &TIM_OCInitTypeStrue); // 初始化定时器2 通道2
TIM_OCInitTypeStrue.TIM_OCMode = TIM_OCMode_PWM1; // PWM模式1,时器计数小于TIM_Puls输出有效电平
TIM_OCInitTypeStrue.TIM_OCPolarity = TIM_OCNPolarity_High; // 输出有效电平为高电平
TIM_OCInitTypeStrue.TIM_OutputState = TIM_OutputState_Enable; // 使能PWM输出
TIM_OCInitTypeStrue.TIM_Pulse = 0; // 设置待装入捕获比较寄存器的脉冲值
TIM_OC3Init(TIM2, &TIM_OCInitTypeStrue); // 初始化定时器2 通道3
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Disable); // CH2预装载使能
TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Disable); // CH3预装载使能
TIM_ARRPreloadConfig(TIM2, ENABLE); // 预装载使能
TIM_Cmd(TIM2, ENABLE); // 使能定时器TIM2
}
void Motor_GpioPin_Config(){
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能端口时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); //使能端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; //端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //50M
GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIO
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; //端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //50M
GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIO
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //50M
GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIO
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //50M
GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIO
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; //使能IO初始化
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA,GPIO_Pin_3); //io输出0,防止电机乱转
GPIO_ResetBits(GPIOA,GPIO_Pin_4); //io输出0,防止电机乱转
GPIO_ResetBits(GPIOA,GPIO_Pin_5); //io输出0,防止电机乱转
GPIO_ResetBits(GPIOA,GPIO_Pin_6); //io输出0,防止电机乱转
GPIO_SetBits(GPIOC,GPIO_Pin_13);
}
```
3.Controller层:该层调用了Middle层接收到的数据(key1,key2)及Handler层的初始化,来控制小车的运动状态。
```c
//通过"X"象限控制小车
void Quadrant_Ctr_Car(int key1 , int key2)
{
//原点停止
if(key1==0 && key2==0) StopVehicle();
//第二象限前进
if(key1>=128 && key2<=127) startVehicle();
//第一象限后退
if(key1<=127 && key2<=127) BackwardVehicle();
//第三象限左转
if(key1>=128 && key2>=128) LeftwardVehicle();
//第四象限右转
if(key1<=127 && key2>=128) RightwardVehicle();
}
//通过XY轴控制小车
void XYaxis_Ctr_Car(int key1,int key2)
{
//AD变量记录第一象限内的差值,用量辅助小车的运动方向,以此类推
int AD,BD,CD,DD;
if(key1==0 && key2==0) StopVehicle();
//前进
if(key2<=127)
{
AD=key2-key1;
BD=key1-key2;
if(AD>=0 || BD<=127 )
{
startVehicle();
}
}
//后退
else
{
CD=key2-key1;
DD=key2-key1;
if(CD>=0 || DD<=127)
{
BackwardVehicle();
}
}
//右转
if(key<=127)
{
AD=key1-key2;
DD=key2-key1;
if(AD>=0 || DD<=127)
{
RightwardVehicle();
}
}
//左转
else
{
BD=key1-key2;
CD=key1-key2;
if(BD<=127 || CD>=0)
{
LeftwardVehicle();
}
}
AD=0;
BD=0;
CD=0;
DD=0;
}
```
4.Application层:该层对上三层进行简单调用即可。
```c
void ctrlVehicleADVByBT(){
//初始化控制引脚
Controller_Init();
//初始化串口
Usart3_init(115200);
}
void Ctr_Car_State()
{
XYaxis_Ctr_Car( key1 ,key2 );
}
```
#### 使用说明
1. 下载该项目代码,并烧录到开发板
2. 下载蓝牙调试助手,添加调试工程
调试工程添加流程:
点击底部的小加号,添加调试工程
通讯设置:添加两个字节X,Y。
编辑器件:配置参数与上图输入的数据匹配即可。
TB6612参考原理图:
成品预览:
#### 参与贡献
1. Fork 本仓库
2. 新建 Feat_xxx 分支
3. 提交代码
4. 新建 Pull Request