您的位置:首页 > 运维架构 > Linux

转载_Linux下串口编程

2013-03-01 17:06 429 查看
一.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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: