当前位置: 首页 > news >正文

一、基于freertos系统上关于ATGM336H定位模块的定位测试验证

一、硬件连接

模块引脚 连接目标 说明
TX 串口助手接收端(RX) 交叉连接,用于模块发送数据到上位机
RX 不接 测试阶段无需发送指令,可悬空
VCC 5V/3.3V 根据模块版本选择:多数ATGM336H型号需5V供电(具体以规格书为准)
GND GND 必须与上位机共地,否则会导致数据乱码或通信失败
注意
1、模块上的led灯闪烁时,相当于提示定位信息获取到了,常量表示定位失效。
2、断电重启模块,更新信息状态。
3、定位时,天线上的陶瓷片向上(陶瓷片上的金属小点一面朝向天空),朝向空旷的天空,高楼会遮挡信号导致定位不到。
4、模块的通信默认用9600波特率通信的。

二、代码部分

定义部分

#defineDMA_BUF_SIZE256// DMA接收缓冲区大小#defineNMEA_QUEUE_LEN8// NMEA帧队列长度#defineGNGGA_HEAD"$GNGGA"#defineLAT_LON_SCALE60.0f// 度分转度的系数#defineGNGGA_MIN_FIELD_CNT6typedefstruct{uint8_tvalid;// 定位有效标志(1有效,0无效)chartime[7];// UTC时间(HHMMSS)floatlatitude;// 纬度(度)charlat_dir;// 纬度方向(N/S)floatlongitude;// 经度(度)charlon_dir;// 经度方向(E/W)uint8_tsat_num;// 锁定卫星数(新增,适配GNGGA)uint8_tparse_ok;// 解析成功标志}GnssInfo_t;externGnssInfo_t gnss_info;floatnmea_degree_convert(char*str);// 度分转度externuint8_tdma_rx_buf[DMA_BUF_SIZE];externvolatileuint16_tdma_rx_len;// 开启USART2空闲中断__HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE);// 启动DMA接收(循环模式)HAL_UART_Receive_DMA(&huart2,dma_rx_buf,DMA_BUF_SIZE);voidUSART2_IRQHandler(void){HAL_UART_IRQHandler(&huart2);USART2_IDLE_IRQHandler();// 处理空闲中断}// 打印定位信息voidUSART2_IDLE_IRQHandler(void){if(__HAL_UART_GET_FLAG(&huart2,UART_FLAG_IDLE)!=RESET){__HAL_UART_CLEAR_IDLEFLAG(&huart2);// 清除空闲中断标志HAL_UART_DMAStop(&huart2);// 停止DMA接收// 计算接收长度dma_rx_len=DMA_BUF_SIZE-__HAL_DMA_GET_COUNTER(&hdma_usart2_rx);}}floatnmea_degree_convert(char*str){if(str==NULL||strlen(str)<4||strchr(str,'.')==NULL){return0.0f;}floatdegree=0.0f;floatminute=0.0f;chartemp[16]={0};intdot_pos=strchr(str,'.')-str;// 纬度:DDMM.mmmm → 前2位度if(strlen(str)>=4&&dot_pos>=2){strncpy(temp,str,2);degree=atof(temp);minute=atof(str+2);}// 经度:DDDMM.mmmm → 前3位度elseif(strlen(str)>=5&&dot_pos>=3){strncpy(temp,str,3);degree=atof(temp);minute=atof(str+3);}else{return0.0f;}// 防止转换后为0(有效经纬度不可能为0)floatres=degree+(minute/LAT_LON_SCALE);return(res>0.0f)?res:0.0f;}

任务调用部分

