使用串口读取GPS模块数据
这两天由于把电脑充电器落在家里了,自己的电脑无法工作了,所以使用会比较拖拉了,还望坛友多多包涵。下面是上周五的工作,使用orangepi zero读取GPS模块传回来的数据,由于是在室内,GPS无法输出有效数据,不过这次只是串口读取实验,下次实验再进行串口数据解析。
参考文章:
http://blog.chinaunix.net/uid-28458801-id-4243864.html
http://www.cnblogs.com/wblyuyang/archive/2011/11/21/2257544.html
和其他设备一样,Linux也是通过设备文件来提供访问串口的功能。当需要访问串口的时候,你只需要open相应的文件。Linux系统上一般有一个或者多个串口,一般串口设备在dev文件夹中的名称为ttyS0、ttyS1之类的,S表示的是Serial的意思。使用系统调用open函数打开对应的串口设备之后就可以进行读写操作,但是在读写操作之前还需要进行串口的设置,否则使用的是默认的串口配置。配置的方法下面将会介绍。
打开串口连接的时候,程序在open函数中除了Read+Write模式以外还指定了两个选项;
fd = open(“/dev/ttyS0”, O_RDWR | O_NOCTTY | O_NDELAY);
标志O_NOCTTY可以告诉UNIX这个程序不会成为这个端口上的“控制终端”。如果不这样做的话,所有的输入,比如键盘上过来的Ctrl+C中止信号等等,会影响到你的进程。而有些程序比如getty(1M/8)则会在打开登录进程的时候使用这个特性,但是通常情况下,用户程序不会使用这个行为。
O_NDELAY标志则是告诉UNIX,这个程序并不关心DCD信号线的状态——也就是不关心端口另一端是否已经连接。如果不指定这个标志的话,除非DCD信号线上有space电压否则这个程序会一直睡眠。
打开串口设备之后要做的第一步工作就是配置串口的参数例如波特率、数据位长度、停止位数量、流控等等。很多系统都支持POSIX终端(串口)接口。程序可以利用这个接口来改变终端的参数,与串口操作相关的最重要的两个POSIX函数可能就是tcgetattr(3)和tcsetattr(3)。顾名思义,这两个函数分别用来取得设设置终端的属性。调用这两个函数的时候,你需要提供一个包含着所有串口选项的termios结构体:
struct termios { tcflag_t c_iflag; //input flags tcflag_t c_oflag; //output flags tcflag_t c_cflag; //control flags tcflag_t c_lflag; //local flags cc_t c_cc[NCCS]; //control characters };- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
串口配置流程
1>保存原先串口配置,用tcgetattr(fd,&oldtio)函数
struct termios newtio,oldtio;
tcgetattr(fd,&oldtio);
2>激活选项有CLOCAL和CREAD,用于本地连接和接收使用
newtio.c_cflag | = CLOCAL | CREAD;
3>设置波特率,使用函数cfsetispeed、cfsetospeed
cfsetispeed(&newtio,B115200);
cfsetospeed(&newtio,B115200);
4>设置数据位,需使用掩码设置
newtio.c_cflag &= ~CSIZE;
newtio.c_cflag |= CS8;
5>设置奇偶校验位,使用c_cflag和c_iflag.
设置奇校验:
newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
newtio.c_iflag |= (INPCK | ISTRIP);
设置偶校验:
newtio.c_iflag |= (INPCK|ISTRIP);
newtio.c_cflag |= PARENB;
newtio.c_cflag |= ~PARODD;
6>设置停止位,通过激活c_cflag中的CSTOPB实现。若停止位为1,则清除CSTOPB,若停止位为2,则激活CSTOPB。
newtio.c_cflag &= ~CSTOPB;
7>设置最少字符和等待时间,对于接收字符和等待时间没有特别的要求时,可设为0:
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 0;
8>处理要写入的引用对象,tcflush函数刷新(抛弃)输入缓存(终端驱动程序已接收到,但用户程序尚未读)或输出缓存(用户程序已经写,但尚未发送).
int tcflush(int filedes,int quene)
quene数应当是下列三个常数之一:
*TCIFLUSH 刷清输入队列
*TCOFLUSH 刷清输出队列
*TCIOFLUSH 刷清输入、输出队列
例如:tcflush(fd,TCIFLUSH);
9>激活配置。在完成配置后,需要激活配置使其生效。使用tcsetattr()函数:
int tcsetattr(int filedes,int opt,const struct termios *termptr);
opt使我们可以指定在什么时候新的终端属性才起作用,
*TCSANOW:更改立即发生
*TCSADRAIN:发送了所有输出后更改才发生。若更改输出参数则应使用此选项
*TCSAFLUSH:发送了所有输出后更改才发生。更进一步,在更改发生时未读的
所有输入数据都被删除(刷清).
例如: tcsetattr(fd,TCSANOW,&newtio);
写数据到串口时使用write函数例如:
n = write(fd, “tangquan\r\n”, 10);
表示写10个字节的数据到文件描述符fd描述的文件中去。从串口上读取数据时使用read函数:
len = read(fd,buff,100);
需要注意read函数是否为阻塞函数,如果需要可以设置为非阻塞读方式。
下面是我使用orangepi zero对GPS模块的读取程序,没有数据解析,只有读取功能,解析在之后的试用过程中发出来。
- #include <stdio.h>
- #include <string.h>
- #include <sys/types.h>
- #include <errno.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <termios.h>
- #include <stdlib.h>
- int main(int argc, char *argv[])
- {
- int fd = open("/dev/ttyS1", O_RDWR | O_NOCTTY | O_NDELAY);
-
- struct termios newtio,oldtio;
- tcgetattr(fd,&oldtio);
-
- newtio.c_cflag |= (CLOCAL | CREAD);
- cfsetispeed(&newtio,B38400);
- cfsetospeed(&newtio,B38400);
- newtio.c_cflag &= ~CSIZE;
- newtio.c_cflag |= CS8;
- newtio.c_cflag &= ~PARENB;
- newtio.c_cflag &= ~CSTOPB;
- newtio.c_cflag &= ~CSIZE;
- newtio.c_cflag |= CS8;
- newtio.c_cflag &= ~CSTOPB;
- newtio.c_cc[VTIME] = 0;
- newtio.c_cc[VMIN] = 0;
- tcsetattr(fd,TCSANOW,&newtio);
由于我的电脑没电了,运行结果截不出来,但是之间把结果复制下来了,这里贴出来:
- $GPRMC,,V,,,,,,,,,,N*53
- $GPVTG,,,,,,,,,N*30
- $GPGGA,,,,,,0,00,99.99,,,,,,*48
- $GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30
- $GPGSV,1,1,00*79
- $GPGLL,,,,,,V,N*64
具体的GPS字段含义可以参看我的CSDN文章:http://blog.csdn.net/tq384998430/article/details/53669784
审核真的需要这么久么?
不错的资料 学习了