基于Arduino的GPS数据解析程序

这篇博客讲了我利用arduino来解析和转发原始nema 0813数据的思想和实现方法。因为arduino比较简单,无法实现串口数据接收中断,所以都写在主循环里面了。不知道代码存在何种缺陷和漏洞,欢迎大家批评指正。

GPS软件要求

·         Ardiuno软件

·         监控串口1,接收数据。

·         数据格式:NEMA0813

·         解析出经纬度原始格式,xxxx.xxxxx, xxxx.xxxxx,保存,解析出短格式,2B 经度,2B 维度,保存

·         短格式:经纬度都是0.0ABCD格式小数最末4位,例如信号中经度是1234.56789,则得到67 和 89

·         经纬度都正常则LED亮。

·         串口2收到AddressWHR的时候:

·         经纬度按原始格式向串口2发送,以AddressFLT开头,跟着固定格式经纬度xxxx.xxxxx,xxxx.xxxxx,CRC结尾

·         经纬度按短格式向串口2发送:{ AddressLCT,2B 经度,2B 维度,1B CRC}

/***
 * The circuit:
 * RX is digital pin 10 (connect to TX of other device)
 * TX is digital pin 11 (connect to RX of other device)
***/
#include 

SoftwareSerial mySerial(10, 11);

char rmc_flag = 0;
char command_flag = 0;

char gps_data_nema[220] = {0};
char gps_data_rmc[72] = {0};
char gps_data_anal[20] = {'0','0','0','0','0','.','0','0','0','0',
                        '0','0','0','0','0','.','0','0','0','0'};//经纬度分
char gps_data_byte[4] = {0};

char *gprmc = "$GPRMC";
char *command = "Ad";
char command_code[2] = {0};

void memcpy(char *dest, char *src, int n)
{
  int i = 0;
  for(i = 0; i < n; i++)
  {
    *dest = *src;
    dest++;
    src++;
  }
}

int memcmp(char *s1, char *s2, int n)
{
  int i = 0;
  for(i = 0; i < n; i++)
  {
    if(*s1 != *s2)return 0;
    s1++;
    s2++;
  }
  return 1;
}

void setup() 
{
  Serial.begin(57600);
  mySerial.begin(4800);
}

void loop() {
  static char i = 0;
  static char j = 0;
  char k = 0;
  char l = 0;
  char comma[12] = {0}; //一共有12个逗号
  // put your main code here, to run repeatedly:
  if(Serial.available())
  {
    gps_data_nema[i] = Serial.read();
    Serial.print(gps_data_nema[i]);

	if(i == 0)
	{
	    if(gps_data_nema[i] != '$')
            Serial.println("Warning:the data input is wrong!");
	}

	if(gps_data_nema[i] == '$')
	{
		i = 0;
		gps_data_nema[i] = '$';
	}

	if(gps_data_nema[i] == 0x0A) //if the end of string
	{
	    if(memcmp(gps_data_nema, gprmc, 6))
	    {
	      memcpy(gps_data_rmc, gps_data_nema, i);
	      rmc_flag = 1;
	    };
	    i = 0;
	 }
	
    if(i > 210) //if the data is out range
      Serial.println("Warning:the data formation is false!");
	
    i++;
  }
  
  if(rmc_flag == 1)
  {
    l = 0;
    for(k = 0; k < 72; k++)
    {
    if(gps_data_rmc[k] == ',')
    {
      comma[l] = k;
      l ++;
    }
  }
  
  if((comma[3]-comma[2]) == 10)
  {
    k = comma[2] + 1;
    memcpy(&gps_data_anal[11], &gps_data_rmc[k], 9);
  }
    
  if((comma[5]-comma[4]) == 11)
  {
    l = comma[4] + 1;
    memcpy(&gps_data_anal[0], &gps_data_rmc[l], 10);
  }

    gps_data_byte[0] = gps_data_anal[8];
    gps_data_byte[1] = gps_data_anal[9];
    gps_data_byte[2] = gps_data_anal[18];
    gps_data_byte[3] = gps_data_anal[19];

    rmc_flag = 0;
  }

  if(mySerial.available()&&(command_flag == 0))
  {
    command_code[j] = mySerial.read();
    mySerial.print(command_code[j]);
    j = j + 1;
    if(j == 2)
    {
      mySerial.print("AddressWHR");
      command_flag = 1;
      j = 0;
    }
  }

  if(command_flag == 1)
  {
    if(memcmp(command, command_code, 2))
  	{
	    mySerial.print("AddressFLT");
	    for(k = 0; k < 20; k++)mySerial.print(gps_data_anal[k]);
	    mySerial.print("CRC");

	    mySerial.print("AddressLCT");
	    for(l = 0; l < 4; l++)mySerial.print(gps_data_byte[l]);
	    mySerial.print("CRC");
  	}
    command_flag = 0;
  }
}


SoftwareSerial mySerial(10, 11);

char rmc_flag = 0;
char command_flag = 0;

char gps_data_nema[220] = {0};
char gps_data_rmc[72] = {0};
char gps_data_anal[20] = {'0','0','0','0','0','.','0','0','0','0',
                        '0','0','0','0','0','.','0','0','0','0'};//经纬度分
char gps_data_byte[4] = {0};

char *gprmc = "$GPRMC";
char *command = "Ad";
char command_code[2] = {0};

