您好,
会员登录 快速注册
退出 ( 条未读消息)
关于本站 意见反馈 首页

公告:小宅博客网可以开发票了,需要发票的,去群里找群主哈!!
全部文章分类
  • 人工智能 >

  • 编程语言 >

  • WPF系列 >

  • ASP.NET系列 >

  • Linux >

  • 数据库 >

  • 嵌入式 >

  • WEB技术 >

  • PLC系列 >

  • 微服务与框架 >

  • 小宅DIY >

  • 学习资料 >

OpenCv基础 ANN车牌识别 yolov5车牌识别 指针式仪表识别 ROS系列 YOLO Halcon Detectron2 昇腾AI ChatGPT在线体验 英伟达JETSON ChatGLM ChatTTS FunASR 地平线 ByteTrack 魔搭社区 LangChain
C C# C++ Python Java Go
WPF
ASP.NET小功能 GPS定位系统-MVC GPS定位系统-VUE ASP.NET WebRTC
Linux Linux内核 Shell MakeFile
MySql SqlServer Oracle
STM8 STM32 51单片机
VUE入门 HTML JavaScript CSS layui镜像网站 ElementUi中文官网 element-plus 图标
三菱 欧姆龙 西门子 施耐德 松下 台达
IOTSharp IOTGateway ABP FRAMEWORK Docker
亚克力音响 编程仙途:智驭万法
面试题与技巧 Python入门技能树 微软C#教程
首页 编程之美 工具下载 全国就业 流量地图 文心一言
GPS定位系统-MVC
.NET6.0 GPS定位系统介绍(物联网) 系列源码下载 1、新建.net core web工程 2、添加自定义登录页面 3、添加百度地图页面 4、添加后台日志系统 5、添加mysql数据存储 6、添加SqlServer数据存储(额外内容) 7、用户注册与登录功能实现 8、添加坐标报表页面(用于遍历地图坐标) 9、前后端数据交互与报表数据展示 10、报表数据的编辑与修改 11、用户登录与退出 12、自定义GPRS通讯协议 13、添加TCP通讯功能(接收) 14、添加TCP通讯功能(发送) 15、模拟GPRS数据通讯 16、设备链接状态检测与提示 17、新建Windows Server虚拟机 18、服务器IIS运行环境配置 19、服务器.net程序发布 20、关于如何配置.net3.1框架 21、关于如何配置.net5.0框架 22、WinForm版地图上位机(带数据库和TCP功能) 23、WPF版地图上位机(带数据库和TCP功能) 24、公网映射与外网通讯 25、GPS协议与AT命令流程说明 26、GPRS协议与AT命令流程说明 27、STM32、A9G硬件连接图 28、STM32开发环境搭建 29、STM32 GPS/GPRS通讯功能实现 30、STM32 GPS定位数据上报服务器 31、室外最终效果演示 32、结束语
29、STM32 GPS/GPRS通讯功能实现
31、室外最终效果演示
激萌の小宅 小宅博客网 GPS定位系统-MVC

文章作者:激萌の小宅

促销:¥0

价格:¥0

配送方式: 购买后立即生效(如购买异常,请联系站长)
付款之后一定要等待自动跳转结束,否则购买可能会失败
  • 0 天

    有效期

  • 0

    总销量

  • 0

    累计评价

STM32 GPS定位数据上报服务器 - (第三十讲)

视频讲解如下:


工程源码下载:GPS定位系统系列教程源码下载


        在上一节中,我们已经把下位机中A9G的AT命令集写好了。关于a9g.c文件的接口调用代码如下:

#include <string.h>
#include <stdlib.h>
#include "stdio.h"
#include "config.h"
#include "delay.h"
#include "usart2.h"
#include "usart3.h"
#include "A9G.h"
#include "GpsCoord.h"

// A9G模块的GPS和GPRS采用的同一个输出口,这就导致了TCP透传和GPS定位无法同时开启。
int PackNum = 0;// 每个包的包号

int dou_post(char **str_ptr)
{
  int post_num = 0;
  while((**str_ptr >='0')&&(**str_ptr <= '9')){
    post_num = post_num * 10;
    post_num += (**str_ptr - 48);
    (*str_ptr)++;
  }
  if(**str_ptr == '.') (*str_ptr)--;
  return post_num;
}
 
