[应用相关] stm32与GPS模块的数据传输,最后把数据传回到电脑

[复制链接]
2277|35
 楼主| 我爱台妹mmd 发表于 2022-2-10 16:10 | 显示全部楼层 |阅读模式
ST, gp, ps
准备工作
  • stm32f103zet6开发板一块
  • gps模块一个(型号为G28Z2FTTL)
  • 串口调试助手
  • 杜邦线若干

 楼主| 我爱台妹mmd 发表于 2022-2-10 16:37 | 显示全部楼层
GPS(G28Z2FTTL)模块介绍
模组采用中科微AT6558R定位芯片,是一-款能够以99通道接收卫星信号低功耗;高灵敏度高的G-MOUSE能够在城市、峡谷、高架下面等弱信号的地方,以及汽车内部任何位置可以快速、准确的进行定位。使得模块可广泛用于车载监控、公交车报站、车载导航、船载导航、笔记本导航等产品上。
 楼主| 我爱台妹mmd 发表于 2022-2-10 16:40 | 显示全部楼层
 楼主| 我爱台妹mmd 发表于 2022-2-10 16:56 | 显示全部楼层
 楼主| 我爱台妹mmd 发表于 2022-2-10 17:08 | 显示全部楼层
从上图可以从看出,GPS模块是通过串口传输数据的,因此与stm32f103zet6的接法如下
52556204d60dccb93.png

评论

这里GPS和stm32之间是通过USART2来传输的。  发表于 2022-2-10 17:17
 楼主| 我爱台妹mmd 发表于 2022-2-10 17:19 | 显示全部楼层
GPS数据类型及格式
GPS常见类型
285076204d882711f0.png
 楼主| 我爱台妹mmd 发表于 2022-2-10 17:23 | 显示全部楼层
数据格式
  1. $GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>*hh
  2.   <1> UTC 时间,hhmmss(时分秒)格式
  3.   <2> 定位状态,A=有效定位,V=无效定位
  4.   <3>纬度ddmm.mmmm(度分)格式(前面的0也将被传输)
  5.   <4> 纬度半球N(北半球)或S(南半球)
  6.   <5>经度dddmm.mmmm(度分)格式(前面的0也将被传输)
  7.   <6> 经度半球E(东经)或W(西经)
  8.   <7>地面速率(000.0~999.9节,前面的0也将被传输)
  9.   <8>地面航向(000.0~359.9度,以真北为参考基准,前面的0也将被传输)
  10.   <9> UTC 日期,ddmmyy(日月年)格式
  11.   <10>磁偏角(000.0~180.0度,前面的0也将被传输)
  12.   <11> 磁偏角方向,E(东)或W(西)
  13.   <12>模式指示(仅NMEA01833.00版本输出,A=自主定位,D=差分,E=估算,N=数据无效)
 楼主| 我爱台妹mmd 发表于 2022-2-10 17:24 | 显示全部楼层
  1. $GPGGA,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,M,<10>,M,<11>,<12>*xx<CR><LF>
  2.   <1> UTC 时间,格式为hhmmss.sss;
  3.   <2> 纬度,格式为ddmm.mmmm(第一位是零也将传送);
  4.   <3> 纬度半球,N 或S(北纬或南纬)
  5.   <4> 经度,格式为dddmm.mmmm(第一位零也将传送);
  6.   <5> 经度半球,E 或W(东经或西经)
  7.   <6> 定位质量指示,0=定位无效,1=定位有效;
  8.   <7>使用卫星数量,从00到12(第一个零也将传送)
  9.   <8>水平精确度,0.5到99.9
  10.   <9>天线离海平面的高度,-9999.9到9999.9米M指单位米
  11.   <10>大地水准面高度,-9999.9到9999.9米M指单位米
  12.   <11>差分GPS数据期限(RTCMSC-104),最后设立RTCM传送的秒数量
  13.   <12>差分参考基站标号,从0000到1023(首位0也将传送)。
 楼主| 我爱台妹mmd 发表于 2022-2-10 17:27 | 显示全部楼层
