原创 【电子DIY】STM32F407定位器

2025-2-13 23:05 48 0 分类: MCU/ 嵌入式 文集: 随心记
前言
最近正好想要做一个定位器,正好可以用嘉立创的STM32F407的板子,还要淘晶驰的串口屏
配合NEO-6M做一个GPS实时定位
感觉设计到的知识点还是挺全面的,包括串口通信,还要定时器




硬件
NEO-6M
采用串口通信,默认9600(可以通过软件改115200)
搭配有源天线,在室外定位很好用


淘晶驰
很火的串口屏,通过自带的软件可以随便画界面,还是很方便的
可通过 USART HMI 软件进行全界面可视化编辑、支持 “C 语言代码” 和 “0 代码” 双模式编程,广泛应用于工业控制、智能家居等领域的智能串口显示屏。


STM32F407
意法半导体推出的基于 ARM Cortex-M4 内核的高性能微控制器,具有高达 168MHz 的主频、丰富的外设接口(如 USB OTG、以太网、CAN 等)、大容量的闪存和 SRAM,适用于工业控制、消费电子、汽车电子等对处理能力和外设资源要求较高的多种应用场景。


软件
下面是MX的一些设置





通过串口1解析NEO-6M的数据
然后将数据解析,将获取到的经纬度数据,通过串口2发送到串口屏
void convert_utc_to_local(char *utc_time, char *local_time) {
    int hour, minute, second;
    // 从UTC时间字符串中解析出小时、分钟和秒
    sscanf(utc_time, "%2d%2d%2d", &hour, &minute, &second);

    // 加上时区偏移
    hour = (hour + 8) % 24;//中国时区+8

    // 格式化本地时间字符串,添加冒号分隔符
    sprintf(local_time, "%02d:%02d:%02d", hour, minute, second);
}


float convert_to_degree(float coord) {
    int degrees = (int)(coord / 100);
    float minutes = coord - (degrees * 100);
    return degrees + (minutes / 60);
}

void ParseGNGGA(char *gga_string) {
    char *token;
    token = strtok(gga_string, ","); // 按逗号分隔字符串
    if (token == NULL) return;

    // 跳过 $GNGGA
    token = strtok(NULL, ",");
    if (token == NULL) return;
    // UTC时间
    char *utc_time = token;

    // 纬度
    token = strtok(NULL, ",");
    if (token == NULL) return;
    float latitude = atof(token);
    // 北纬或南纬
    token = strtok(NULL, ",");
    if (token == NULL) return;
    char latitude_hemisphere = token[0];

    // 经度
    token = strtok(NULL, ",");
    if (token == NULL) return;
    float longitude = atof(token);
    // 东经或西经
    token = strtok(NULL, ",");
    if (token == NULL) return;
    char longitude_hemisphere = token[0];

    // 定位质量指示
    token = strtok(NULL, ",");
    if (token == NULL) return;
    int fix_quality;
    if (is_numeric(token)) {
        fix_quality = atoi(token);
    } else {
        fix_quality = 0; // 错误处理,如果不是数字,设为0
    }

    // 使用卫星数量
    token = strtok(NULL, ",");
    if (token == NULL) return;
    int num_satellites;
    if (is_numeric(token)) {
        num_satellites = atoi(token);
    } else {
        num_satellites = 0; // 错误处理,如果不是数字,设为0
    }

    // 水平精确度
    token = strtok(NULL, ",");
    if (token == NULL) return;
    float horizontal_accuracy = atof(token);

    // 天线离海平面的高度
    token = strtok(NULL, ",");
    if (token == NULL) return;
    float altitude = atof(token);

    // 大地水准面高度
    token = strtok(NULL, ",");
    if (token == NULL) return;
    float geoidal_height = atof(token);

    // 将度分格式的经纬度转换为度格式
    latitude = convert_to_degree(latitude);
    longitude = convert_to_degree(longitude);

    // 打印解析结果
//	//DMA_Usart_Send(utc_time, 10);
//   // printf("UTC Time: %s\n", utc_time);
 char local_time[10];
convert_utc_to_local(utc_time, local_time);
		printf2("page1.t0.txt=\"%s\"\xff\xff\xff",local_time);  
		HAL_Delay(5);
//DMA_Usart_Send2(utc_time,10);
//   // printf("Latitude: %f %c\n", latitude, latitude_hemisphere);

	printf2("page0.t0.txt=\"%f\"\xff\xff\xff",latitude);
	HAL_Delay(5);
////	printf2("t0.txt=\"%c\"\xff\xff\xff",latitude_hemisphere);  //N

//  //  printf("Longitude: %f %c\n", longitude, longitude_hemisphere);
	printf2("page0.t1.txt=\"%f\"\xff\xff\xff",longitude);
	HAL_Delay(5);
//	//printf2("t0.txt=\"%c\"\xff\xff\xff",longitude_hemisphere);  //E

//	
//    //printf("Fix Quality: %d\n", fix_quality);
	//    printf2("t0.txt=\"%d\"\xff\xff\xff", fix_quality);  
		HAL_Delay(5);
	 if(num_satellites<1)
	 {
	  printf2("page0.t2.bco=63488\xff\xff\xff");//GPS状态指示,红
		 HAL_Delay(5);
	 }else{
	   printf2("page0.t2.bco=2016\xff\xff\xff");//GPS状态指示,绿
		 HAL_Delay(5);
	 }

//	  
//    //printf("Number of Satellites: %d\n", num_satellites);//卫星数量
	printf2("page0.t6.txt=\"%d\"\xff\xff\xff",num_satellites);  
HAL_Delay(5);
//  //  printf("Horizontal Accuracy: %f m\n", horizontal_accuracy);
//	//printf2("t0.txt=\"%f\"\xff\xff\xff",horizontal_accuracy);  
//	
//    //printf("Altitude: %f m\n", altitude);//海拔
	printf2("page0.t8.txt=\"%f\"\xff\xff\xff",altitude);  
HAL_Delay(5);
//   // printf("Geoidal Height: %f m\n", geoidal_height);
	 
//send_http("AT+MHTTPREQUEST=0,1,0,\"/api/tqyb.php?city=442000\"\r");
//send_http("AT+MHTTPREQUEST=0,1,0,\"/api/GPS/gps.php?id=1001&N=\"%f\"&E=22.22\"\r",latitude);
char command[2000];
    snprintf(command, sizeof(command), "AT+MHTTPREQUEST=0,1,0,\"/api/GPS/gps.php?id=1001&N=%.6f&E=%.6f\"\r", latitude, longitude);

    // 调用 send_http 函数发送请求
    send_http(command);
}