double dou_point(char **str_ptr)
{
  double point_num = 0;
  if((**str_ptr >='0')&&(**str_ptr <= '9')){
    point_num = **str_ptr - 48;
    (*str_ptr)++;
    if((**str_ptr >='0')&&(**str_ptr <= '9')){
      point_num += dou_point(str_ptr);
    }
  }
  if(**str_ptr == '\0') (*str_ptr)--;
  return point_num / 10;
}
 
// 字符串转double
double str_to_dou(char *str_ptr)
{
  int post_num = 0;
  double point_num = 0;
  int point_flag = 0;
  while(*str_ptr != '\0')
  {
    if(*str_ptr == '.')
      point_flag = 1;
    else if(point_flag == 0)
      post_num =dou_post(&str_ptr);
    else if(point_flag == 1)
      point_num =dou_point(&str_ptr);
    str_ptr++;

  }
  return (double)post_num + point_num;
}

// TCP通讯的和校验算法
u8 GetSum(u8 *data, int length)
{
    int i = 0;
    int value = 0;
    for (i = 0; i < length; i++)
    {
        value ^= data[i];
    }
    return (value & 0x00FF);
}

// 上传服务器
// Order 上传的数据
// length 数据长度
// oTime 等待超时时间
int SendServer(char *Order,int length, int oTime)
{
  int i = 0;
  int siz = 0;
  char Receive[700]={0}; // 服务器反馈数据

  // 发送AT命令
  printf("Send Sever:");
  for( i =0;i<length;i++)
  {
    printf("%02X ", Order[i]);
  }
  printf("\r\n");
  
  usart3_Send((u8 *)Order, length);
  usart3_FreeBuff(); // 把之前残留的垃圾清理掉
  
  // 等待接收,超时时间:oTime(秒)
  for(i = 0;i < oTime * 5; i++)
  {
    delay_ms(200); // 等待200ms,给串口中断留一些数据接收的时间
    siz = 0;
    memset(Receive,0,sizeof(Receive)); // 清空缓存数据
    siz = usart3_Receive((u8 *)Receive, sizeof(Receive)); // 接收串口数据
    if(siz <= 0) continue; 
    
    // 解析串口数据,如果接收到指定的字符了,则认为命令发送成功了
    // CC 01 00 01 00 07 01 00 CA
    if(Receive[0] == 0xCC && siz == 9)
    {
        // 发送AT命令
        printf("Recv:");
        for( i =0;i<siz;i++)
        {
          printf("%02X ", Receive[i]);
        }
        printf("\r\n");
        
        printf("Send Sever OK\r\n");
      // 我这里只对第一个字符做校验,其他的校验忽略。
      return 0;
    }
  }
  printf("Send Sever ERROR\r\n");
  return -1;
}
        
// GPS数据中提取坐标信息
int GetGpsLocation(char *data, int length, double *location)
{
    int i = 0, j = 0, a = 0, b = 0;
    char *p = NULL;
    char gnrmc[700] = "";// 原始GNRMC字符串
    char temp[12][15]={0,0}; // 保存解析到分割数据
    
    if(data == NULL || sizeof(data) == 0)
      
    printf("[%s]\r\n", data); //打印一下我们接收到的字符串
    
    // $GNRMC,112119.000,A,2559.8845,N,11921.6583,E,1.324,159.42,280922,,,A * 4F
    //我们GPS初始化的时候,定义的是GPS+BD模式,所以我们需要在 $GNRMC 里面提取出我们的坐标数据
    p = strstr(data,"$GNRMC");
    if(p == NULL)
      return -1; // 没找到我们需要的字符串
    while((p- data <= length))
    {
        gnrmc[i] = *p;
        if(gnrmc[i] == '\n')
        {
           gnrmc[i+1] = '\0';
          break;
        }
        p++;
        i++;
    }

    //时间、经纬度
    if((p = strstr(gnrmc,"$GNRMC")) != 0)
    {   
        p+=6;
        for(j = 0;j<12;j++)
        {
            p++;
            i = 0;
            while((*p != ',') && (*p != '*')){ 
              if(*p == '\0'){ j = 12; break;}
              temp[j][i++] = *(p++);  
            }
        }
    }

    if(temp[1][0] != 'A') //定位失败 
    {
        printf("定位失败!\r\n");
        return -1;
    }

    location[0] = str_to_dou(temp[2]);
    location[1] = str_to_dou(temp[4]);
    a = (int)(location[0]/100.0);
    b = (int)(location[1]/100.0);
    location[0] = a + (location[0] / 100.0 - a) * 100.0 / 60.0;// 纬度
    location[1] = b + (location[1] / 100.0 - b) * 100.0 / 60.0;// 经度
    
    // 将GPS坐标转换成百度坐标
    wgs2bd(location[0],location[1], &location[0], &location[1]); 
    
    printf("定位成功:%s,%s\r\n",temp[2], temp[4]);
    return 0;
}