$GPVTG,<1>,T,<2>,M,<3>,N,<4>,K,<5>*hh
  <1> 以正北为参考基准的地面航向(000~359度,前面的0也将被传输)
  <2> 以磁北为参考基准的地面航向(000~359度,前面的0也将被传输)
  <3> 地面速率(000.0~999.9节,前面的0也将被传输)
  <4> 地面速率(0000.0~1851.8公里/小时,前面的0也将被传输)
  <5> 模式指示(仅NMEA0183 3.00版本输出,A=自主定位,D=差分,E=估算,N=数据无效
 楼主| 我爱台妹mmd 发表于 2022-2-10 17:29 | 显示全部楼层
  1. $GPGSV,(1),(2),(3),(4),(5),(6),(7),…(4),(5),(6),(7)*hh(CR)(LF) 
  2. 各部分含义为:
  3.   (1)总的GSV语句电文数;2;
  4.   (2)当前GSV语句号:1;
  5.   (3)可视卫星总数:08;
  6.   (4)PRN码(伪随机噪声码) 也可以认为是卫星编号
  7.   (5)仰角(00~90度):33度;
  8.   (6)方位角(000~359度):240度;
  9.   (7)信噪比(00~99dB):45dB(后面依次为第10,16,17号卫星的信息);   *总和校验域;    hh 总和校验数:78;   (CR)(LF)回车,换行。
  10.   注:每条语句最多包括四颗卫星的信息,每颗卫星的信息有四个数据项,即:
  11.     (4)-卫星号,(5)-仰角,(6)-方位角,(7)-信噪比。
 楼主| 我爱台妹mmd 发表于 2022-2-10 17:30 | 显示全部楼层
  1. $GPGSA,A,3,01,20,19,13,,,,,,,,,40.4,24.4,32.2*0A
  2. 字段1:定位模式,A=自动手动2D/3D,M=手动2D/3D   
  3. 字段2:定位类型,1=未定位,2=2D定位,3=3D定位   
  4. 字段3:PRN码(伪随机噪声码),第1信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)   
  5. 字段4:PRN码(伪随机噪声码),第2信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)   
  6. 字段5:PRN码(伪随机噪声码),第3信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)   
  7. 字段6:PRN码(伪随机噪声码),第4信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)   
  8. 字段7:PRN码(伪随机噪声码),第5信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)   
  9. 字段8:PRN码(伪随机噪声码),第6信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)   
  10. 字段9:PRN码(伪随机噪声码),第7信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)   
  11. 字段10:PRN码(伪随机噪声码),第8信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)   
  12. 字段11:PRN码(伪随机噪声码),第9信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)   
  13. 字段12:PRN码(伪随机噪声码),第10信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)   
  14. 字段13:PRN码(伪随机噪声码),第11信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)   
  15. 字段14:PRN码(伪随机噪声码),第12信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)   
  16. 字段15:PDOP综合位置精度因子(0.5 - 99.9)   
  17. 字段16:HDOP水平精度因子(0.5 - 99.9)   
  18. 字段17:VDOP垂直精度因子(0.5 - 99.9)   
  19. 字段18:校验值
 楼主| 我爱台妹mmd 发表于 2022-2-10 17:31 | 显示全部楼层
代码部分
串口初始化部分
因为串口1用来电脑和stm32通信,所以GPS和stm32的通信选择串口2。
下面是串口2代码的初始化:
  1. void My_USART2_Init(void){
  2.         GPIO_InitTypeDef GPIO_InitStrue;
  3.         USART_InitTypeDef USART2_InitStrue;
  4.         NVIC_InitTypeDef NVIC_InitStrue;
  5.        
  6.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  7.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
  8.        
  9.         GPIO_InitStrue.GPIO_Mode = GPIO_Mode_AF_PP;//推挽输出
  10.         GPIO_InitStrue.GPIO_Pin = GPIO_Pin_2;
  11.         GPIO_InitStrue.GPIO_Speed = GPIO_Speed_10MHz;
  12.         GPIO_Init(GPIOA, &GPIO_InitStrue);
  13.        
  14.         GPIO_InitStrue.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  15.         GPIO_InitStrue.GPIO_Pin = GPIO_Pin_3;
  16.         GPIO_InitStrue.GPIO_Speed = GPIO_Speed_10MHz;
  17.         GPIO_Init(GPIOA, &GPIO_InitStrue);
  18.        
  19.         USART2_InitStrue.USART_BaudRate = 9600;
  20.         USART2_InitStrue.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  21.         USART2_InitStrue.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
  22.         USART2_InitStrue.USART_Parity = USART_Parity_No;//奇偶校验位
  23.         USART2_InitStrue.USART_StopBits = USART_StopBits_1;//停止位
  24.         USART2_InitStrue.USART_WordLength = USART_WordLength_8b;//数据位
  25.         USART_Init(USART2, &USART2_InitStrue);
  26.        
  27.         USART_Cmd(USART2, ENABLE);
  28.        
  29.        
  30.         USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//打开接收中断,当接收到数据时开启中断
  31.         NVIC_InitStrue.NVIC_IRQChannel = USART2_IRQn;
  32.         NVIC_InitStrue.NVIC_IRQChannelCmd = ENABLE;
  33.         NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority = 1;
  34.         NVIC_InitStrue.NVIC_IRQChannelSubPriority = 1;
  35.         NVIC_Init(&NVIC_InitStrue);
  36. }
 楼主| 我爱台妹mmd 发表于 2022-2-10 17:32 | 显示全部楼层
下面是串口2中断代码:
  1. extern short int point1;
  2. extern const short int USART2_MAX_RECV_LEN;
  3. extern char USAR2_RX_BUF[200];
  4. extern const short int GPS_Buffer_Length;
  5. short int point1;
  6. extern struct Data Save_Data;

  7. void USART2_IRQHandler(void){
  8.         u8 res;
  9.         if(USART_GetITStatus(USART2, USART_IT_RXNE)){
  10.                 res = USART_ReceiveData(USART2);
  11.                 if(res == '){
  12.                         point1 = 0;
  13.                 }
  14.                 USAR2_RX_BUF[point1++] = res;
  15.                 if(USAR2_RX_BUF[0] == ' && USAR2_RX_BUF[4] == 'M' && USAR2_RX_BUF[5] == 'C'){
  16.                         if(res == '\n'){
  17.                                 memcpy(Save_Data.GPS_Buffer, USAR2_RX_BUF, point1);
  18.                                 Save_Data.isGetData = TRUE;
  19.                                 point1 = 0;
  20.                                 memset(USAR2_RX_BUF, 0, USART2_MAX_RECV_LEN);//Çå¿ÕÊý×é
  21.                                
  22.                                 parseGpsBuffer();//½âÎöÊý¾Ý
  23.                                 printfGpsBuffer();//´òÓ¡Êý¾Ý
  24.                         }
  25.                 }
  26.                 if(point1 >= USART2_MAX_RECV_LEN)
  27.                 {
  28.                         point1 = USART2_MAX_RECV_LEN;
  29.                 }
  30.         }
  31. }
 楼主| 我爱台妹mmd 发表于 2022-2-10 17:34 | 显示全部楼层
