新人求帮助:刚学嵌入式开发,不太会编程序,求助

baidu_38555429 2017-04-27 06:02:09
现在我需要把串口2接收到的GPS模块定位数据用单片机处理(提取出GPMRC中的经纬度信息)之后,通过串口1发送到电脑上,在串口调试助手上显示出坐标,单片机用的STM32F103RC,用的IAR编译。自己在编程序的时候感觉有很多地方搞不清楚,编译的时候这里错那里错的,有没有哪位大神给我发个源码,或者工程文件,我先把它看懂了再说。
...全文
1099 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
zgl7903 2017-07-24
  • 打赏
  • 举报
回复
1 把MCU的串口部分代码调试好, 与PC机能正常通信 2 把从GPS模块收到的原始发送到串口, 确定从与GPS模块接收到数据是正确的 3 解析GPS数据
qq_31992299 2017-07-24
  • 打赏
  • 举报
回复
同新手,求教~
u010289931 2017-07-20
  • 打赏
  • 举报
回复

typedef struct {
	char utc_time[15];
	unsigned char status;
	char latitude[15];
	unsigned char north_or_south;
	char longitude[15];
	unsigned char east_or_west;
	char speed[15];
	char cursor[15];
	char date[15];
}RMC_DATA;


/*
  $GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>*hh
  <1>UTC时间(世界时间),hhmmss(时分秒)格式 
  <2>定位状态,A=有效定位,V=无效定位 
  <3>纬度ddmm.mmmm(度分)格式(前面的0也将被传输)
  <4>纬度半球N(北半球)或S(南半球) 
  <5>经度dddmm.mmmm(度分)格式(前面的0也将被传输)
  <6>经度半球E(东经)或W(西经) 
  <7>地面速率(000.0~999.9节,前面的0也将被传输) 
  <8>地面航向(000.0~359.9度,以正北为参考基准,前面的0也将被传输)
  <9>UTC日期,ddmmyy(日月年)格式 
  <10>磁偏角(000.0~180.0度,前面的0也将被传输)
  <11>磁偏角方向,E(东)或W(西) 
  <12>模式指示(仅NMEA01833.00版本输出,A=自主定位,D=差分,E=估算,N=数据无效)
*/

void RMC_process(unsigned char* rmcData)
{
	unsigned char i = 0;
	unsigned char rmc_len = 0;
	RMC_DATA sRMC;

	unsigned char param_num = 0;
	unsigned char param_index = 0;

	memset(sRMC, 0, sizeof(RMC_DATA));
	rmc_len = strlen(rmcData);

	// 解析RMC
	for (i=0; i<rmc_len; i++)
	{
		if (rmcData[i] == ',')
		{
			param_num++;
			param_index = 0;
			continue;
		}

		switch (param_num) {
		case 1:
			sRMC.utc_time[param_index++] = rmcData[i];
			break;
		case 2:
			sRMC.status = rmcData[i];
			break;
		case 3:
			sRMC.latitude[param_index++] = rmcData[i];
			break;
		case 4:
			sRMC.north_or_south = rmcData[i];
			break;
		case 5:
			sRMC.longitude[param_index++] = rmcData[i];
			break;
		case 6:
			sRMC.east_or_west = rmcData[i];
			break;
		case 7:
			sRMC.speed[param_index++] = rmcData[i];
			break;
		case 8:
			sRMC.cursor[param_index++] = rmcData[i];
			break;
		case 9:
			sRMC.date[param_index++] = rmcData[i];
			break;
		default:
			break;
		}
	}

	//
}
------ ------ ------ ------ ------ ------ ------ 看了下你代码,有打人的冲动!
baidu_38555429 2017-05-04
  • 打赏
  • 举报
回复
引用 3 楼 91program 的回复:
gps 的原始 nmea 信息也不应该是这样的,你串口得到的数据是别人处理过、然后输出的。 两个错误原因的可能: 1) NMEA 信息错误,也就是说接收到的 GPS 信息是错误的,这个需要硬件来分析 GPS 模块、或者换模块试一下 2) 别人处理过、然后输出的代码有问题,没有获取到正确的信息
模块没问题,数据的确是处理过的,要不我把代码放上来您帮忙看一下行吗?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bsp_gps.h"
#include "usart2.h"