// 发送坐标信息
void SendLocation(int user, double *location)
{
  // 拼装命令
  char oData[255] = {0};
  int ret = 0;
  long a = 0, b = 0;
  oData[ret++] = 0xCC; // 网络识别码
  oData[ret++] = 0x01; // 设备类型
  oData[ret++] = 0x00; // 设备号H
  oData[ret++] = 0x01; // 设备号L
  if(PackNum > 1000) PackNum = 0;
  oData[ret++] = (PackNum >> 8);     //  包号H
  oData[ret++] = (PackNum & 0x00FF); //  包号L
  oData[ret++] = 0x11; // 功能码
  // 用户ID 
  oData[ret++] = (user >> 8);     //  用户ID H
  oData[ret++] = (user & 0x00FF); //  用户ID L

  // 经度
  a = (long)(location[1] * 100000);
  oData[ret++] = ((a >> 24) & 0x000000FF);
  oData[ret++] = ((a >> 16) & 0x000000FF);
  oData[ret++] = ((a >> 8) & 0x000000FF);
  oData[ret++] = (a & 0x000000FF);

  // 纬度
  b = (long)(location[0] * 100000);
  oData[ret++] = ((b >> 24) & 0x000000FF);
  oData[ret++] = ((b >> 16) & 0x000000FF);
  oData[ret++] = ((b >> 8) & 0x000000FF);
  oData[ret++] = (b & 0x000000FF);

  // 校验
  oData[ret++] = (char)GetSum((u8 *)oData, ret);
  
  // 上传命令,应该走的是GPRS网络,等待可以久点,我这里是5秒
  SendServer(oData, ret, 5);
}

int main(void)
{    
  char GpsBuff[1000]="";
  double location[2]={0};
  int siz = 0;
  delay_init();//延时函数初始化
  usart2_Configuration(115200); // Printf的输出口(本来是打算用usart1来做打印接口的,但是我的板子usart1好像坏了。。。。)
  
  // 经过测试,GPS单次数据包大约有228个字节,我这里直接在.h文件中给串口2开辟300字节的缓存空间
  // A9G虽然有个独立的GPS输出口,但是在开启GPS定位时,AT命令口GPS口都会同时输出定位信息,这搞的GPS口很鸡肋。
  usart3_Configuration(115200); // GPRS、GPS
  
  // 串口测试用,将 A9G-USART 输出的数据直接透传到USART2口
  //  while(1)
  //  {
  //    delay_ms(500);
  //    siz = 0;
  //    memset(GpsBuff,0,sizeof(GpsBuff)); 
  //    siz = usart3_Receive((u8 *)GpsBuff, sizeof(GpsBuff)); 
  //    if(siz <= 0) continue; 
  //    
  //    usart2_Send((u8 *)GpsBuff, siz);
  //  }
  
  // 输出一些日志信息,方便调试
  printf("等待GPS设备启动完成...\r\n");
  // 等待GPS启动完成
  A9G_Start();  
  
  // 初始化GPS,但是先别启动GPS,因为我们后面还需要初始化GPRS
  printf("初始化GPS...\r\n");
  A9G_Init_GPS();
  printf("初始化GPS完成!\r\n");
  
  // 初始化GPRS,采用透传模式上传我们的数据,初始化完成之后,先别开起来。
  printf("初始化GPRS...\r\n");
  A9G_Init_GPRS("103.46.128.21", "39343");
  printf("初始化GPRS完成!\r\n");
    
  usart3_FreeBuff(); // 把之前残留的垃圾清理掉
  A9G_Start_GPS();   // 启动GPS
      
  // 开始采集
  while(1)
  {
    // 延时等待一下,反正也不需要那么快上报
    delay_ms(500);
        
    // 清理一下缓存
    siz = 0;
    memset(GpsBuff,0,sizeof(GpsBuff));
    siz = usart3_Receive((u8 *)GpsBuff, sizeof(GpsBuff));
    if(siz == 0) continue;
    
    // 提取GPS坐标,如果提取成功,说明定位成功了
    memset(location,0,sizeof(location));
    if(GetGpsLocation(GpsBuff, siz, location) == -1)
    {
      // 定位失败
      continue;
    }

    // 停止GPS
    A9G_Stop_GPS();

    // 启动GPRS 
    A9G_Start_GPRS();
    
    // 发送GPS坐标,用户的ID是2
    SendLocation(2, location);
    
    // 停止GPRS
    A9G_Stop_GPRS();
    
    // 启动GPS
    A9G_Start_GPS();
  }
}