void memcpy(char *dest, char *src, int n)
{
  int i = 0;
  for(i = 0; i < n; i++)
  {
    *dest = *src;
    dest++;
    src++;
  }
}

int memcmp(char *s1, char *s2, int n)
{
  int i = 0;
  for(i = 0; i < n; i++)
  {
    if(*s1 != *s2)return 0;
    s1++;
    s2++;
  }
  return 1;
}

void setup() 
{
  Serial.begin(57600);
  mySerial.begin(4800);
}

void loop() {
  static char i = 0;
  static char j = 0;
  char k = 0;
  char l = 0;
  char comma[12] = {0}; //一共有12个逗号
  // put your main code here, to run repeatedly:
  if(Serial.available())
  {
    gps_data_nema[i] = Serial.read();
    Serial.print(gps_data_nema[i]);

	if(i == 0)
	{
	    if(gps_data_nema[i] != '$')
            Serial.println("Warning:the data input is wrong!");
	}

	if(gps_data_nema[i] == '$')
	{
		i = 0;
		gps_data_nema[i] = '$';
	}

	if(gps_data_nema[i] == 0x0A) //if the end of string
	{
	    if(memcmp(gps_data_nema, gprmc, 6))
	    {
	      memcpy(gps_data_rmc, gps_data_nema, i);
	      rmc_flag = 1;
	    };
	    i = 0;
	 }
	
    if(i > 210) //if the data is out range
      Serial.println("Warning:the data formation is false!");
	
    i++;
  }
  
  if(rmc_flag == 1)
  {
    l = 0;
    for(k = 0; k < 72; k++)
    {
    if(gps_data_rmc[k] == ',')
    {
      comma[l] = k;
      l ++;
    }
  }
  
  if((comma[3]-comma[2]) == 10)
  {
    k = comma[2] + 1;
    memcpy(&gps_data_anal[11], &gps_data_rmc[k], 9);
  }
    
  if((comma[5]-comma[4]) == 11)
  {
    l = comma[4] + 1;
    memcpy(&gps_data_anal[0], &gps_data_rmc[l], 10);
  }

    gps_data_byte[0] = gps_data_anal[8];
    gps_data_byte[1] = gps_data_anal[9];
    gps_data_byte[2] = gps_data_anal[18];
    gps_data_byte[3] = gps_data_anal[19];

    rmc_flag = 0;
  }

  if(mySerial.available()&&(command_flag == 0))
  {
    command_code[j] = mySerial.read();
    mySerial.print(command_code[j]);
    j = j + 1;
    if(j == 2)
    {
      mySerial.print("AddressWHR");
      command_flag = 1;
      j = 0;
    }
  }

  if(command_flag == 1)
  {
    if(memcmp(command, command_code, 2))
  	{
	    mySerial.print("AddressFLT");
	    for(k = 0; k < 20; k++)mySerial.print(gps_data_anal[k]);
	    mySerial.print("CRC");

	    mySerial.print("AddressLCT");
	    for(l = 0; l < 4; l++)mySerial.print(gps_data_byte[l]);
	    mySerial.print("CRC");
  	}
    command_flag = 0;
  }
}

  • 6
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: Arduino串口数据解析Arduino与外部设备进行数据交互的一个重要环节。通常,我们需要通过串口将外部设备传来的数据读取,解析后再通过串口将处理后的数据发送回外部设备。以下是一些关键的步骤: 首先,设置串口的通信参数,包括波特率、数据位、停止位等。然后,通过Serial.read()函数读取串口缓存区中的数据,一般应先检查缓存区是否有数据可读,以避免出现无效数据的问题。 接着,需要对读取到的数据进行解析。这个过程的难度取决于外部设备发送的数据格式。比如,如果传来的是ASCII字符,则可以通过ASCII码值进行判断解析;如果是二进制数据,则需要将收到的数据按位进行分析。 最后,还需要对数据进行处理,例如将解析的数值转换为合适的单位,再将处理后的数据通过Serial.write()函数发送回外部设备。 值得注意的是,Arduino串口通信时,要保证发送端与接收端的数据格式和流程相匹配,否则容易造成通信失败。因此,在实际应用时,我们需要对于数据格式进行详细的协商和定义。 ### 回答2: Arduino串口数据解析是将从串口读到的数据进行拆分和转换,使得人们能够比较方便地读取到其中的信息。一般情况下,串口通信是从外设或其他设备获取数据,并将这些数据通过串口发送到Arduino板上,Arduino则需要进行数据解析,以方便获取其中的有效信息。 数据解析可以通过将接收到的数据进行分割和筛选。一般来讲,在传输数据时,需要预先规定好数据格式,这样Arduino便可以通过读取数据的格式和顺序来获取其中的信息。以常见的串口通信协议为例,如RS232协议或者通过USB连接的Virtual Com Port,Arduino可以通过读取串口数据的起始位、终止位、校验位等信息,来保证数据的正确性以及完整性。 另外,Arduino还可以将数据进行转换处理,以方便后续处理和显示。例如将读入的数据转换成ASCII字符串、16进制字符串或者其他特定格式,以便于数据处理和显示。例如在小车控制系统中,可以将通过串口读入的指令进行解析和转换,从而实现小车的控制。 总的来说,Arduino串口数据解析是将读入的数据进行合理的拆分、筛选和转换处理,以方便后续的数据处理和显示。这是Arduino与其他外设进行通讯和交互的重要环节。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AllenSun-1990

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值