void Analyze0183(uint8_t *_ucaBuf, uint16_t _usLen);
int32_t StrToInt(char *_pStr);
int32_t StrToIntFix(char *_pStr, uint8_t _ucLen);
void HexToAscii(uint8_t *_ucpHex, uint8_t *_ucpAscII, uint8_t _ucLenasc);
BOOL Uart2RxBuf_full =FALSE;
unsigned char Uart2RxBuf[UART2_RX_BUF_SIZE]; 

unsigned char Uart1RxBuf[UART1_RX_BUF_SIZE];                /* com1_rf接收缓冲区 */
GPS myGPS;

char GpsBuf[GPS_BUFF_SIZE];  //该数据解析之后才更新显示GPS信息

/*
*	函 数 名: bsp_InitGPS
*	功能说明: 配置GPS串口
*	形    参:  无
*	返 回 值: 无
*/
void bsp_InitGPS(void)
{
	/*
        GPS 模块使用 UART 串口发送定位数据至 STM32, 每秒钟发送一组数据
        因此,只需要配置串口即可。 bsp_uart_fifo.c 中已经配置好串口,此处不必再配置
	*/
	myGPS.PositionOk = 0;  /* 数据设置为无效 */
	myGPS.TimeOk = 0;  /* 数据设置为无效 */
	
	myGPS.UartOk = 0;	/* 串口通信正常的标志, 如果以后收到了校验合格的命令串则设置为1 */
}
/*
*	函 数 名: gps_pro
*	功能说明:  从串口缓冲区中解析出GPS数据包。插入到主程序中执行即可。分析结果存放在全局变量 myGPS
*	形    参:  无
*	返 回 值: 无
*/

void gps_pro(void)
{
    uint16_t i=0;
	
    char *p,*pt;  

		if (Uart2RxBuf_full)
		   {  

	            USART_ITConfig(USART2, USART_IT_RXNE, DISABLE); //禁止接收中断
	            
	            Uart2RxBuf_full = FALSE;

	            p = (char *)Uart2RxBuf;
	            pt = strchr(p, '$'); //P指向了该位置,在字符串中查找字符$第一次出现的位置
	            for(i=0;i<GPS_BUFF_SIZE;i++)
	            {
	              GpsBuf[i] = Uart2RxBuf[pt-p+i];  //以$开头的字符串					
	            }	 
                 
                printf("%s\r\n",GpsBuf);/* 将收到的GPS模块数据按原样 打印到COM1口,便于跟踪调试 */
                  
	            USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); //使能接收中断		
            
				 
	             }
	
}

void GPS_Data_update()
{
   
    char * start_p = GpsBuf;      

    char *pos_p;
 if(strncmp(GpsBuf, "$GPRMC",6)==0)  
  {
	/*字段1 :UTC 时间,hhmmss.ss,时分秒格式 */
	pos_p = strchr(start_p, ','); //查找字符串s中首次出现字符c的位置,剥离c前面的信息
	if (pos_p == 0)
	{
	    return;//2个逗号连在一起的情况
	}
        pos_p++;  // p+1后指向UTC时间
        myGPS.Hour = StrToIntFix(pos_p, 2);
	pos_p += 2;
	myGPS.Min = StrToIntFix(pos_p, 2);
	pos_p += 2;
	myGPS.Sec = StrToIntFix(pos_p, 2);
        pos_p+= 3;
	myGPS.mSec = StrToIntFix(pos_p, 2);
     
	 //微秒忽略
      /* 字段2 :  gps状态,A=有效;V=无效*/
        pos_p= strchr(pos_p, ',');
	if (pos_p== 0)
	{
		return;
	}
	pos_p++;
	if (*pos_p != 'A')
	{
		/* 未定位则直接返回 */
		myGPS.PositionOk = 0;
		return;
	}
	myGPS.PositionOk = 1;
	pos_p+= 1;

     /* 字段3 :纬度ddmm.mmmmm,度分格式*/
        pos_p = strchr(pos_p, ','); //接着刚才指针位置找下一个逗号
	if (pos_p == 0)
	{
	   return; 
	}
	pos_p++;
        myGPS.WeiDu_Du = StrToIntFix(pos_p, 2);
	pos_p += 2;
	myGPS.WeiDu_Fen = StrToIntFix(pos_p, 2) * 10000;
	pos_p += 3;
	myGPS.WeiDu_Fen += StrToIntFix(pos_p, 5);
        pos_p += 5;
             
        /* 字段4 :N(北纬)或S(南纬) */
	pos_p = strchr(pos_p, ',');
	if (pos_p == 0)
	{
		return;
	}
	pos_p++;
	if (*pos_p == 'S')
	{
		myGPS.NS = 'S';
	}
	else if (*pos_p == 'N')
	{
		myGPS.NS = 'N';
	}
	else
	{
		return;
	}
        pos_p+= 1;
    /* 字段5:经度dddmm.mmmmm,度分格式 */
	pos_p = strchr(pos_p, ',');
	if (pos_p == 0)
	{
		return;
	}
	pos_p++;
	myGPS.JingDu_Du = StrToIntFix(pos_p, 3);
	pos_p += 3;
	myGPS.JingDu_Fen = StrToIntFix(pos_p, 2) * 10000;
	pos_p += 3;
	myGPS.JingDu_Fen += StrToIntFix(pos_p, 5);
        pos_p += 5;
	
        /* 字段6 :E(东经)或W(西经) */
	pos_p = strchr(pos_p, ',');
	if (pos_p == 0)
	{
		return;
	}
	pos_p++;
	if (*pos_p == 'E')
	{
		myGPS.EW = 'E';
	}
	else if (*pos_p == 'W')
	{
		myGPS.EW = 'W';
	}
        else
	{
		return;
	}
     
    
  }
  
  
}
/*
*	函 数 名: CRC_Check
*	功能说明: 检查0183数据包的校验和是否正确:$与*之间的所有字符的异或运算
*	形    参:  _ucaBuf  收到的数据
*		  _usLen    数据长度
*	返 回 值: TRUE 或 FALSE.
*/
CRCStatus CRC_Check(uint8_t *_ucaBuf, uint16_t _usLen)
{
	uint8_t ucXorSum;
	uint8_t ucaBuf[2];
	uint16_t i;

	if (_usLen < 3)
	{
		return CRC_ERROR;
	}

	/* 如果没有校验字节,也认为出错 */
	if (_ucaBuf[_usLen - 3] != '*')
	{
		return CRC_ERROR;
	}

	/* 不允许出现非ASCII字符 */
	for (i = 0; i < _usLen - 3; i++)
	{
		if ((_ucaBuf[i] & 0x80) || (_ucaBuf[i] == 0))
		{
			return CRC_ERROR;
		}
	}

	ucXorSum = _ucaBuf[0];
	for (i = 1; i < _usLen - 3; i++)
	{
		ucXorSum = ucXorSum ^ _ucaBuf[i];
	}

	HexToAscii(&ucXorSum, ucaBuf, 2);

	if (memcmp(&_ucaBuf[_usLen - 2], ucaBuf, 2) == 0)
	{
		return CRC_OK;
	}

	return CRC_ERROR;
}
/*
*	函 数 名: gpsGPRMC
*	功能说明: 分析0183数据包中的 GPGSV 命令,结果存放到全局变量
*	形    参:  _ucaBuf  收到的数据
*			 _usLen    数据长度
*	返 回 值: 无
*/

