Linux 串口编程之GPS

30 篇文章 10 订阅

       对于条件表达式b ? x : y,先计算条件b,然后进行判断。如果b的值为true,计算x的值,运算结果为x的值;否则,计算y的值,运算结果为y的值 .  

       之前编写了一个读取GPS内容的代码,现将之贴出来。此代码中涉及到串口初始化、串口操作的打开、关闭、读写,还涉及到GPS相关协议的解析,如接收到的GPS数据如何处理,如何发送数据到GPS模块等。协议采用的是SIM68VB   NMEA协议。

  1、 串口初始化代码如下:

   此函数为设置串口 属性如波特率、数据位、校验位、停止位,此函数将串口设置为非阻塞,在读串口时可采用I/O多路复用的机制。

例:configs ="115200,8,1,N" 115200代表波特率,8数据位,1停止位,N无校验

int SetNolockComCfg(int fd, char *configs)
{
    int uBaudRate, databits, stopbits;
    char parity;
    char temp[32];
    char *p1 = NULL, *p2 = NULL;
    int n = 0;
    unsigned int flag = 0;
    unsigned short Speed;
    int stats;
    struct termios options;

    /* clear struct for new port settings */
    bzero(&options, sizeof (struct termios));

    //波特率
    p1 = configs;
    p2 = strchr(p1, ',');
    n = p2 - p1;
    if (n) {
        strncpy(temp, p1, n);
        temp[n] = '\0';
        uBaudRate = atoi(temp);
    }
    else
        uBaudRate = COM_BAUDDEF;

    //数据位
    p1 = strchr(p2 + 1, ',');
    n = p1 - (p2 + 1);
    if (n) {
        strncpy(temp, p2 + 1, n);
        temp[n] = '\0';
        databits = atoi(temp);
    }
    else
        databits = COM_DABITSDEF;

    // 停止位
    p2 = strchr(p1 + 1, ',');
    n = p2 - (p1 + 1);
    if (n) {
        strncpy(temp, p1 + 1, n);
        temp[n] = '\0';
        stopbits = atoi(temp);
    }
    else
        stopbits = COM_STBITSDEF;

    //校验位
    if (p2 + 1 != NULL) {
        strcpy(temp, p2 + 1);
        parity = temp[0];
    }
    else {
        parity = COM_PARITYDEF;
    }

    //设置波特率
    switch (uBaudRate) {
    case 110:
        Speed = B110;
        break;

    case 300:
        Speed = B300;
        break;

    case 600:
        Speed = B600;
        break;

    case 1200:
        Speed = B1200;
        break;

    case 2400:
        Speed = B2400;
        break;

    case 4800:
        Speed = B4800;
        break;

    case 9600:
        Speed = B9600;
        break;

    case 19200:
        Speed = B19200;
        break;

    case 38400:
        Speed = B38400;
        break;

    case 57600:
        Speed = B57600;
        break;

    case 115200:
        Speed = B115200;
        break;

    case 230400:
        Speed = B230400;
        break;

    case 460800:
        Speed = B460800;
        break;

    case 921600:
        Speed = B921600;
        break;

    default:
        fprintf(stderr, "Unsupported data size\n");
        return -1;
    }

    flag |= Speed;

    //设置数据位
    switch (databits) {
    case 5:
        flag |= CS5;
        break;

    case 6:
        flag |= CS6;
        break;

    case 7:
        flag |= CS7;
        break;

    case 8:
        flag |= CS8;
        break;

    default:
        fprintf(stderr, "Unsupported data size\n");
        return -1;

    }

    //设置停止位
    switch (stopbits) {
    case 1:
        break;

    case 2:
        flag |= CSTOPB;
        break;

    default:
        fprintf(stderr, "Unsupported stop bits\n");
        return -1;

    }

    //设置奇偶校验位
    switch (parity) {
    case 'n':
    case 'N':
        options.c_iflag = IGNPAR;
        break;

    case 'e':
    case 'E':
        flag |= PARENB;
        options.c_iflag = 0;
        break;

    case 'o':
    case 'O':
        flag |= PARENB | PARODD;
        options.c_iflag = 0;
        break;

    case 's':
    case 'S':
        flag |= PARENB | CMSPAR;
        options.c_iflag = 0;
        break;

    case 'm':
    case 'M':
        flag |= PARENB | PARODD | CMSPAR;
        options.c_iflag = 0;
        break;

    default:
        fprintf(stderr, "Unsupported parity\n");
        return -1;

    }

    options.c_cflag = flag | CREAD | CLOCAL;
    options.c_oflag = 0;
    options.c_lflag = 0;
    options.c_cc[VINTR] = 0;
    options.c_cc[VQUIT] = 0;
    options.c_cc[VERASE] = 0;
    options.c_cc[VKILL] = 0;
    options.c_cc[VEOF] = 4;
    // 100MS 串口等待接收(2S)
    options.c_cc[VTIME] = 0; 
    options.c_cc[VMIN] = 0;
    options.c_cc[VSWTC] = 0;
    options.c_cc[VSTART] = 0;
    options.c_cc[VSTOP] = 0;
    options.c_cc[VSUSP] = 0;
    options.c_cc[VEOL] = 0;
    options.c_cc[VREPRINT] = 0;
    options.c_cc[VDISCARD] = 0;
    options.c_cc[VWERASE] = 0;
    options.c_cc[VLNEXT] = 0;
    options.c_cc[VEOL2] = 0;

    //刷新输入输出缓冲
    tcflush(fd, TCIOFLUSH);

    //把设置真正写到串口中去
    stats = tcsetattr(fd, TCSANOW, &options);

    if (stats != 0) {
        perror("tcsetattr fd1");
        return -1;

    }

    return 0;
}
2、GPS相关的数据定义在一个结构体中,如下