bool is_numeric(const char *str) {
  while (*str) {
    if (!isdigit(*str)) {
      return false;
    }
    str++;
  }
  return true;
}



主函数循环
 while (1) 
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */

   Led0_Light_N(1,100);
// printf3("test");
   if(recv_end_flag == 1)  //接收完成标志
  {
   
   ParseGNGGA(rx_buffer);
   
//  DMA_Usart_Send(rx_buffer, rx_len);
   rx_len = 0;//清除计数
   recv_end_flag = 0;//清除接收结束标志位
//   for(uint8_t i=0;i//    {
//     rx_buffer=0;//清接收缓存
//    }
    memset(rx_buffer,0,rx_len);
  }
  HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);//重新打开DMA接收
  
  
  
  
  
     if(recv_end_flag2 == 1)  //接收完成标志
  {
   
//  ParseGNGGA(rx_buffer2);
//  DMA_Usart_Send2(rx_buffer2, rx_len2);
   rx_len2 = 0;//清除计数
   recv_end_flag2 = 0;//清除接收结束标志位
//   for(uint8_t i=0;i//    {
//     rx_buffer=0;//清接收缓存
//    }
    memset(rx_buffer2,0,rx_len2);
  }
  HAL_UART_Receive_DMA(&huart2,rx_buffer2,BUFFER_SIZE2);//重新打开DMA接收
  
  
       if(recv_end_flag3 == 1)  //接收完成标志
  {
   
//  ParseGNGGA(rx_buffer2);
   //DMA_Usart_Send3(rx_buffer3, rx_len3);
   printf3(rx_buffer3);
   rx_len3 = 0;//清除计数
   recv_end_flag3 = 0;//清除接收结束标志位
//   for(uint8_t i=0;i//    {
//     rx_buffer=0;//清接收缓存
//    }
    memset(rx_buffer3,0,rx_len3);
  }
  HAL_UART_Receive_DMA(&huart3,rx_buffer3,BUFFER_SIZE3);//重新打开DMA接收
  
  
 
屏幕类似这样设计,不过大家可以发挥想象,串口屏还是很好玩的



实验现象


完整代码

作者: 小恶魔owo, 来源:面包板社区

链接: https://mbb.eet-china.com/blog/uid-me-4067534.html

版权声明:本文为博主原创,未经本人允许,禁止转载!

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
0
关闭 站长推荐上一条 /3 下一条