29、STM32 GPS/GPRS通讯功能实现
31、室外最终效果演示

友情链接: CSDN激萌の小宅 95知识库 自考题库 罗分明个人网络博客 精益编程leanboot

小宅博客  www.bilibili996.com All Rights Reserved. 备案号: 闽ICP备2024034575号

网站经营许可证  福建省福州市 Copyright©2021-2025 版权所有

小宅博客
首页 智能家居 地图定位
公告:小宅博客网可以开发票了,需要发票的,去群里找群主哈!!

文章作者:激萌の小宅

促销:¥0

价格:¥0

配送方式: 购买后立即生效(如购买异常,请联系站长)
付款之后一定要等待自动跳转结束,否则购买可能会失败
  • 0 天

    有效期

  • 0

    总销量

  • 0

    累计评价

STM32 GPS定位数据上报服务器 - (第三十讲)

视频讲解如下:


工程源码下载:GPS定位系统系列教程源码下载


        在上一节中,我们已经把下位机中A9G的AT命令集写好了。关于a9g.c文件的接口调用代码如下:

#include <string.h>
#include <stdlib.h>
#include "stdio.h"
#include "config.h"
#include "delay.h"
#include "usart2.h"
#include "usart3.h"
#include "A9G.h"
#include "GpsCoord.h"

// A9G模块的GPS和GPRS采用的同一个输出口,这就导致了TCP透传和GPS定位无法同时开启。
int PackNum = 0;// 每个包的包号

int dou_post(char **str_ptr)
{
  int post_num = 0;
  while((**str_ptr >='0')&&(**str_ptr <= '9')){
    post_num = post_num * 10;
    post_num += (**str_ptr - 48);
    (*str_ptr)++;
  }
  if(**str_ptr == '.') (*str_ptr)--;
  return post_num;
}
 
double dou_point(char **str_ptr)
{
  double point_num = 0;
  if((**str_ptr >='0')&&(**str_ptr <= '9')){
    point_num = **str_ptr - 48;
    (*str_ptr)++;
    if((**str_ptr >='0')&&(**str_ptr <= '9')){
      point_num += dou_point(str_ptr);
    }
  }
  if(**str_ptr == '\0') (*str_ptr)--;
  return point_num / 10;
}
 
// 字符串转double
double str_to_dou(char *str_ptr)
{
  int post_num = 0;
  double point_num = 0;
  int point_flag = 0;
  while(*str_ptr != '\0')
  {
    if(*str_ptr == '.')
      point_flag = 1;
    else if(point_flag == 0)
      post_num =dou_post(&str_ptr);
    else if(point_flag == 1)
      point_num =dou_point(&str_ptr);
    str_ptr++;

  }
  return (double)post_num + point_num;
}

// TCP通讯的和校验算法
u8 GetSum(u8 *data, int length)
{
    int i = 0;
    int value = 0;
    for (i = 0; i < length; i++)
    {
        value ^= data[i];
    }
    return (value & 0x00FF);
}

