这一篇博客延续的是上一篇博客。
上一篇讲述该设计的设计思路,这一篇讲述如何具体实施。
对于该设计的实施,可以大致分为两个part:(1)51单片机编程部分(2)手机导航APP部分
其中对于51单片机部分的编程不算很难,但是确实不是特别好写。这部分比较重要的也就是:(1)串口初始化配置程序(2)中断接收位置信息以及储存位置信息(3)解析位置信息【因为这个格式不是地图中可以直接使用的格式,需要进行坐标换算】
①51单片机接收并处理GPS位置信息的核心代码:
一,下面是main.c的代码。里面的一些变量就不展示声明了。有问题的话可以留言,会及时解答的。
#include "main.h"
#include "uart.h"
#include
#include
#include
#include
#define uchar unsigned char //无符号字符型 宏定义 变量范围0~255
#define uint unsigned int //无符号整型 宏定义 变量范围0~65535
//定义变量
//****************************************************
//主函数
//****************************************************
void main()
{
unsigned char i = 0;
Uart_Init();
Delay_ms(10);
clrStruct(); //清空缓存数组
while(1)
{
parseGpsBuffer();
printGpsBuffer();
}
}
int String_integer(char s[],int head,int end)
{
int i;
int num = 0;
for (i = head; s[i] >= '0' && s[i] <= '9'&&i<=end; i++)
{
num = 10 * num +(s[i] - '0');
}
return num;
}
void jingweidu_jiexi(char a[])
{
char str[20];
int flag=0,i,dian_num,num_a,jzheng,num_b;
double jxiaoshu,jingdu;
for(i=0; i
二,uart.c的代码。
#include "uart.h"
char idata gpsRxBuffer[gpsRxBufferLength];
unsigned char RX_Count = 0;
_SaveData Save_Data;
void Uart_Init()
{
SCON = 0X50; //UART方式1;8位UART
REN = 1; //允许串行口接收数据
PCON = 0x00; //SMOD=0;波特率不加倍
TMOD = 0x20; //T1方式2,用于产生波特率
TH1 = 0xFD; //装初值
TL1 = 0xFD;
TR1 = 1; //启动定时器1
EA = 1; //打开全局中断控制
ES = 1; //打开串行口中断
}
void UartPrintf(unsigned char *p) //发送字符串
{
ES=0;
while(*p)
{
SBUF=*(p++);
while(TI==0)
{
};
TI=0;
}
ES=1;
}
void UartPrintASCII(unsigned char c) //发送一个字符
{
ES=0;
TI=0;
SBUF=c;
while(TI==0);
TI=0;
ES=1;
}
void RECEIVE_DATA(void) interrupt 4 using 3
{
if(RI==1)
{
unsigned char temp = 0;
char i = 0;
//ES=0;
RI = 0;
temp = SBUF;
if(temp == '$')
{
RX_Count = 0;
}
if(RX_Count <= 5)
{
gpsRxBuffer[RX_Count++] = temp;
}
else if(gpsRxBuffer[0] == '$' &&gpsRxBuffer[4] == 'M' && gpsRxBuffer[5] == 'C') //确定是否收到"GPRMC/GNRMC"这一帧数据
{
gpsRxBuffer[RX_Count++] = temp;
if(temp == '\n')
{
memset(Save_Data.GPS_Buffer, 0, GPS_Buffer_Length); //清空
memcpy(Save_Data.GPS_Buffer, gpsRxBuffer, RX_Count); //保存数据
Save_Data.isGetData = true;
RX_Count = 0;
memset(gpsRxBuffer, 0, gpsRxBufferLength); //清空
}
if(RX_Count >= 75)
{
RX_Count = 75;
gpsRxBuffer[RX_Count] = '\0';//添加结束符
//RXbit=1;
}
}
}
//ES=1;
}
void clrStruct()
{
Save_Data.isGetData = false;
Save_Data.isParseData = false;
Save_Data.isUsefull = false;
memset(Save_Data.GPS_Buffer, 0, GPS_Buffer_Length); //清空
memset(Save_Data.UTCTime, 0, UTCTime_Length);
memset(Save_Data.latitude, 0, latitude_Length);
memset(Save_Data.N_S, 0, N_S_Length);
memset(Save_Data.longitude, 0, longitude_Length);
memset(Save_Data.E_W, 0, E_W_Length);
}
这两个.c文件是51单片机部分的所有代码(除了.h里面的变量以及函数的声明)。
②下面讲解手机APP程序部分。
大家可以自行下载E4A最新版。
链接:https://pan.baidu.com/s/1BRGgxj0HgcnK8FKM9DB6gQ 提取码:49rf
在此部分之前,对HC-05的配置要了解,一般只需要用到名字,配对码,其他几乎都默认即可,猪从模式选择从模式,波特率选择9600(这两个都是默认的,无须配置),那么如何配置呢,用串口调试助手,大家可以自行下载,网上有很多,配置注意:(1)发送配置命令要换行(2)使用USB-TTL模块对蓝牙模块进行配置,直接连接即可,txd和rxd交叉相连,很简单的。无须代码,有电就可以进行配置,后面就可以直接实现透传的功能啦。那么为什么不使用单片机进行配置呢?由于单片机里面会保存有上次烧录进去的代码而且无法清除,必然会影响蓝牙模块的配置。
配置以及查询主要命令有:
接着,要将手机设置里面的蓝牙打开,与刚刚配置好的蓝牙模块相配对(找到蓝牙模块的名字并且输入配对码,一般默认配对码为1234,这个1234的默认配对码仅仅对于HC-05来说,例如BT-05默认配对码为123456),配对码可以自行配置,不过不需要修改,以免忘记。手机蓝牙与蓝牙模块配对图所示:
接下来才可进行手机APP与蓝牙模块的通信模式。这就需要APP部分的程序了。
软件界面如图所示:
这部分是最简单的,因为这个软件上面会自带很多例程比如蓝牙例程以及地图导航,只需要修改一部分即可。不过需要注意的是,使用新版蓝牙这个蓝牙例程。其他的蓝牙例程并不适用(对于该设计来说)。
事件 主窗口.创建完毕()
高德地图1.显示比例尺(真)
高德地图1.显示缩放按钮(真)
高德地图1.显示指南针(真)
高德地图1.显示定位按钮(真)
高德导航1.初始化() '初始化高德导航,注意:高德导航必须与高德地图配合使用,否则无效。
结束 事件
事件 按钮1.被单击()
新版蓝牙1.开启蓝牙()
结束 事件
事件 按钮2.被单击()
新版蓝牙1.关闭蓝牙()
结束 事件
事件 按钮3.被单击()
高级列表框1.清空项目()
新版蓝牙1.搜索设备()
结束 事件
事件 按钮4.被单击()
新版蓝牙1.停止搜索()
结束 事件
事件 新版蓝牙1.发现设备(名称 为 文本型,地址 为 文本型,是否已配对 为 逻辑型)
如果 是否已配对 则
高级列表框1.添加项目("",名称 & "(已配对)",地址,"","")
否则
高级列表框1.添加项目("",名称,地址,"","")
结束 如果
结束 事件
事件 高级列表框1.表项被单击(项目索引 为 整数型)
变量 地址 为 文本型
地址=高级列表框1.取项目信息(项目索引)
弹出提示(地址)
新版蓝牙1.停止搜索()
新版蓝牙1.连接设备(地址)
结束 事件
事件 新版蓝牙1.连接成功()
弹出提示("连接成功")
主窗口.标题="Q蓝牙已经连接"
结束 事件
事件 新版蓝牙1.连接失败()
弹出提示("连接失败")
主窗口.标题="Q蓝牙未连接"
结束 事件
事件 新版蓝牙1.丢失连接()
弹出提示("丢失连接")
结束 事件
事件 按钮5.被单击()
新版蓝牙1.断开连接()
结束 事件
事件 新版蓝牙1.搜索完毕()
弹出提示("搜索完毕")
结束 事件
事件 按钮7.被单击()
如果 新版蓝牙1.是否已开启蓝牙() 则
弹出提示("已开启蓝牙")
否则
弹出提示("未开启蓝牙")
结束 如果
结束 事件
事件 按钮8.被单击()
变量 已配对设备 为 文本型(,)'已配对设备(n,0)=名称 已配对设备(n,1)=地址 n >= 0 < 取数组下标(已配对设备,1)
变量 i 为 整数型
高级列表框1.清空项目()
已配对设备=新版蓝牙1.取已配对设备()
i=0
判断循环首 i<取数组下标(已配对设备,1)
高级列表框1.添加项目("",已配对设备(i,0) & "(已配对)",已配对设备(i,1),"","")
i=i+1
判断循环尾
结束 事件
事件 新版蓝牙1.收到数据(数据 为 字节型())
变量 文本数据 为 文本型
文本数据 = 字节到文本(数据,"GBK")
编辑框4.加入文本(文本数据)
编辑框4.置光标位置(取文本长度(编辑框4.内容))
结束 事件
事件 按钮100.被单击()
高德地图1.坐标查询地址(32.968324,112.549652)
结束 事件
事件 高德地图1.坐标查询地址完毕(查询结果 为 逻辑型,地址 为 文本型)
如果 查询结果 = 真 则
编辑框1.内容=地址
否则
弹出提示("查询地址失败")
结束 如果
结束 事件
事件 按钮15.被单击()
高德地图1.开始搜索路线2(编辑框1.内容,编辑框2.内容,1,编辑框3.内容)
结束 事件
事件 高德地图1.搜索路线完毕(搜索结果 为 逻辑型,起点纬度 为 双精度小数型,起点经度 为 双精度小数型,终点纬度 为 双精度小数型,终点经度 为 双精度小数型)
如果 搜索结果 = 真 则
弹出提示("搜索路线成功,开始规划导航路线……")
'高德导航1.规划步行导航路线(起点纬度,起点经度,终点纬度,终点经度)
高德导航1.规划驾车导航路线(起点纬度,起点经度,终点纬度,终点经度)
否则
弹出提示("搜索路线失败")
结束 如果
结束 事件
事件 高德导航1.规划导航路线完毕(规划结果 为 逻辑型)
如果 规划结果 = 真 则
按钮17.可用 = 真
按钮18.可用 = 真
弹出提示("导航路线规划成功,可以开始导航")
否则
弹出提示("导航路线规划失败")
结束 如果
结束 事件
事件 按钮17.被单击()
'高德导航1.开始步行模拟导航()
高德导航1.开始驾车模拟导航()
结束 事件
事件 按钮18.被单击()
'高德导航1.开始步行实时导航()
高德导航1.开始驾车实时导航()
结束 事件
事件 主窗口.按下某键(键代码 为 整数型,传址 屏蔽 为 逻辑型)
如果 键代码 = 返回键 则
高德导航1.释放资源()
结束程序()
结束 如果
结束 事件
下面是APP蓝牙接收数据界面图。
下面的数字是经纬度,一共有两行。不断实时地接收位置信息。上面的代码中只用了取已配对设备,由于界面有限。不过功能是一样的。
下面是路线规划图:
点击开始搜索路线,会进行起点与终点的选择(与地图上面地点要一致)搜索界面如上图。点击开始驾车实时导航会进入导航界面,如下图:
说到这里基本已经结束了,下面附上我实验时候的总图,即实物图:
那么具体连线方式是什么呢?
对于GPS模块来说:
GPS模块 单片机
VCC 5V(单片机)
GND GND
TXD RXD(P3.0)
对于蓝牙模块来说:
蓝牙模块 单片机
VCC 5V(单片机)
GND GND
RXD TXD(P3.1)
一共六根线即可。
大家有什么问题可以留言,我可以及时作答,毕竟刚答辩结束。