void gpsGPRMC(uint8_t *_ucaBuf, uint16_t _usLen)
{
	char *p;
	p = (char *)_ucaBuf;
	p[_usLen] = 0;
	/* 字段1 UTC时间,hhmmss.sss格式 */
	p = strchr(p, ',');
	if (p == 0)
	{
		return;
	}
	p++;
	myGPS.Hour = StrToIntFix(p, 2);
	p += 2;
	myGPS.Min = StrToIntFix(p, 2);
	p += 2;
	myGPS.Sec = StrToIntFix(p, 2);
	p += 3;
	myGPS.mSec = StrToIntFix(p, 2);
        p += 2;
	/* 字段2 状态,A=定位,V=未定位 */
	p = strchr(p, ',');
	if (p == 0)
	{
		return;
	}
	p++;
	if (*p != 'A')
	{
		/* 未定位则直接返回 */
		myGPS.PositionOk = 0;
		return;
	}
	myGPS.PositionOk = 1;
	p += 1;
	/* 字段3 纬度ddmm.mmmm,度分格式 */
	p = strchr(p, ',');
	if (p == 0)
	{
		return;
	}
	p++;
	myGPS.WeiDu_Du = StrToIntFix(p, 2);
	p += 2;
	myGPS.WeiDu_Fen = StrToIntFix(p, 2) * 10000;
	p += 3;
	myGPS.WeiDu_Fen += StrToIntFix(p, 5);
	p += 5;

	/* 字段4 纬度N(北纬)或S(南纬)*/
	p = strchr(p, ',');
	if (p == 0)
	{
		return;
	}
	p++;
	if (*p == 'S')
	{
		myGPS.NS = 'S';
	}
	else if (*p == 'N')
	{
		myGPS.NS = 'N';
	}
	else
	{
		return;
	}
        p += 1;
	/* 字段5 经度dddmm.mmmm,度分格式 */
	p = strchr(p, ',');
	if (p == 0)
	{
		return;
	}
	p++;
	myGPS.JingDu_Du = StrToIntFix(p, 3);
	p += 3;
	myGPS.JingDu_Fen = StrToIntFix(p, 2) * 10000;
	p += 3;
	myGPS.JingDu_Fen += StrToIntFix(p, 5);
	p += 5;

	/* 字段6:经度E(东经)或W(西经) */
	p = strchr(p, ',');
	if (p == 0)
	{
		return;
	}
	p++;
	if (*p == 'E')
	{
		myGPS.EW = 'E';
	}
	else if (*p == 'W')
	{
		myGPS.EW = 'W';
	}
        else
	{
		return;
	}
       
}
/*
*	函 数 名: Analyze0183
*	功能说明: 分析0183数据包
*	形    参:  _ucaBuf  收到的数据
*			 _usLen    数据长度
*	返 回 值: 无
*/
void Analyze0183(uint8_t *_ucaBuf, uint16_t _usLen)
{
	if (CRC_Check(_ucaBuf, _usLen) != CRC_OK)
	{
		return;
	}
	if (memcmp(_ucaBuf, "GPGGA,", 6) == 0)
	{
		gpsGPGGA(_ucaBuf, _usLen);
	}
	else if (memcmp(_ucaBuf, "GPGSA,", 6) == 0)
	{
		gpsGPGSA(_ucaBuf, _usLen);
	}
	else if (memcmp(_ucaBuf, "GPGSV,", 6) == 0)
	{
		gpsGPGSV(_ucaBuf, _usLen);
	}
	else if (memcmp(_ucaBuf, "GPRMC,", 6) == 0)
	{
		gpsGPRMC(_ucaBuf, _usLen);
	}
	else if (memcmp(_ucaBuf, "GPVTG,", 6) == 0)
	{
		gpsGPVTG(_ucaBuf, _usLen);
	}
	else if (memcmp(_ucaBuf, "GPGLL,", 6) == 0)
	{
		gpsGPGLL(_ucaBuf, _usLen);
	}
}
/*
*	函 数 名: StrToInt
*	功能说明: 将ASCII码字符串转换成十进制
*	形    参: _pStr :待转换的ASCII码串. 可以以逗号或0结束
*	返 回 值: 二进制整数值
*/
int32_t StrToInt(char *_pStr)
{
	uint8_t flag;
	char *p;
	uint32_t ulInt;
	uint8_t i;
	uint8_t ucTemp;

	p = _pStr;
	if (*p == '-')
	{
		flag = 1;	/* 负数 */
		p++;
	}
	else
	{
		flag = 0;
	}

	ulInt = 0;
	for (i = 0; i < 15; i++)
	{
		ucTemp = *p;
		if (ucTemp == '.')	/* 遇到小数点,自动跳过1个字节 */
		{
			p++;
			ucTemp = *p;
		}
		if ((ucTemp >= '0') && (ucTemp <= '9'))
		{
			ulInt = ulInt * 10 + (ucTemp - '0');
			p++;
		}
		else
		{
			break;
		}
	}

	if (flag == 1)
	{
		return -ulInt;
	}
	return ulInt;
}
/*
*	函 数 名: StrToIntFix
*	功能说明: 将ASCII码字符串转换成十进制, 给定长度
*	形    参: _pStr :待转换的ASCII码串. 可以以逗号或0结束
*			 _ucLen : 固定长度
*	返 回 值: 二进制整数值
*/
int32_t StrToIntFix(char *_pStr, uint8_t _ucLen)
{
	uint8_t flag;
	char *p;
	uint32_t ulInt;
	uint8_t i;
	uint8_t ucTemp;
	p = _pStr;
	if (*p == '-')
	{
		flag = 1;	/* 负数 */
		p++;
		_ucLen--;
	}
	else
	{
		flag = 0;
	}
	ulInt = 0;
	for (i = 0; i < _ucLen; i++)
	{
		ucTemp = *p;
		if (ucTemp == '.')	/* 遇到小数点,自动跳过1个字节 */
		{
			p++;
			ucTemp = *p;
		}
		if ((ucTemp >= '0') && (ucTemp <= '9'))
		{
			ulInt = ulInt * 10 + (ucTemp - '0');
			p++;
		}
		else
		{
			break;
		}
	}

	if (flag == 1)
	{
		return -ulInt;
	}
	return ulInt;
}
/*
*	函 数 名: gps_FenToDu
*	功能说明: 将分转换为度的小数部分,保留6位小数。 将分换算为度。
*	形    参: 无
*	返 回 值: 返回度的小数部分(十进制)
*/
uint32_t gps_FenToDu(uint32_t _fen)
{
	uint32_t du;
	
	/* myGPS.WeiDu_Fen;	纬度,分. 232475;  小数点后4位  表示 23.2475分 */
	
	du = (_fen * 100) / 60;
	
	return du;
}
/*
*	函 数 名: gps_FenToMiao
*	功能说明: 将分的小数部分转化秒
*	形    参: 无
*	返 回 值: 秒 整数部分
*/
uint16_t gps_FenToMiao(uint32_t _fen)
{
	uint32_t miao;
	miao = ((_fen % 10000) * 60);
	
	if ((miao % 10000) >= 5000)
	{
		miao = miao / 10000 + 1;
	}
	else
	{
		miao = miao / 10000;
	}
		
	return miao;
}


