最近学了很多,也是时候自己做点东西来复习并且巩固下之前的知识了。学以致用最重要。最近写了个小软件,用来处理处理从窗口发送过来的GPS信息。GPS是与STM32相连接任何STM32把GPS信息发到电脑的串口上。任何我写了个C#的程序通过串口接收到信息,并对信息进行处理得到我们需要的经纬度,并通过经纬度查找到具体的地址。可以表达的不太清晰,想来几张图来个大家看看具体的效果。任何在讲讲具体的程序。
这是通过别的串口接收软件接收到的串口上的信息。
这是初始化状态下的软件界面

这是按了按钮之后的。由于经纬度查地址需要时间,所以地址不能马上的显示出来。

现在地址查询结束了。
然后我来介绍下程序。
首先需要先写程序来接收串口发过来的数据。
SerialPort sp = new SerialPort();首先我们可以实例化一个串口对象。
sp.PortName = "COM8"; //端口
sp.BaudRate = 38400; //波特率
sp.Open(); //打开串口
配置完端口和波特率后就可以打开串口来接收数据了
string message = sp.ReadLine();
message = message.Substring(0, message.Length - sp.NewLine.Length);
用这两句可以获得串口传来的数据并且保持在message字符串中。
我们刚才已经看过了传过来的字符串是什么格式的。它采用的是NMEA0183 协议,如果想具体了解它的协议可以去百度下,这里就不再赘述了。
由于我们只是需要经纬度,所以只需要对$GPGGA的数据进行处理。
经过观察我们可以使用,做为分割符来使用Split方法进行分割字符串
然后转换成我们需要的信息。
这里附上程序:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
SerialPort sp = new SerialPort();
//private void button1_Click(object sender, EventArgs e)
//{
// //sp.Close();
// sp.PortName = "COM8";
// sp.BaudRate = 38400;
// sp.Open();
//}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
sp.PortName = "COM8"; //端口
sp.BaudRate = 38400; //波特率
sp.Open(); //打开串口
bool stop = false; //标志位
string longitude = "0";//经度
string latitude = "0";//纬度
while (!stop)
{
try
{
string message = sp.ReadLine();
message = message.Substring(0, message.Length - sp.NewLine.Length);
if (message.StartsWith("$GPGGA"))
{
//模拟定位
//message = "$GPGGA,012440.00,2232.458380,N,11356.91024,E,1,05,2.7,40.2,M,0.5,M,,*6F";
//message = "$GPGGA,012440.00,2232.301654,N,11402.058366,E,1,05,2.7,40.2,M,0.5,M,,*6F";
char[] separator = { ',' };
string[] data = message.Split(separator);
if (data[6].Equals("1"))
{
string s;
s = data[2];
int idx = s.IndexOf(".");
string d1 = s.Substring(0, idx - 2);
string d2 = s.Substring(idx - 2);
double degree = Double.Parse(d1) + Double.Parse(d2) / 60;
latitude = Convert.ToString(Convert.ToDouble(s) / 100);//纬度
string j;
j = data[4];
int idxj = j.IndexOf(".");
string d1j = j.Substring(0, idxj - 2);
string d2j = j.Substring(idxj - 2);
double degreej = Double.Parse(d1j) + Double.Parse(d2j) / 60;
longitude = Convert.ToString(Convert.ToDouble(j)/100);//经度
textBox1.Text = longitude;
textBox2.Text = latitude;
stop = true;
}
else
{
sp.Close();
sp.PortName = "COM8";
sp.BaudRate = 38400;
sp.Open();
// button2_Click(button2,EventArgs e);
}
}
else if (message.StartsWith("$GPGGA"))
{
char[] separator = { ',' };
string[] data = message.Split(separator);
}
}
catch (TimeoutException) { }
}
sp.Close();
// sp = null;
//textBox4.Text = adrss();2
MessageBox.Show("GPS已停止,请等待地址信息的查询!");
textBox4.Text = GPSadrss.adrss(latitude, longitude);
}
在获得了经纬度之后我们需要用经纬度来查询地址。我在这里定义了一个GPSadrss的类,并且在里面定义了一个static类型的adrss方法。这样我们不需要实例化GPSadrss对象也可以调用adrss方法了。
adrss里我们使用来谷歌的接口来查询地址。
class GPSadrss
{
public static string adrss(string latitude, string longitude)
{
WebClient client = new WebClient();//webclient客户端对象
//string url = "http://maps.google.com/maps/api/geocode/xml?latlng=29.82121,121.55973&language=zh-CN&sensor=false";//请求地址
string url = "http://maps.google.com/maps/api/geocode/xml?latlng="+latitude+","+longitude
+"&language=zh-CN&sensor=false";//请求地址
client.Encoding = Encoding.UTF8;//编码格式
string responseTest = client.DownloadString(url);//下载xml响应数据
XmlDocument doc = new XmlDocument();//创建XML文档对象
if (!string.IsNullOrEmpty(responseTest))
{
doc.LoadXml(responseTest);//加载xml字符串
//获取状态信息
string xpath = @"GeocodeResponse/status";
XmlNode node = doc.SelectSingleNode(xpath);
string status = node.InnerText.ToString();
if (status == "OK")
{
//获取地址信息
xpath = @"GeocodeResponse/result/formatted_address";
node = doc.SelectSingleNode(xpath);
string address = node.InnerText.ToString();
string[]ad= address.Split();
return ad[0];
}
return "false";
}
return "false";
}
这是GPSadrss里面的代码。这里用了webclient客户端对象来访问谷歌的端口。
然后说下界面的设计,由于经纬度和地址,我们都希望不能由用户直接输入使用我们需要把3个文本框的ReadOnly属性设计为ture;

由于我们也不希望用户任意的拉伸窗口所以我把边框样式设置成了Fixed


并且把窗口的最大化按钮去掉了
现在的程序还很粗糙,离我的目标还有些差距。比如这个版本的程序在点击了按钮只后等待查询地址的时候程序假死在那里了,直到查到了地址我们才能继续控制它,这里我觉得是因为在查地址的时候程序一直在等待网页上传来的数据。所以程序假死。下个版本的目标是用线程来查询地址,就可以解决这个问题了。