当前位置: 首页 > 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.gsyq.cn/news/100870.html

相关文章:

  • Point-E点云预处理:从入门到精通的完整指南
  • Pig企业级权限管理系统:从零搭建微服务架构的实战指南
  • 终极船舶水动力学与运动控制实践指南:从建模到仿真的完整技术路径
  • Postman便携版深度解析:Windows免安装API测试神器全攻略
  • LRCGET:离线音乐库的终极批量歌词同步解决方案 [特殊字符]
  • x64dbg调试器完整指南:从零开始掌握逆向分析核心技术
  • Qwen3-VL-8B-Instruct-FP8横空出世:FP8量化技术引领多模态AI进入普惠时代
  • Obsidian Git高效配置:构建智能笔记备份系统
  • 探索硬件检测的5个高效方法:系统信息获取完全指南
  • 3分钟快速上手MediaGo:终极M3U8视频下载指南
  • 安卓智能新纪元:智谱AI开源AndroidGen-GLM-4-9B,重新定义移动端AI交互范式
  • 人工智能如何重塑未来工作格局:机遇与挑战并存
  • 40亿参数引爆多模态AI革命:Qwen3-VL-4B-FP8开启边缘智能新纪元
  • UE5 材质-37-节点:
  • 多模态生成革命:Lumina-DiMOO全能模型重塑跨模态交互新范式
  • 腾讯发布HunyuanWorld-Voyager:单图驱动3D场景漫游的视频生成框架革新
  • 终极SafetyNet绕过技术:在Google检测下实现系统属性无缝修改
  • 开源多模态新突破:CogVLM2 模型深度解析与性能评测
  • 如何快速构建高效信息流:智能订阅工具的终极指南
  • 5分钟搞定全网资源下载:这款跨平台工具让你轻松捕获视频号、抖音无水印内容
  • ZoomEye功能类似的搜索引擎还有哪些?结合ZoomEye等进行相关搜索以及如何进行子域名收集[特殊字符]
  • Python工作流引擎SpiffWorkflow:如何用纯代码解决复杂业务流程管理难题?
  • AdGuard浏览器扩展:终极免费广告拦截和隐私保护解决方案
  • Quill图片调整终极指南:一键实现富文本图片大小控制
  • 百度网盘分享链接解析工具完全使用指南
  • 3步搞定!E-Hentai下载工具解放双手,献给ACG爱好者的终极离线方案
  • 零基础极速上手:Docker一键部署wvp-GB28181-pro视频监控平台
  • ArkLights明日方舟智能托管助手:解放双手的终极游戏伴侣
  • 微信小程序大文件上传终极方案:性能对比与实战指南
  • Delphi逆向工程实战:从零精通IDR反编译工具