// 上传服务器
// Order 上传的数据
// length 数据长度
// oTime 等待超时时间
int SendServer(char *Order,int length, int oTime)
{
  int i = 0;
  int siz = 0;
  char Receive[700]={0}; // 服务器反馈数据

  // 发送AT命令
  printf("Send Sever:");
  for( i =0;i<length;i++)
  {
    printf("%02X ", Order[i]);
  }
  printf("\r\n");
  
  usart3_Send((u8 *)Order, length);
  usart3_FreeBuff(); // 把之前残留的垃圾清理掉
  
  // 等待接收,超时时间:oTime(秒)
  for(i = 0;i < oTime * 5; i++)
  {
    delay_ms(200); // 等待200ms,给串口中断留一些数据接收的时间
    siz = 0;
    memset(Receive,0,sizeof(Receive)); // 清空缓存数据
    siz = usart3_Receive((u8 *)Receive, sizeof(Receive)); // 接收串口数据
    if(siz <= 0) continue; 
    
    // 解析串口数据,如果接收到指定的字符了,则认为命令发送成功了
    // CC 01 00 01 00 07 01 00 CA
    if(Receive[0] == 0xCC && siz == 9)
    {
        // 发送AT命令
        printf("Recv:");
        for( i =0;i<siz;i++)
        {
          printf("%02X ", Receive[i]);
        }
        printf("\r\n");
        
        printf("Send Sever OK\r\n");
      // 我这里只对第一个字符做校验,其他的校验忽略。
      return 0;
    }
  }
  printf("Send Sever ERROR\r\n");
  return -1;
}
        
// GPS数据中提取坐标信息
int GetGpsLocation(char *data, int length, double *location)
{
    int i = 0, j = 0, a = 0, b = 0;
    char *p = NULL;
    char gnrmc[700] = "";// 原始GNRMC字符串
    char temp[12][15]={0,0}; // 保存解析到分割数据
    
    if(data == NULL || sizeof(data) == 0)
      
    printf("[%s]\r\n", data); //打印一下我们接收到的字符串
    
    // $GNRMC,112119.000,A,2559.8845,N,11921.6583,E,1.324,159.42,280922,,,A * 4F
    //我们GPS初始化的时候,定义的是GPS+BD模式,所以我们需要在 $GNRMC 里面提取出我们的坐标数据
    p = strstr(data,"$GNRMC");
    if(p == NULL)
      return -1; // 没找到我们需要的字符串
    while((p- data <= length))
    {
        gnrmc[i] = *p;
        if(gnrmc[i] == '\n')
        {
           gnrmc[i+1] = '\0';
          break;
        }
        p++;
        i++;
    }

    //时间、经纬度
    if((p = strstr(gnrmc,"$GNRMC")) != 0)
    {   
        p+=6;
        for(j = 0;j<12;j++)
        {
            p++;
            i = 0;
            while((*p != ',') && (*p != '*')){ 
              if(*p == '\0'){ j = 12; break;}
              temp[j][i++] = *(p++);  
            }
        }
    }

    if(temp[1][0] != 'A') //定位失败 
    {
        printf("定位失败!\r\n");
        return -1;
    }

    location[0] = str_to_dou(temp[2]);
    location[1] = str_to_dou(temp[4]);
    a = (int)(location[0]/100.0);
    b = (int)(location[1]/100.0);
    location[0] = a + (location[0] / 100.0 - a) * 100.0 / 60.0;// 纬度
    location[1] = b + (location[1] / 100.0 - b) * 100.0 / 60.0;// 经度
    
    // 将GPS坐标转换成百度坐标
    wgs2bd(location[0],location[1], &location[0], &location[1]); 
    
    printf("定位成功:%s,%s\r\n",temp[2], temp[4]);
    return 0;
}

