STM32循迹小车/Android蓝牙控制小车(三)

循迹蓝牙小车的第三篇终于来了,这篇开篇先来介绍一下整个开发过程中得构思思路。本来这应该放在第一篇,但是实际思路会因为开发过程中遇到的问题而改变,到今天为止小车的三个目标功能都已经实现。所以在介绍app控制小车之前先来理清一下思路。

整个设计软件方面分为两大块:

一、STM32作为主控制器,有三种工作模式,三种模式通过开发板上的物理按键或者App虚拟按键来进行切换:

1、红外遥控——通过接受解码红外头接收到的遥控信息来控制小车
2、循线跟踪——通过循环扫描光电循迹模块检测黑线并且跟踪黑线行驶
3、手机蓝牙控制——HC-05蓝牙模块接收App通过蓝牙发送的信息控制小车行驶

二、Android端APP:
App功能分为两大块:蓝牙连接、控制小车,两大功能模块通过两个Activity来实现。

 蓝牙连接包括:1、判断当前设备是否支持蓝牙2、判断当前设备蓝牙功能是否打开3、读取已经配对的蓝牙信息4、扫描周围蓝牙信息5、与指定蓝牙发起配对6、与指定蓝牙发起连接7、断开连接、取消配对控制小车:
控制小车其实就是和小车通讯,只需要通过已经连接蓝牙的Socket通道,向小车端发送约定的信息,
小车端STM32接收到信息,解码之后根据约定的含义控制小车。

先从App开始:

App开发软件平台AndroidStudio2.2.2
硬件平台:Android手机,目标API 28,最低API 24。检测平台OPPO A7X

APP工程文件构架:

下图详解说明了每个文件的具体作用:

蓝牙连接过程详细说明请访问Android 官服档,有详细说明:
Android 官服文档 ——蓝牙概览

APP UI界面:

循迹蓝牙小车.mp4

STM32蓝牙接收端源码:

 因为TC-05蓝牙模块数据通过串口输出,所以使用的时候不需要涉及到任何蓝牙协议。直接把模块当成串口来使用就行,代码相对简单:

串口初始化程序:

void LanYa_Init(void){GPIO_InitTypeDef GPIO_InitStrue;USART_InitTypeDef USART_InitStrue;NVIC_InitTypeDef NVIC_InitStrue;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//① 使能GPIOA时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);//① 使能USART2时钟GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP;GPIO_InitStrue.GPIO_Pin=GPIO_Pin_2;GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;GPIO_Init(GPIOA,&GPIO_InitStrue);//②设置发送端IOGPIO_InitStrue.GPIO_Mode=GPIO_Mode_IN_FLOATING;GPIO_InitStrue.GPIO_Pin=GPIO_Pin_3;GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;GPIO_Init(GPIOA,&GPIO_InitStrue);//②设置接收端IOUSART_InitStrue.USART_BaudRate=9600;USART_InitStrue.USART_HardwareFlowControl=USART_HardwareFlowControl_None;USART_InitStrue.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;USART_InitStrue.USART_Parity=USART_Parity_No;USART_InitStrue.USART_StopBits=USART_StopBits_1;USART_InitStrue.USART_WordLength=USART_WordLength_8b; USART_Init(USART2,&USART_InitStrue);//③设置串口参数,波特率9600,发送接收双工模式,无奇偶校验,数据位8位,停止位1位,无流控制USART_Cmd(USART2,ENABLE);//使能串口1USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);//开启接收中断NVIC_InitStrue.NVIC_IRQChannel=USART2_IRQn;NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE;NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=1;NVIC_InitStrue.NVIC_IRQChannelSubPriority=1;//中断优先级设置NVIC_Init(&NVIC_InitStrue);
}//串口2中断服务程序
void USART2_IRQHandler(void)
{if(USART_GetITStatus(USART2,USART_IT_RXNE)){LanYaRes = USART_ReceiveData(USART2);  //蓝牙接收到的数据LCD_ShowNum(30+8*16,70,1,5,16);flag = 0;}
}int GetLanYaRes(void){if(flag == 0){flag = 1;return LanYaRes;}else return -1;
}

数据接收处理代码:

     LCD_Clear(WHITE);LanYa_Init();      //蓝牙接收初始化
//      USART_Cmd(USART2,ENABLE);//使能串口2
//      USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);//开启串口2接收中断pwm_sudu = 10000;    flagSudu = 0;while(mode1 == 2){ //模式3,App蓝牙模式mode1 = GetMode();if(flagSudu == 0){PGout(13) = 0;PGout(14) = 0;flagSudu = 1;}Show_Str(30,30,200,16,"循迹小车蓝牙调试界面",16,0); POINT_COLOR=RED;LanYaRes1 = GetLanYaRes();Show_Str(30,70,200,16,"蓝牙接收数据:",16,0);switch(LanYaRes1){case 48:{TIM_SetCompare4(TIM3,pwm_sudu);   //前进PGout(13) = 1;PGout(14) = 0;LanYaRes1 = -1;}break;case 50:{TIM_SetCompare4(TIM3,pwm_sudu);  //后退PGout(13) = 0;PGout(14) = 1;LanYaRes1 = -1;                 }break;case 49:{TIM_SetCompare4(TIM3,0);                //停止PGout(13) = 0;PGout(14) = 0;LanYaRes1 = -1;                 }break;case 51:{                                                        //加速if(pwm_sudu <= 14000)pwm_sudu+=500;else pwm_sudu=8000;   TIM_SetCompare4(TIM3,pwm_sudu);LanYaRes1 = -1;                  }break; case 52:{                                                       //减速if(pwm_sudu >=1000)pwm_sudu-=500;else pwm_sudu=0;TIM_SetCompare4(TIM3,pwm_sudu);LanYaRes1 = -1;                  }break;case 54:{                                                        //左转TIM_SetCompare2(TIM3,MIN_zou);LanYaRes1 = -1;                   }break;                 case 53:{                                                       //右转TIM_SetCompare2(TIM3,MAX_you);LanYaRes1 = -1;                   }break; case 56:{                                                       //右转TIM_SetCompare2(TIM3,Z_qian);LanYaRes1 = -1;                    }break;default:break;}}

代码中设计一条LanYaRes1 = -1; 的代码,为什么要在每次数据处理之后将LanYaRes1 = -1置为-1?
因为蓝牙接收到的信息不是按键,如果不在每使用一次数据信息之后将数据清理,那么同一条数据就会重复直行很多次,就像按键处理里面的连续按键一样。可以看到,在上面一个程序片段中,也有相似的代码:flag = 0; return -1; 如下,也是同样的原因。

if(USART_GetITStatus(USART2,USART_IT_RXNE)){LanYaRes = USART_ReceiveData(USART2);    //蓝牙接收到的数据LCD_ShowNum(30+8*16,70,1,5,16);flag = 0;}
}int GetLanYaRes(void){if(flag == 0){flag = 1;return LanYaRes;}else return -1;
}

App端源码:

public void onClick(View v) {switch (v.getId()){case R.id.BluetoothConnectivity:{   //连接蓝牙startActivityForResult(new Intent(MainActivity.this,Main2Activity.class),1);
//                Toast.makeText(MainActivity.this,"按“搜索”开始扫描附近蓝牙设备",Toast.LENGTH_LONG).show();}break;case R.id.Forward_Button:{          //前进if(writeTask != null)writeTask.doInBackground(""+0);}break;case R.id.Stop_Button:{          //停止if(writeTask != null)writeTask.doInBackground(""+1);}break;case R.id.Back_Button:{          //后退if(writeTask != null)writeTask.doInBackground(""+2);}break;case R.id.Accelerate_Button:{          //加速if(writeTask != null)writeTask.doInBackground(""+3);}break;case R.id.SlowDown_Button:{          //减速if(writeTask != null)writeTask.doInBackground(""+4);}break;case R.id.Right_Button:{          //右转if(writeTask != null)writeTask.doInBackground(""+5);}break;case R.id.Left_Button:{          //左转if(writeTask != null)writeTask.doInBackground(""+6);}break;case R.id.Mode_Button:{          //模式切换if(writeTask != null)writeTask.doInBackground(""+7);}break;case R.id.StraightTravel_Button:{          //直行if(writeTask != null)writeTask.doInBackground(""+8);}break;default:writeTask.cancel(); //关闭蓝牙通道}}@Overrideprotected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
//        super.onActivityResult(requestCode, resultCode, data);switch (requestCode){case 1:{if(resultCode == RESULT_OK){if(data.getParcelableExtra("connectBluetooth") != null)currentBluetoothDevice = data.getParcelableExtra("connectBluetooth"); //接收反馈回来的当前连接蓝牙设备LanYa_TextView.setText("蓝牙“" + currentBluetoothDevice.getName() + "”已连接");if(((GlobalBlueSocket)getApplication()).getGlobalBlueSocket() != null)mBluetoothSocket = ((GlobalBlueSocket)getApplication()).getGlobalBlueSocket();  //通过全局变量获取蓝牙套接字writeTask =  new WriteTask(mBluetoothSocket);}}break;default:break;}}

关于蓝牙连接以及相关的逻辑代码,因为涉及功能多逻辑复杂,将在下篇进行介绍。

STM32循迹小车/Android蓝牙控制小车(一)
STM32循迹小车/Android蓝牙控制小车(二)
STM32循迹小车/Android蓝牙控制小车(三)
STM32循迹小车/Android蓝牙控制小车(四)完结篇——Android经典蓝牙开发

STM32循迹小车/Android蓝牙控制小车(三)相关推荐

  1. stm32的语音识别_基于stm32循迹避障语音控制金属探测蓝牙小车设计(原理图+pcb+源码+参考文档)...

    功能描述及设计原理: 小车具有检测里程功能,在金属探测模式,槽型光耦会检测小车车轮的圈数,以此来计算小车行走的里程,并可以通过OLED屏幕显示出来.还可以显示小车的工作模式以及小车距离前方障碍物的距离 ...

  2. stm32项目_stm32f103c8t6项目_循迹避障小车完整制作过程_智能小车设计_STM32智能小车教程-循迹-避障-蓝牙遥控-跟随

    [硬件] 元件选型 照片上传出问题了,改天补上,着急的可以看视频 视频链接在这里 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sKjJGMXv-16463139639 ...

  3. 超声波模块详细介绍(stm32循迹小车中超声波的介绍)

    超声波模块详细介绍(stm32循迹小车中超声波的介绍) 超声波模块是非常重要的一个模块,今天给大家全面介绍一下超声波模块的原理以及用法,代码的编写. 1 超声波模块的认识 首先,市面上的常见超声波模块 ...

  4. Java关于蓝牙单片机的类,BluetoothCar 蓝牙控制小车 需要硬件单片机电源等配合 需 模块 Java Develop 256万源代码下载- www.pudn.com...

    文件名称: BluetoothCar下载  收藏√  [ 5  4  3  2  1 ] 开发工具: Java 文件大小: 976 KB 上传时间: 2016-04-18 下载次数: 0 提 供 者: ...

  5. STM32循迹小车系列教程(三)—— 使用灰度传感器循迹

    本章节主要讲解如何获取灰度传感器值以及如何使用灰度传感器循迹 灰度传感器简介 灰度传感器如图 1 所示: 灰度传感器 使用一对抗干扰较强的光电传感器,其中发射管的光源采用高亮白色聚光 LED,发射管端 ...

  6. STM32循迹避障小车制作代码详解(简单实现版)

    感谢几年来大家的支持,看到大家对工程的呼声很高,所以来把工程上传了,大家自行下载即可哈,谢谢大家支持 这个代码是进阶版的,就是可以跑的很快的,和上面博客的主要区别就是这个代码的避障机制并不是做在主ma ...

  7. 个人项目 小跟班——蓝牙控制小车(蓝牙控制篇)

    5 蓝牙的配置 到了核心部分了,首先,想要控制手机蓝牙的打开和关闭,需要在manifest中添加相应的权限: <uses-permission android:name="androi ...

  8. 蓝牙控制小车教程:STC89C52RC + HC-06蓝牙模块

    目录 前期准备: 开发环境: 设备:单片机(以STC89C52RC为例),HC-06 , 串口下载器 IDE:AndroidStudio , keil4 工具:串口调试助手  , stc-isp 设备 ...

  9. Android蓝牙遥控小车软件

    PS:不需写一行Android代码哦~~~                    很多热衷于玩单片机小车.机器人的童靴,往往也向往着有天能自己编写一个Android手机的遥控程序,通过自己的手机遥控小 ...

最新文章

  1. 嵌入式系统一次EMMC测试的体会及错误分析过程
  2. ThreadLocal类与Synchonized对象锁的区别
  3. MATLAB拉格朗日插值
  4. React开发(100):3.0没有image
  5. 局域网中搜计算机无法访问,怎么找不到共享电脑,手把手教你局域网中共享电脑找不到怎么办...
  6. B站 - 黑客攻防 入门到入狱 [网络安全] -笔记
  7. html向下三角箭头,CSS 实现三角形尖角箭头的实例
  8. 【刷机】小米平板1刷ROM时出现E1001 Error:7和twrp恢复备份报错Error:255的报错解决方法
  9. 中国知网上html是什么意思,知网上网络首发是什么意思
  10. 隐私计算在普惠金融领域的应用研究
  11. 揭开docker的神秘面纱?镜像制作
  12. 内存数据库-H2简介与实践
  13. 开源B2B2C WSTMart商城系统开发框架及插件介绍
  14. 怎么网络同步计算机的本地时间,VBA实现本地计算机时间与网服务器时间的同步...
  15. DELPHI BULK INSERT
  16. mysqldump时域问题
  17. 电子现金 圈存、补登
  18. 阳离子微球二氧化硅单分散木莓结构/带正电荷Cd离子修饰介孔二氧化硅(SiO2)表面的制备
  19. 高中所学过的计算机知识,浅谈高中计算机学习重点论文
  20. Java中线程池拒绝策略——代码讲解

热门文章

  1. CSU:Corolado State University(科罗拉多州立大学)
  2. Java操作系统进程调度算法——先来先服务(FCFS)算法
  3. springboot实现阿里短信发送并查询状态
  4. MIL开发实践(1)——开发环境的设置
  5. C#比较两文件内容是否完全一样
  6. “程序媛”往往比“程序猿”更受认可,但前提是不能公开性别
  7. 动画(CSS3) animation
  8. mysql 插入递增_如何批量插入Mysql并取得各自的递增ID
  9. 夺命雷公狗---js_mv思路
  10. 在php中自定义一个类的关键字为( ),精读《未来简史》尔雅章节测验答案