struct    stGPS {
    //位置信息有效性
    char            loca_state;   
    //东西经
    char            we;            
    //经度位置
    unsigned int    Longitude;
    //南北纬
    char            ns;    
    //纬度位置
    unsigned int    Latitude;        
    //海拔高度
    unsigned int    Altitude;    
    //距1970-1-1 0:0:0 的秒数
    unsigned int    Time;            
};

3、获取GPS信息的函数如下

相关宏:
#define        GPGGA        "$GPGGA"    //GPS定位系统输出字符串的头部
#define        GPRMC        "$GPRMC"
#define        BDGGA        "$BDGGA"    //北斗定位系统输出字符串的头部
#define        BDRMC        "$BDRMC"
 

int GetBDGPSData(int    bdgps_fd, struct  stGPS    *bdgps, int mode)
{
    int     ret;
    char    read_buf[512] = {0};
    char     *pGGA = NULL, *pRMC = NULL;
    char     gpstime[64] = {0};
    char    altitude[64] = {0};
    char    ns;       //纬度标识
    char    we;        //经度标识
    char    state;    //状态标识
    char    ns_data[16] = {0};  //纬度
    char    we_data[16] = {0};    //经度
    char     date[16] = {0};
    struct    tm     utc_time = {0};    
    int     year;
    int     daytime;
    int     err_num;
    int        flag = 0;
    char     str1[10] = {0};
    char     str2[10] = {0};
    
    switch (mode){
        case    BD_MODE:
            memcpy(str1, BDGGA, sizeof(BDGGA));
            memcpy(str2, BDRMC, sizeof(BDRMC));
            break;
        case    GPS_MODE:
        default:
            memcpy(str1, GPGGA, sizeof(GPGGA));
            memcpy(str2, GPRMC, sizeof(GPRMC));
            break;
    }
    
    for(err_num=0; err_num<MAX_ERROR; err_num++){
        delay(0, 100);
        ret = read(bdgps_fd, read_buf, sizeof(read_buf));
        pGGA = strstr(read_buf,str1);  //在字符串中查找字符串
        pRMC = strstr(read_buf,str2);
        if((ret>150) && pGGA && pRMC){
            flag = 1;
            break;
        }
    }
    if(!flag)
        return -1;
    
    printf("read num = %d \nread_buf: %s \n", ret, read_buf);

   //根据需求我们需要采集到两次信息

    sscanf(pGGA, "%[^\r]", pGGA);     //解析字符串
    sscanf(pRMC, "%[^\r]", pRMC);
    

    //根据协议解析字符串
    sscanf(pGGA, "%*[^,],%*[^,],%*[^,],%*[^,],%*[^,],%*[^,],%*[^,],%*[^,],%*[^,],%[^,]",altitude); 
    //                      时间  状态   纬度  ns    经度  we    
    sscanf(pRMC, "%*[^,],%[^,],%c, %[^,],%c,%[^,],%c,%*[^,],%*[^,],%[^,]",
                    gpstime, &state , ns_data, &ns, we_data, &we,  date);
    year = atoi(date);
    daytime = atoi(gpstime);
    
    utc_time.tm_sec   = daytime%100;
    utc_time.tm_min   = daytime%10000/100 ;
    utc_time.tm_hour  = daytime/10000;
    utc_time.tm_mday  = year/10000;
    utc_time.tm_mon   = year%10000/100;
    utc_time.tm_year  = year%100 + 2000;
    
    bdgps->Longitude  = atof(we_data) * 10000;
    bdgps->Latitude   = atof(ns_data) * 10000;
    bdgps->loca_state = state;
    bdgps->Altitude      = atof(altitude) * 10000;
    bdgps->ns          = ns;
    bdgps->we          = we;
    bdgps->Time       = mktime(&utc_time);
    
    return 0;
}

