一.termios相关的操作,termios是在计算机使用初期,linux提供对串口操作的支持的接口
1总览:
#include <termios.h>
#include <unistd.h>
int tcgetattr(int fd, struct termios *termios_p);//获取当前对串口设置的参数
int tcsetattr(int fd, int optional_actions, struct termios *termios_p);//用已经配置好的参数设置串口
int tcsendbreak(int fd, int duration);
int tcdrain(int fd);
int tcflush(int fd, int queue_selector);//刷新数据缓存去
int tcflow(int fd, int action);
int cfmakeraw(struct termios *termios_p);
speed_t cfgetispeed(struct termios *termios_p);//获取当前串口的输出波特率
speed_t cfgetospeed(struct termios *termios_p);//获取当前串口的输入波特率
int cfsetispeed(struct termios *termios_p, speed_t speed);//设置串口输出的波特率
int cfsetospeed(struct termios *termios_p, speed_t speed);//设置串口输入的波特率
2数据结构:
tcflag_t c_iflag; /* 输入模式 */
tcflag_t c_oflag; /* 输出模式 */
tcflag_t c_cflag; /* 控制模式 */
tcflag_t c_lflag; /* 本地模式 */
cc_t c_cc[NCCS]; /* 控制字符 */
二.对串口设置的实现流程:
1.保存以前对串口的设置:
使用tcgetattr()
2.激活串口
设置c_cflag的CLOCAL和CREAD标记位
3.设置波特率:
使用cfsetispeed()设置输入的波特率
使用cfsetospeed()设置输出的波特率
4.设置数据位:
设置c_cflag的~CSIZE和CS8的标记位
5.设置奇偶校验:
如果设置为奇校验,需要设置的标记位如下:
c_cflag的PARENB和PARODD
c_iflag的INPCK和ISTRIP
如果设置为偶校验,需要设置的标记位如下:
c_cflag的PARENB和~PARODD
c_iflag的INPCK和ISTRIP
6.设置停止位:
一位停止位:
c_cflag设置为~CSTOPB
两位停止位
c_cflag设置为CSTOPB
7.设置最少等待时间和最小字符:
c_cc[VIME]=0;
c_cc[VMIN]=0;
8.处理要写入的对象:
tcflush()
这里面有三个参数要注意:
TCIFLUSH 刷新输入队列
TCOFLUSH 刷新输出队列
TCIOFLUSH 刷新输入输出队列
9.激活配置:
tcgetattr();获取设置好的参数
tcsetattr();设置并且激活对串口的配置
这里面有三个参数要注意:
TCSANOW 更改立即发生
TCSADRAIN 发送了所有的输出后更改才发生,若更改输出参数应该使用这个选项
TCSAFLUSH 发送了所有的输出后更改才发生,在更改发生时未读的所有数据都删除
三.对串口的操作:
1.打开串口设备:
fd = open("/dev/ttyS0",O_RDWR|O_NOCTTY|O_NDELAY)
O_NOCTTY:通知linux系统,这个程序不会成为这个端口的控制终端
O_NDELAY:通知linux系统不关心DCD信号线所处的状态(DCD信号线用以检测串口线另一端是否有设备连接)
2.串口的读和写:
read(fd,buff,8);
write(fd,buff,8);
四.经测试可用的源代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <string.h>
#define TRUE 1
//初始化串口选项:
void setTermios(struct termios * pNewtio, int uBaudRate)
{
bzero(pNewtio, sizeof(struct termios));
//8N1
pNewtio->c_cflag = uBaudRate | CS8 | CREAD | CLOCAL;
pNewtio->c_iflag = IGNPAR;
pNewtio->c_oflag = 0;
pNewtio->c_lflag = 0;
pNewtio->c_cc[VINTR] = 0; /* Ctrl-c */
pNewtio->c_cc[VQUIT] = 0; /* Ctrl-/ */
pNewtio->c_cc[VERASE] = 0; /* del */
pNewtio->c_cc[VKILL] = 0; /* @ */
pNewtio->c_cc[VEOF] = 4; /* Ctrl-d */
pNewtio->c_cc[VTIME] = 5; /* inter-character timer, timeout VTIME*0.1 */
pNewtio->c_cc[VMIN] = 0; /* blocking read until VMIN character arrives */
pNewtio->c_cc[VSWTC] = 0; /* '/0' */
pNewtio->c_cc[VSTART] = 0; /* Ctrl-q */
pNewtio->c_cc[VSTOP] = 0; /* Ctrl-s */
pNewtio->c_cc[VSUSP] = 0; /* Ctrl-z */
pNewtio->c_cc[VEOL] = 0; /* '/0' */
pNewtio->c_cc[VREPRINT] = 0; /* Ctrl-r */
pNewtio->c_cc[VDISCARD] = 0; /* Ctrl-u */
pNewtio->c_cc[VWERASE] = 0; /* Ctrl-w */
pNewtio->c_cc[VLNEXT] = 0; /* Ctrl-v */
pNewtio->c_cc[VEOL2] = 0; /* '/0' */
}
#define BUFSIZE 512
int main(int argc, char **argv)
{
int fd;
int nread;
char buff[BUFSIZE];
struct termios oldtio, newtio;
struct timeval tv;
char *dev ="/dev/ttyS0";
fd_set rfds;
if ((fd = open(dev, O_RDWR | O_NOCTTY))<0)
{
printf("err: can't open serial port!/n");
return -1;
}
tcgetattr(fd, &oldtio); /* save current serial port settings */
setTermios(&newtio, B9600);
tcflush(fd, TCIFLUSH);
tcsetattr(fd, TCSANOW, &newtio);
tv.tv_sec=30;
tv.tv_usec=0;
while (TRUE)
{
printf("wait.../n");
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
if (select(1+fd, &rfds, NULL, NULL, &tv)>0)
{
if (FD_ISSET(fd, &rfds))
{
nread=read(fd, buff, BUFSIZE);
printf("readlength=%d/n", nread);
buff[nread]='/0';
printf("%d/n", buff[6]);
}
}
}
tcsetattr(fd, TCSANOW, &oldtio);
close(fd);
}