GPS部分代码
解析GPS数据代码
  1. #ifndef _GPS_//预编译
  2. #define _GPS_
  3. #include "sys.h"


  4. typedef struct Data
  5. {
  6.         char GPS_Buffer[200];//数据接收       
  7.         BOOL isGetData;//接收数据是否完成
  8.         char *UTCTime;//时间戳
  9.         char *latitude;//纬度
  10.         char *N_S;//南北
  11.         char *longitude;//经度
  12.         char *E_W;//东西
  13.         BOOL isParseData;//是否解析完成
  14.         BOOL isUsefull;//是否为有效数据位
  15. }Data;



  16. void parseGpsBuffer(void);
  17. void printfGpsBuffer(void);
  18. #endif
 楼主| 我爱台妹mmd 发表于 2022-2-10 17:34 | 显示全部楼层
  1. const short int USART2_MAX_RECV_LEN = 200;
  2. char USAR2_RX_BUF[USART2_MAX_RECV_LEN];
  3. const short int GPS_Buffer_Length = 200;
  4. struct Data Save_Data;

  5. void parseGpsBuffer(void){
  6.         char *subString;
  7.         char *subStringNext;
  8.         int i = 0;
  9.         if(Save_Data.isGetData)
  10.         {
  11.                 Save_Data.isGetData = FALSE;
  12.                 printf("*****************\r\n");
  13.                 printf("%s",Save_Data.GPS_Buffer);
  14.                
  15.                 for(i = 0; i <= 6; i++){
  16.                         if(i == 0){
  17.                                 if((subString = strstr(Save_Data.GPS_Buffer, ",")) == NULL)
  18.                                         printf("解析错误");
  19.                                 }
  20.                                 else{
  21.                                         subString++;//到达解析数据中逗号的下一位
  22.                                         if((subStringNext = strstr(subString, ",")) != NULL)
  23.                                         {
  24.                                                 char usefullBuffer[2];
  25.                                                 switch(i){
  26.                                                         case 1:
  27.                                                                 //利用subStringNext和subString的首地址相减来确定指针开辟空间的大小,以防指针不合法。
  28.                                                                 Save_Data.UTCTime = (char *)malloc((subStringNext - subString)*sizeof(char));
  29.                                                                 memcpy(Save_Data.UTCTime, subString, subStringNext - subString);
  30.                                                                 break;
  31.                                                         case 2: memcpy(usefullBuffer, subString, subStringNext - subString); break;
  32.                                                         case 3: Save_Data.latitude = (char *)malloc((subStringNext - subString)*sizeof(char));
  33.                                                                 memcpy(Save_Data.latitude, subString, subStringNext - subString);
  34.                                                                 break;
  35.                                                         case 4: Save_Data.N_S = (char *)malloc((subStringNext - subString)*sizeof(char));
  36.                                                                 memcpy(Save_Data.N_S, subString, subStringNext - subString);
  37.                                                                 break;
  38.                                                         case 5: Save_Data.longitude = (char *)malloc((subStringNext - subString)*sizeof(char));
  39.                                                                 memcpy(Save_Data.longitude, subString, subStringNext - subString);
  40.                                                                 break;
  41.                                                         case 6: Save_Data.E_W = (char *)malloc((subStringNext - subString)*sizeof(char));
  42.                                                                 memcpy(Save_Data.E_W, subString, subStringNext - subString);
  43.                                                                 break;
  44.                                                         default: break;
  45.                                                 }
  46.                                                 subString = subStringNext;
  47.                                                 Save_Data.isParseData = TRUE;
  48.                                                 if(usefullBuffer[0] == 'A')
  49.                                                         Save_Data.isUsefull = TRUE;
  50.                                                 else if(usefullBuffer[0] == 'V')
  51.                                                         Save_Data.isUsefull = FALSE;
  52.                                         }
  53.                                         else{
  54.                                                         printf("解析错误2");
  55.                                         }
  56.                                 }
  57.                         }
  58.                 }
  59. }
 楼主| 我爱台妹mmd 发表于 2022-2-10 17:37 | 显示全部楼层
打印GPS数据代码到串口调试助手上:
  1. void printfGpsBuffer(void){
  2.         if(Save_Data.isParseData){
  3.                 Save_Data.isParseData = FALSE;
  4.                 printf("Save_Data.UTCTime = %s\r\n", Save_Data.UTCTime);//打印数据
  5.                 free(Save_Data.UTCTime);//释放空间
  6.                
  7.                 if(Save_Data.isUsefull){
  8.                         Save_Data.isUsefull = FALSE;
  9.                         printf("Save_Data.latitude = %s\r\n", Save_Data.latitude);
  10.                         free(Save_Data.latitude);
  11.                         printf("Save_Data.N_S = %s\r\n", Save_Data.N_S);
  12.                         free(Save_Data.N_S);
  13.                         printf("Save_Data.longitude = %s\r\n", Save_Data.longitude);
  14.                         free(Save_Data.longitude);
  15.                         printf("Save_Data.E_W = %s\r\n", Save_Data.E_W);
  16.                         free(Save_Data.E_W);
  17.                 }
  18.                 else
  19.                 {
  20.                         printf("GPS DATA is not usefull!\r\n");
  21.                 }
  22.         }
  23. }

 楼主| 我爱台妹mmd 发表于 2022-2-10 23:35 | 显示全部楼层
数据展示 547496204dcf391470.png

评论

上图就是经过解析提取到的GPRMC数据,把经纬度输入到地图上就可以查看具体位置了。  发表于 2022-2-10 23:35
mickit 发表于 2022-2-13 09:50 | 显示全部楼层
楼主有上位机的程序吗  
jstgotodo 发表于 2022-2-13 10:38 | 显示全部楼层
GPS模块推荐哪款呢   
jackcat 发表于 2022-2-13 21:25 | 显示全部楼层
stm32与GPS模块是串口吗
您需要登录后才可以回帖 登录 | 注册

本版积分规则

72

主题

648

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部