//获取信息voidStartTask01(void*argument){uint8_tnmea_buf[DMA_BUF_SIZE]={0};for(;;){if(dma_rx_len>0){// 拷贝DMA接收的数据到临时缓冲区memcpy(nmea_buf,dma_rx_buf,dma_rx_len);nmea_buf[dma_rx_len]='\0';// 字符串结束符//输出串口接收信息HAL_UART_Transmit(&huart1,(uint8_t*)&dma_rx_buf,dma_rx_len,8000);printf("\r\n");// 发送到NMEA解析队列osMessageQueuePut(myQueue01Handle,nmea_buf,0,100);// 重置DMA接收dma_rx_len=0;memset(dma_rx_buf,0,DMA_BUF_SIZE);HAL_UART_Receive_DMA(&huart2,dma_rx_buf,DMA_BUF_SIZE);}osDelay(5);}}//解析部分voidStartTask02(void*argument){uint8_tnmea_buf[DMA_BUF_SIZE]={0};for(;;){// 解析任务核心逻辑if(osMessageQueueGet(myQueue01Handle,nmea_buf,NULL,100)==osOK){gnss_info.parse_ok=0;char*gngga_frame=strstr((char*)nmea_buf,GNGGA_HEAD);if(gngga_frame!=NULL&&strlen(gngga_frame)>20){char*token=NULL;char*save_ptr=NULL;intfield_idx=0;intfield_cnt=0;// 临时变量:先存储经纬度字符串,等定位质量解析后再转换charlat_str[16]={0};charlon_str[16]={0};token=strtok_r(gngga_frame,",",&save_ptr);while(token!=NULL){field_cnt++;if(strlen(token)==0){token=strtok_r(NULL,",",&save_ptr);field_idx++;continue;}switch(field_idx){case0:// $GNGGA:帧头校验if(strcmp(token,GNGGA_HEAD)!=0){field_idx=-1;break;}break;case1:// UTC时间(HHMMSS.ss)if(strlen(token)>=6){strncpy(gnss_info.time,token,6);gnss_info.time[6]='\0';}else{memset(gnss_info.time,0,sizeof(gnss_info.time));}break;// 先存储经纬度字符串(不立即转换)case2:// 纬度字符串(DDMM.mmmm)strncpy(lat_str,token,sizeof(lat_str)-1);break;case3:// 纬度方向(N/S)if(token[0]=='N'||token[0]=='S'){gnss_info.lat_dir=token[0];}else{gnss_info.lat_dir='\0';}break;case4:// 经度字符串(DDDMM.mmmm)strncpy(lon_str,token,sizeof(lon_str)-1);break;case5:// 经度方向(E/W)if(token[0]=='E'||token[0]=='W'){gnss_info.lon_dir=token[0];}else{gnss_info.lon_dir='\0';}break;case6:// 定位质量(核心:先解析!)gnss_info.valid=(atoi(token)==1)?1:0;// 定位有效时,再转换经纬度(关键修复!)if(gnss_info.valid){if(strlen(lat_str)>=4)gnss_info.latitude=nmea_degree_convert(lat_str);if(strlen(lon_str)>=5)gnss_info.longitude=nmea_degree_convert(lon_str);}break;case7:// 卫星数gnss_info.sat_num=atoi(token);break;default:if(field_idx>=8)// 解析到卫星数后停止{token=NULL;break;}break;}if(field_idx==-1){token=NULL;break;}token=strtok_r(NULL,",",&save_ptr);field_idx++;}// 放宽最终校验条件(适配实际场景)if(field_cnt>=7// 至少7个字段(核心字段)&&gnss_info.valid==1// 定位质量=1&&gnss_info.lat_dir!='\0'// 纬度方向有效&&gnss_info.lon_dir!='\0'// 经度方向有效&&gnss_info.latitude>0.0f// 纬度>0(有效范围)&&gnss_info.longitude>0.0f// 经度>0(有效范围)&&gnss_info.sat_num>=1)// 卫星数≥1(放宽){gnss_info.parse_ok=1;// 【调试打印】解析成功提示printf("解析成功!纬度:%.6f%c,经度:%.6f%c,utc时间:%s,定位质量=%d,卫星数=%d\r\n",gnss_info.latitude,gnss_info.lat_dir,gnss_info.longitude,gnss_info.lon_dir,gnss_info.time,gnss_info.valid,gnss_info.sat_num);}else{memset(&gnss_info,0,sizeof(GnssInfo_t));printf("解析失败:字段数=%d,定位质量=%d,卫星数=%d\r\n",field_cnt,gnss_info.valid,gnss_info.sat_num);}}}osDelay(10);}}

测试效果示意图:

http://www.jsqmd.com/news/90466/

相关文章:

  • Point-E点云预处理:从入门到精通的完整指南
  • 腾讯混元-7B-Instruct震撼发布:中文大模型领域的里程碑突破
  • Twitch掉落自动收集器:5分钟掌握高效挂机技巧
  • Pig企业级权限管理系统:从零搭建微服务架构的实战指南
  • 终极船舶水动力学与运动控制实践指南:从建模到仿真的完整技术路径
  • Postman便携版深度解析:Windows免安装API测试神器全攻略
  • LRCGET:离线音乐库的终极批量歌词同步解决方案 [特殊字符]
  • Qwen3-0.6B震撼发布:轻量级大模型迎来推理与多语言能力的双重突破
  • AutoGPT景点讲解词生成AI
  • AriaNg下载管理革命:可视化界面如何终结命令行时代
  • x64dbg调试器完整指南:从零开始掌握逆向分析核心技术
  • Lumafly模组管理器:Hollow Knight玩家的终极跨平台解决方案
  • 终极指南:3步搞定LyricsX桌面歌词,打造沉浸式音乐体验
  • 企业级权限管理系统15分钟快速部署指南:Pig完整教程
  • Qwen3-VL-8B-Instruct-FP8横空出世:FP8量化技术引领多模态AI进入普惠时代
  • Obsidian Git高效配置:构建智能笔记备份系统
  • 心电图AI分类终极指南:3个简单步骤让新手快速上手
  • ViGEmBus虚拟手柄驱动:打造完美游戏控制体验的终极解决方案
  • 明日方舟速通神器ArkLights:完整自动化游戏体验终极指南
  • 人工智能大模型发展新趋势:技术突破与行业应用深度融合
  • 揭秘Whisper.cpp:如何用离线语音识别技术解决真实业务痛点
  • 探索硬件检测的5个高效方法:系统信息获取完全指南
  • UKB_RAP生物医学数据分析平台完全实战手册
  • GPT-SoVITS WebUI语音合成终极指南:从零开始打造个性化语音助手
  • Mac本地大模型性能突破:mlx-lm 0.28.1版本效率跃升背后的语言异常现象调查
  • 腾讯Hunyuan3D-1模型震撼开源:10秒实现文本图像转3D资产,引领行业生产力革命
  • 3分钟快速上手MediaGo:终极M3U8视频下载指南
  • 用BlenderGIS重塑真实地形的高效工作流
  • OpenBoardView终极指南:如何免费查看.brd电路板文件
  • 安卓智能新纪元:智谱AI开源AndroidGen-GLM-4-9B,重新定义移动端AI交互范式