# 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. 下载蓝牙调试助手,添加调试工程 调试工程添加流程: 点击底部的小加号,添加调试工程 1 通讯设置:添加两个字节X,Y。 2 编辑器件:配置参数与上图输入的数据匹配即可。 93 TB6612参考原理图: 引脚图 成品预览: 3 #### 参与贡献 1. Fork 本仓库 2. 新建 Feat_xxx 分支 3. 提交代码 4. 新建 Pull Request