/*
*	函 数 名: DispGPSStatus
*	功能说明: 打印GPS数据包解码结果
*	形    参:无
*	返 回 值: 无
*/
void DispGPSStatus(void)
{
        char buf[128];
        if (myGPS.NS == 'S')
        {
                sprintf(buf, "南纬 %02d.%07d°", myGPS.WeiDu_Du, gps_FenToDu(myGPS.WeiDu_Fen));
        }
        else 
        {
                sprintf(buf, "北纬 %02d.%07d°",myGPS.WeiDu_Du, gps_FenToDu(myGPS.WeiDu_Fen));
        }
        printf(buf);
        if (myGPS.EW == 'W')
        {
                sprintf(buf, "西经 %03d.%07d°", myGPS.JingDu_Du, gps_FenToDu(myGPS.JingDu_Fen));
        }
        else 
        {
                sprintf(buf, "东经 %03d.%07d°", myGPS.JingDu_Du, gps_FenToDu(myGPS.JingDu_Fen));
        }
        printf(buf);

        printf("\n"); 
}

void * my_memccpy(void *dest,const void *src,int c,int count)  
{  
      while ( count && (*((char *)(dest = (char *)dest + 1) - 1) = 
   *((char *)(src = (char *)src + 1) - 1)) != (char)c )  
      count--;  
   return(count ? dest : NULL);  
}  
91program 2017-05-02
  • 打赏
  • 举报
回复
gps 的原始 nmea 信息也不应该是这样的,你串口得到的数据是别人处理过、然后输出的。 两个错误原因的可能: 1) NMEA 信息错误,也就是说接收到的 GPS 信息是错误的,这个需要硬件来分析 GPS 模块、或者换模块试一下 2) 别人处理过、然后输出的代码有问题,没有获取到正确的信息
baidu_38555429 2017-05-01
  • 打赏
  • 举报
回复
引用 1 楼 91program 的回复:
发源码?LZ 你的企望值过高了!来这里问具体的问题来差不多。

好吧,那我说下我出现的问题,您能帮忙看一下吗
就是我现在只想要经度和纬度,但是出来的数据都是0,而且是西经
91program 2017-04-28
  • 打赏
  • 举报
回复
发源码?LZ 你的企望值过高了!来这里问具体的问题来差不多。

19,502

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 嵌入开发(WinCE)
社区管理员
  • 嵌入开发(WinCE)社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