快要吐血了,一个linux的串口问题,发现接收数据有错误,不知是那里的设置错了。谢谢了啦
我用了下面的方法设置串口,不知是什么原因,接收到的数据会偶有一些不规律的错误,而我在windows下做的串口则很准确.说明硬件设备没有问题,问题出在串口上.
我的系统是red hat linux9.0
数据格式: 起始位+8位数据位+1位停止位 奇校验
波特率:4800b
都 愁死我了,我检查了好多次,都不知问题出在那,但就是linux有问题,windows下就好好的.同时我用的57600b对另一个设备也没有问题.
谢!!!
#include <termios.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include "iocom.h"
speed_t syscom_speed(int speednum) { //设定波特率
if (speednum >= 460800) return B460800;
if (speednum >= 230400) return B230400;
if (speednum >= 115200) return B115200;
if (speednum >= 57600) return B57600;
if (speednum >= 38400) return B38400;
if (speednum >= 19200) return B19200;
if (speednum >= 9600) return B9600;
if (speednum >= 4800) return B4800;
if (speednum >= 2400) return B2400;
if (speednum >= 1800) return B1800;
if (speednum >= 1200) return B1200;
if (speednum >= 600) return B600;
if (speednum >= 300) return B300;
if (speednum >= 200) return B200;
if (speednum >= 150) return B150;
if (speednum >= 134) return B134;
if (speednum >= 110) return B110;
if (speednum >= 75) return B75;
return B50;
}
int initusbcom(int _nucom,int speednum)
{
struct termios pts;
char comnu[12];
sprintf(comnu,"/dev/ttyS%d",_nucom);
int com;
com=open(comnu, O_RDWR);//打开串口
printf("%s\n",comnu);
if(com==-1)
{
printf("error !open fail %d\n",com);
}
tcgetattr(com,&pts);//取得串口termios
pts.c_lflag &= ~ICANON;//不启动档准模式
pts.c_lflag &= ~(ECHO|ECHOCTL|ECHONL);//不回显,不对字接收字符取模,不回显'\n'
// pts.c_cflag |= HUPCL;
pts.c_cc[VMIN] = 1;
pts.c_cc[VTIME] =0;
pts.c_oflag &= ~ONLCR;//发送时不改变字符
pts.c_cflag |= PARENB;//
pts.c_cflag |= PARODD;//这行和上一行设定校验为奇校验
pts.c_cflag &=~CSTOPB;//一位停止位
pts.c_cflag |=CREAD;//设定接收字符
pts.c_iflag |=IGNPAR;//忽略错误
pts.c_iflag |=INPCK;//进行奇偶校验
pts.c_iflag &= ~ICRNL;//不改变回车符
cfsetospeed(&pts,syscom_speed(speednum));//设定波特率
cfsetispeed(&pts,syscom_speed(speednum));
tcsetattr(com,TCSANOW,&pts);
printf("ok\n");
return com;
}
/*
main()
{
int com;
unsigned char strread;
com=initcom(0,4800);
while(1)
{
read(com,&strread,1);
printf("%d\n",strread);
}
};
*/
问题点数:0、回复次数:7Top
1 楼gdhyj(gdhyj)回复于 2005-04-02 13:01:31 得分 0
这一段广为流传的串口初始化代码大家都觉得不好使
试试这一段
tcgetattr(fd,&t);
bzero(&t,sizeof(t));
fcntl(fd,F_SETFL,0);
t.c_cflag |= CLOCAL | CREAD;
t.c_cflag &= ~PARENB;
t.c_cflag &= ~CSTOPB;
t.c_cflag &= ~CSIZE;
t.c_cflag |= CS8;
t.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
t.c_oflag &= ~OPOST;
t.c_cc[VMIN] = 0;
t.c_cc[VTIME] = 50;Top
2 楼flying520520(不老山)回复于 2005-04-03 21:03:07 得分 0
在等待
Top
3 楼yangyouyi(yangyouyi)回复于 2005-04-05 10:27:40 得分 0
linux是真正的分时,可能和这个有关系。你想,设备传动字符的时候并不是要等你读,他才传送。只要开始传送了,它就要一直传送到一个任务完成。可是在设备传送的过程中,你的while循环程序可能没有被分到时间片运行,所以你就丢了字符。你最好用中断的方式来读字符,这样不存在时间片的问题了。Top
4 楼flying520520(不老山)回复于 2005-04-06 13:24:48 得分 0
upTop
5 楼ssli(30岁的程序员)回复于 2005-04-06 13:41:29 得分 0
请参考如下代码,这是我的程序的一部分:
int speed_arr[] = {B230400, B115200, B38400, B19200, B9600, B4800, B2400, B1200, B300,
B115200, B38400, B19200, B9600, B4800, B2400, B1200, B300, };
int name_arr[] = {230400, 115200, 38400, 19200, 9600, 4800, 2400, 1200, 300,
115200, 38400, 19200, 9600, 4800, 2400, 1200, 300, };
void set_speed(int fd, int speed) //set com speed
{
int i;
int status;
struct termios Opt;
tcgetattr(fd, &Opt);
for ( i= 0; i < sizeof(speed_arr) / sizeof(int); i++)
{
if (speed == name_arr[i])
{
tcflush(fd, TCIOFLUSH);
cfsetispeed(&Opt, speed_arr[i]);
cfsetospeed(&Opt, speed_arr[i]);
status = tcsetattr(fd, TCSANOW, &Opt);
if (status != 0)
perror("tcsetattr fd1");
return;
}
tcflush(fd,TCIOFLUSH);
}
}
int set_Parity(int fd,int databits,int stopbits,int parity) //set com parity and other property
{
struct termios options;
if ( tcgetattr( fd,&options) != 0)
{
perror("SetupSerial 1");
return(FALSE);
}
options.c_cflag &= ~CSIZE;
switch (databits)
{
case 7:
options.c_cflag |= CS7;
break;
case 8:
options.c_cflag |= CS8;
break;
default:
fprintf(stderr,"Unsupported data size\n");
return (FALSE);
}
switch (parity)
{
case 'n':
case 'N':
options.c_cflag &= ~PARENB; /* Clear parity enable */
options.c_iflag &= ~INPCK; /* Enable parity checking */
break;
case 'o':
case 'O':
options.c_cflag |= (PARODD | PARENB);
options.c_iflag |= INPCK; /* Disnable parity checking */
break;
case 'e':
case 'E':
options.c_cflag |= PARENB; /* Enable parity */
options.c_cflag &= ~PARODD;
options.c_iflag |= INPCK; /* Disnable parity checking */
break;
case 'S':
case 's': /*as no parity*/
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
break;
default:
fprintf(stderr,"Unsupported parity\n");
return (FALSE);
}
switch (stopbits)
{
case 1:
options.c_cflag &= ~CSTOPB;
break;
case 2:
options.c_cflag |= CSTOPB;
break;
default:
fprintf(stderr,"Unsupported stop bits\n");
return (FALSE);
}
/* Set input parity option */
if (parity != 'n')
options.c_iflag |= INPCK;
options.c_lflag = 0;
options.c_oflag = 0;
options.c_oflag |= OPOST;
options.c_cflag |= CLOCAL | CREAD;
options.c_cc[VTIME] =5; // 15 seconds
options.c_cc[VMIN] = 0;
tcflush(fd,TCIFLUSH); /* Update the options and do it NOW */
if (tcsetattr(fd,TCSANOW,&options) != 0)
{
perror("SetupSerial 3");
return (FALSE);
}
return (TRUE);
}
int OpenDev(const char *Dev) //Open com
{
int fd = open( Dev, O_RDWR | O_NOCTTY); //| O_NOCTTY | O_NDELAY
if (-1 == fd)
{
fprintf(stderr, "Can't Open Serial Port: %s", Dev);
return -1;
}
else
return fd;
}Top
6 楼flying520520(不老山)回复于 2005-04-07 22:42:06 得分 0
那里有最祥细的LINUX串口资料Top
7 楼flying520520(不老山)回复于 2005-04-10 22:51:55 得分 0
upTop




