|
最近要做个LINUX下串口控制的程序,对LINUX不熟悉,参看了Serial Programming HOWTO以后,在自己机子上实验了上面的程序,发现读不到数据,从网上DOWN了别人的代码还是读不到。一到读数据的时候就会阻塞。我是在WINXP下用的虚拟机虚拟REDHAT 9.0,因为只有一个串口,所以我是把2 3脚对接来做实验的。另外我有台56K的外猫,在WIN下可以被识别,但是到LINUX下我用minicom 设置了波特率,数据位长以后minicom 并没有显示OK,也没有MODEM的初始数据。LINUX下,串口是不是要被设置才能用?或者是因为别的什么错误,请指点一下。很急。
下面是Serial Programming HOWTO中的例子,里面的write是我加上去的,我机子上读不到数据。
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
#define BAUDRATE B38400
// 定义您所需要的串口号
#define MODEMDEVICE "/dev/ttyS1"
#define _POSIX_SOURCE 1 /*POSIX compliant source POSIX系统兼容*/
#define FALSE 0
#define TRUE 1
volatile int STOP=FALSE;
main() {
int fd,c, res;
struct termios oldtio,newtio;
char buf[255];
int n;
开启设备用于读写,但是不要以控制 tty 的模式,因为我们并不希望在发送 Ctrl-C
后结束此进程
*/
fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY );
if (fd <0) {perror(MODEMDEVICE); exit(-1); }
tcgetattr(fd,&oldtio);
// 储存当前的串口设置
bzero(&newtio, sizeof(newtio));
// 清空新的串口设置结构体
/*BAUDRATE: 设置串口的传输速率bps, 也可以使用 cfsetispeed 和 cfsetospeed 来设置
CRTSCTS : 输出硬件流控(只能在具完整线路的缆线下工作,参考 Serial-HOWTO 第七节)
CS8 : 8n1 (每一帧8比特数据,无奇偶校验位,1 比特停止位)
CLOCAL : 本地连接,无调制解调器控制
CREAD : 允许接收数据
*/
newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
/* IGNPAR : 忽略奇偶校验出错的字节
ICRNL : 把 CR 映像成 NL (否则从其它机器传来的 CR 无法终止输入)或者就把设备设
为 raw 状态(没有额外的输入处理)*/
newtio.c_iflag = IGNPAR | ICRNL;
/*
Raw 模式输出
*/
newtio.c_oflag = 0;
/*
ICANON : 启动 标准输出, 关闭所有回显echo 功能,不向程序发送信号
*/
newtio.c_lflag = ICANON;
/*
初始化所有的控制字符, 默认值可以在 /usr/include/termios.h 找到,
并且做了注解,不过这里我们并不需要考虑这些
*/
newtio.c_cc[VINTR] = 0; /* Ctrl-c */
newtio.c_cc[VQUIT] = 0; /* Ctrl-\ */
newtio.c_cc[VERASE] = 0; /* del */
newtio.c_cc[VKILL] = 0; /* @ */
newtio.c_cc[VEOF] = 4; /* Ctrl-d */
newtio.c_cc[VTIME] = 0; /* inter-character timer unused */
/* 不使用字符间的计时器 */
newtio.c_cc[VMIN] = 1; /* blocking read until 1 character arrives */
/* 阻塞,直到读取到一个字符 */
newtio.c_cc[VSWTC] = 0; /* ''''\0'''' */
newtio.c_cc[VSTART] = 0; /* Ctrl-q */
newtio.c_cc[VSTOP] = 0; /* Ctrl-s */
newtio.c_cc[VSUSP] = 0; /* Ctrl-z */
newtio.c_cc[VEOL] = 0; /* ''''\0'''' */
newtio.c_cc[VREPRINT] = 0; /* Ctrl-r */
newtio.c_cc[VDISCARD] = 0; /* Ctrl-u */
newtio.c_cc[VWERASE] = 0; /* Ctrl-w */
newtio.c_cc[VLNEXT] = 0; /* Ctrl-v */
newtio.c_cc[VEOL2] = 0; /* ''''\0'''' */
/*
清空数据线,启动新的串口设置
*/
tcflush(fd, TCIFLUSH);
tcsetattr(fd,TCSANOW,&newtio);
/*
终端设置完成,现在就可以处理数据了
在本程序中,在一行的开始输入一个 ''''z'''' 会终止该程序
*/
n = write(fd, "ABCD\r", 5);
if( n < 0 )
{
printf("write failed");
exit(-1);
}
while (STOP==FALSE) { /*
// 循环直到满足终止条件
即使输入超过 255 个字节,读取的程序段还是会一直等到行结束符出现才会停止。
如果读到的字符少于应刚获得的字符数,则剩下的字符串会在下一次读取时读到。
res 用来获得每次真正读到的字节数
*/
res = read(fd,buf,255);
buf[res]=0; // 设置字符串结束符,从而可以顺利使用 printf
printf(":%s:%d\n", buf, res);
if (buf[0]==''''z'''') STOP=TRUE;
}
/* restore the old port settings 恢复旧的串口设置 */
tcsetattr(fd,TCSANOW,&oldtio);
} |
|