4、 main函数,采用select机制读取GPS串口的数据
int main()
{
    int        ret = 0;
    fd_set    readfs;
    int     bdgps_fd, maxfd;
    int     err_num = 0;
    
    struct    stGPS    bdgps = {0};
    struct  timeval timeout={1, 0}; 
    
    bdgps_fd = open("/dev/ttyS1", O_RDWR);
    if(bdgps_fd < 0){
        perror("open ttyS1");
        return -1;
    }
    
    //设置为非阻塞
    ret = SetNolockComCfg(bdgps_fd, CONFIG);
    if(ret)
        return -1;
    
    while(1){
        FD_ZERO(&readfs);
        FD_SET(bdgps_fd, &readfs);
        maxfd = bdgps_fd + 1;
        ret = select(maxfd, &readfs, NULL, NULL, &timeout);
        if(ret < 0){
            perror("select");   //允许出错三次
            err_num++;
            if(err_num < MAX_ERROR)
                continue;
            else
                break;
        }
        err_num = 0;
        
        if(FD_ISSET(bdgps_fd, &readfs)){            
            ret = GetBDGPSData(bdgps_fd, &bdgps, GPS_MODE);
            if(ret)
                continue;
            
            printf("bdgps->state:    %c \n",bdgps.loca_state);
            printf("bdgps->we:       %c \n",bdgps.we);
            printf("bdgps->Longitude:%d \n",bdgps.Longitude);
            printf("bdgps->ns:       %c \n",bdgps.ns);
            printf("bdgps->Latitude: %d \n",bdgps.Latitude);
            printf("bdgps->Altitude: %d \n",bdgps.Altitude);
            printf("bdgps->Time:      %d \n",bdgps.Time);    
        }
        usleep(50*1000);
    }
    close(bdgps_fd);
    
    return 0;
    
}

至此,一个完整的GPS读取数据的程序已经完成,已经能够读取到相关的位置信息。

  
---------------------
作者:hellohkm
来源:CSDN
原文:https://blog.csdn.net/weixin_42218802/article/details/81122795
版权声明:本文为作者原创文章,转载请附上博文链接!
内容解析By:CSDN,CNBLOG博客文章一键转载插件

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
GPS应用程序设计》源代码。本软件是专为《GPS应用程序设计》一书配套发行的。包括: 1、 data_log.c 数据采集程序 2、 rinexout.c RINEX数据格式写入子程序 3、 to_rinex.c 数据格式转换 4、 sav_pos.c 卫星位置计算程序 5、 sky_sav.c 卫星天空显示程序 6、 dop_calc.c 卫星星座DOP计算程序 7、 view_sav.c 历书预报卫星出现程序 8、 absl_pos.c 单点绝对定位程序 9、 ssgsoft.c -- 相对静态定位主程序 10、 controlf.c ? 读取输入文件子程序 11、 orbit.c -- 选择参考卫星子程序 12、 broad.c -- 读广播星历计算子程序 13、 igs.c -- 读 IGS 精密星历子程序 14、 singlep.c -- 近似位置计算子程序 15、 rinex.c -- 读 Rinex 数据、探测跳周、组成单差子程序 16、 eqdd_s.c -- 组成双差方程子程序 17、 normdd_s.c ? 组成法方差子程序 18、 ad_core.c -- 平差子程序19、 ambifix.c -- 模糊度固定子程序 20、 tranf.c -- 坐标变换子程序 21、 dgps_ppr. 相位平滑伪距改正数计算程序 22、 dgps_phr 准载波相位改正数计算程序 23 rtcmencd.c RTCM 电文编码程序 24 rtcmencd.c RTCM 电文译码程序 25、 net_dgn.c 测量格网设计程序 26 sur_ctr.c 动态测量控制程序 27、 replay.c 动态测量数据回放程序 28、 kin_tran.c 动态定位坐标转换程序 29、 rms.c 定位精度估计程序 30、 tide.c 潮位改正程序 31、 xybl_54.c 54坐标变换程序 32、 xyxy_loc.c 任意坐标系转换程序 33、 gga+gsv.c GGA和GSV数据模拟程序 34、 depth.c 水深数据模拟程序 35、 gg_pos.c GPS+GLONASS导航程序 36、 menu1.c DOS环境换页式菜单程序 37、 menu2.c DOS环境下拉式菜单程序 38、 menu3.c windows95环境下拉式多层界面菜单程序 39、 makedata.c 利用RINEX格式文件data.98n和data.98o形成的data.out文件,供计算单点定位用

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值