// 发送坐标信息
void SendLocation(int user, double *location)
{
  // 拼装命令
  char oData[255] = {0};
  int ret = 0;
  long a = 0, b = 0;
  oData[ret++] = 0xCC; // 网络识别码
  oData[ret++] = 0x01; // 设备类型
  oData[ret++] = 0x00; // 设备号H
  oData[ret++] = 0x01; // 设备号L
  if(PackNum > 1000) PackNum = 0;
  oData[ret++] = (PackNum >> 8);     //  包号H
  oData[ret++] = (PackNum & 0x00FF); //  包号L
  oData[ret++] = 0x11; // 功能码
  // 用户ID 
  oData[ret++] = (user >> 8);     //  用户ID H
  oData[ret++] = (user & 0x00FF); //  用户ID L

  // 经度
  a = (long)(location[1] * 100000);
  oData[ret++] = ((a >> 24) & 0x000000FF);
  oData[ret++] = ((a >> 16) & 0x000000FF);
  oData[ret++] = ((a >> 8) & 0x000000FF);
  oData[ret++] = (a & 0x000000FF);

  // 纬度
  b = (long)(location[0] * 100000);
  oData[ret++] = ((b >> 24) & 0x000000FF);
  oData[ret++] = ((b >> 16) & 0x000000FF);
  oData[ret++] = ((b >> 8) & 0x000000FF);
  oData[ret++] = (b & 0x000000FF);

  // 校验
  oData[ret++] = (char)GetSum((u8 *)oData, ret);
  
  // 上传命令,应该走的是GPRS网络,等待可以久点,我这里是5秒
  SendServer(oData, ret, 5);
}

int main(void)
{    
  char GpsBuff[1000]="";
  double location[2]={0};
  int siz = 0;
  delay_init();//延时函数初始化
  usart2_Configuration(115200); // Printf的输出口(本来是打算用usart1来做打印接口的,但是我的板子usart1好像坏了。。。。)
  
  // 经过测试,GPS单次数据包大约有228个字节,我这里直接在.h文件中给串口2开辟300字节的缓存空间
  // A9G虽然有个独立的GPS输出口,但是在开启GPS定位时,AT命令口GPS口都会同时输出定位信息,这搞的GPS口很鸡肋。
  usart3_Configuration(115200); // GPRS、GPS
  
  // 串口测试用,将 A9G-USART 输出的数据直接透传到USART2口
  //  while(1)
  //  {
  //    delay_ms(500);
  //    siz = 0;
  //    memset(GpsBuff,0,sizeof(GpsBuff)); 
  //    siz = usart3_Receive((u8 *)GpsBuff, sizeof(GpsBuff)); 
  //    if(siz <= 0) continue; 
  //    
  //    usart2_Send((u8 *)GpsBuff, siz);
  //  }
  
  // 输出一些日志信息,方便调试
  printf("等待GPS设备启动完成...\r\n");
  // 等待GPS启动完成
  A9G_Start();  
  
  // 初始化GPS,但是先别启动GPS,因为我们后面还需要初始化GPRS
  printf("初始化GPS...\r\n");
  A9G_Init_GPS();
  printf("初始化GPS完成!\r\n");
  
  // 初始化GPRS,采用透传模式上传我们的数据,初始化完成之后,先别开起来。
  printf("初始化GPRS...\r\n");
  A9G_Init_GPRS("103.46.128.21", "39343");
  printf("初始化GPRS完成!\r\n");
    
  usart3_FreeBuff(); // 把之前残留的垃圾清理掉
  A9G_Start_GPS();   // 启动GPS
      
  // 开始采集
  while(1)
  {
    // 延时等待一下,反正也不需要那么快上报
    delay_ms(500);
        
    // 清理一下缓存
    siz = 0;
    memset(GpsBuff,0,sizeof(GpsBuff));
    siz = usart3_Receive((u8 *)GpsBuff, sizeof(GpsBuff));
    if(siz == 0) continue;
    
    // 提取GPS坐标,如果提取成功,说明定位成功了
    memset(location,0,sizeof(location));
    if(GetGpsLocation(GpsBuff, siz, location) == -1)
    {
      // 定位失败
      continue;
    }

    // 停止GPS
    A9G_Stop_GPS();

    // 启动GPRS 
    A9G_Start_GPRS();
    
    // 发送GPS坐标,用户的ID是2
    SendLocation(2, location);
    
    // 停止GPRS
    A9G_Stop_GPRS();
    
    // 启动GPS
    A9G_Start_GPS();
  }
}