当前位置: 技术问答>linux和unix
串口通信的问题
来源: 互联网 发布时间:2017-03-21
本文导语: 在网上修改了串口通信的代码,编译正确,打开串口和参数设置都是正确的,但是就是在发送数据的时候出现问题,板子发送的数据PC收不到,PC发送的数据板子也收不到,不知道是什么原因,详情各位大哥看看~~~ 附...
在网上修改了串口通信的代码,编译正确,打开串口和参数设置都是正确的,但是就是在发送数据的时候出现问题,板子发送的数据PC收不到,PC发送的数据板子也收不到,不知道是什么原因,详情各位大哥看看~~~
附上我的主要代码:
附上我的主要代码:
/***@brief 设置串口通信速率
*@param fd 类型 int 打开串口的文件句柄
*@param speed 类型 int 串口速度
*@return void*/
int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300,
B38400, B19200, B9600, B4800, B2400, B1200, B300, };
int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300,
38400, 19200, 9600, 4800, 2400, 1200, 300, };
void set_speed(int fd, int speed)
{
int i;
int status;
struct termios Opt;
tcgetattr(fd, &Opt);
for(i= 0;i0)
{
printf("Open Serial Port Successful!n");
set_speed(fd,19200);
printf("set_speed Successful!n");
}
else
{
printf("Can't Open Serial Port!n");
exit(0);
}
if (set_Parity(fd,8,1,'N')== FALSE)
{
printf("Set Parity Errorn");
exit(1);
}
printf("Set Parity Successful!n");
#if 1
//while(1)
//{
nRet = write(fd,buff,512);
if(-1 == nRet)
{
printf("Write Error!n");
}
printf("Write Successful!n");
//}
#endif
#if 0
while(1)
{
while((nread = read(fd,buff,512))>0)
{
printf("nLen %dn",nread);
buff[nread+1]='';
printf("n%s",buff);
}
}
#endif
nRet = close(fd);
if(-1 == nRet)
{
printf("Close Port Error!n");
}
printf("Close Port Successful!n");
}
|
1、判断你的串口线是否正确
2、判断你所用的串口设备是否正确
3、判断你的板子和PC之间的串口设置是否一致
还不行的话,建议用示波器进行判断:
当板子发送数据时,用示波器看看串口线上是否有波形。
2、判断你所用的串口设备是否正确
3、判断你的板子和PC之间的串口设置是否一致
还不行的话,建议用示波器进行判断:
当板子发送数据时,用示波器看看串口线上是否有波形。
|
再给你个建议:
把你这段代码,放到PC上(Linux OS)编译运行,让两台PC进行串口通讯。
如果没有问题那应该是板子的串口驱动程序有问题。
如果在PC上运行也有问题,再仔细查你的代码(稍微浏览了一下,没有发现明显的问题)。
把你这段代码,放到PC上(Linux OS)编译运行,让两台PC进行串口通讯。
如果没有问题那应该是板子的串口驱动程序有问题。
如果在PC上运行也有问题,再仔细查你的代码(稍微浏览了一下,没有发现明显的问题)。
|
给你一个建议:
1,首先用超级终端测试该串口是否是通的。我曾今遇到这种情况,串口线绝对是好的。设备绝对是好的。
但是就是不同。最后找了很久才发现,原来我的开发板串口竟然没有交叉!!!RXD Txd竟然没有交叉!!
2.先不着急发送别的,先测试发送单个字符。
然后对于串口设置,设置好几就ok了。主要的问题恐怕就是设置阻塞那一段属性需要你自己去式。其他没什么
困难的了
1,首先用超级终端测试该串口是否是通的。我曾今遇到这种情况,串口线绝对是好的。设备绝对是好的。
但是就是不同。最后找了很久才发现,原来我的开发板串口竟然没有交叉!!!RXD Txd竟然没有交叉!!
2.先不着急发送别的,先测试发送单个字符。
然后对于串口设置,设置好几就ok了。主要的问题恐怕就是设置阻塞那一段属性需要你自己去式。其他没什么
困难的了
|
在实际中的情况往往是非常多特例,比如,在用write发送数据时没有键入回车,信息就将发送不出去的情况,这主要是因为我们在输出输入时是按照 规范模式接受到回车或换行才发送,而非常多情况我们是不必回车和换行的,这时,应当转换到行方式输入,设置options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);不经处理直接发送。
又比如在我们发送字符0x0d的时候,往往接受端得到的字符是0x0a 这是怎么回事,原因是在串口设置中c_iflag和c_oflag中存在从NL-CR 和CR-NL的映射,也就是说,串口能把回车和换行看成一个字符,所以,此时我们应该屏蔽掉这些,用options.c_oflag &=~(INLCR|IGNCR|ICRNL|);和options.c_oflag &=~(ONLCR|OCRNL); 进行设置。
又比如在我们发送字符0x0d的时候,往往接受端得到的字符是0x0a 这是怎么回事,原因是在串口设置中c_iflag和c_oflag中存在从NL-CR 和CR-NL的映射,也就是说,串口能把回车和换行看成一个字符,所以,此时我们应该屏蔽掉这些,用options.c_oflag &=~(INLCR|IGNCR|ICRNL|);和options.c_oflag &=~(ONLCR|OCRNL); 进行设置。
|
我也用过这段代码,也是无法通信,后来网上查了下,在set_Parity的设置options的设置改成如下就可以了
options.c_cflag |= CLOCAL | CREAD;
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
options.c_oflag &= ~OPOST;
options.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
options.c_cflag |= CLOCAL | CREAD;
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
options.c_oflag &= ~OPOST;
options.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
|
int set_Parity(int ai_com,uchar ai_databits,uchar ai_stopbits,uchar ai_parity)
{
struct termios options;
if ( tcgetattr( ai_com,&options) != 0)
{
return ERROR_LOAD_COMINFO;
}
options.c_cflag |= CLOCAL | CREAD;
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
options.c_oflag &= ~OPOST;
options.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
/*options.c_cflag &= ~CSIZE;
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
options.c_oflag &= ~OPOST; */
switch (ai_databits) /*设置数据位数*/
{
case 5:
options.c_cflag |= CS5;
break;
case 6:
options.c_cflag |= CS6;
break;
case 7:
options.c_cflag |= CS7;
break;
case 8:
options.c_cflag |= CS8;
break;
default:
return ERROR_DATABITS;
}
switch (ai_parity)
{
/*case 'n':
case 'N':*/
case 1:
options.c_cflag &= ~PARENB; /* Clear parity enable */
options.c_iflag &= ~INPCK; /* Enable parity checking */
break;
/*case 'o':
case 'O':*/
case 2:
options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/
options.c_iflag |= INPCK; /* Disnable parity checking */
break;
/*case 'e':
case 'E':*/
case 3:
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*/
case 4:
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
break;
default:
return ERROR_PARITY;
}
/* 设置停止位*/
switch (ai_stopbits)
{
case 1:
options.c_cflag &= ~CSTOPB;
break;
case 2:
options.c_cflag |= CSTOPB;
break;
default:
return ERROR_STOPBITS;
}
/* Set input parity option */
/* if (ai_parity != 'n')*/
if (ai_parity != 1)
options.c_iflag |= INPCK;
tcflush(ai_com,TCIFLUSH);
options.c_cc[VTIME] = 0; /* 设置超时15 seconds*/
options.c_cc[VMIN] = 1; /* define the minimum bytes data to be readed*/
if (tcsetattr(ai_com,TCSANOW,&options) != 0)
{
/*printf("set_Parity errorn");*/
return (FALSE);
}
/*printf("set_Parity successn");*/
return (TRUE);
}
这是我的set_Parity,用在modem拨号程序上,做了些修改以对应数据库里的参数,大体上和你用的差不多
{
struct termios options;
if ( tcgetattr( ai_com,&options) != 0)
{
return ERROR_LOAD_COMINFO;
}
options.c_cflag |= CLOCAL | CREAD;
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
options.c_oflag &= ~OPOST;
options.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
/*options.c_cflag &= ~CSIZE;
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
options.c_oflag &= ~OPOST; */
switch (ai_databits) /*设置数据位数*/
{
case 5:
options.c_cflag |= CS5;
break;
case 6:
options.c_cflag |= CS6;
break;
case 7:
options.c_cflag |= CS7;
break;
case 8:
options.c_cflag |= CS8;
break;
default:
return ERROR_DATABITS;
}
switch (ai_parity)
{
/*case 'n':
case 'N':*/
case 1:
options.c_cflag &= ~PARENB; /* Clear parity enable */
options.c_iflag &= ~INPCK; /* Enable parity checking */
break;
/*case 'o':
case 'O':*/
case 2:
options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/
options.c_iflag |= INPCK; /* Disnable parity checking */
break;
/*case 'e':
case 'E':*/
case 3:
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*/
case 4:
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
break;
default:
return ERROR_PARITY;
}
/* 设置停止位*/
switch (ai_stopbits)
{
case 1:
options.c_cflag &= ~CSTOPB;
break;
case 2:
options.c_cflag |= CSTOPB;
break;
default:
return ERROR_STOPBITS;
}
/* Set input parity option */
/* if (ai_parity != 'n')*/
if (ai_parity != 1)
options.c_iflag |= INPCK;
tcflush(ai_com,TCIFLUSH);
options.c_cc[VTIME] = 0; /* 设置超时15 seconds*/
options.c_cc[VMIN] = 1; /* define the minimum bytes data to be readed*/
if (tcsetattr(ai_com,TCSANOW,&options) != 0)
{
/*printf("set_Parity errorn");*/
return (FALSE);
}
/*printf("set_Parity successn");*/
return (TRUE);
}
这是我的set_Parity,用在modem拨号程序上,做了些修改以对应数据库里的参数,大体上和你用的差不多
|
重点查查串口驱动中的初始化部分,看看你要用的串口的配置寄存器是否正确。或者你的驱动中只配置了UART0和UART1,而你却要用到UART3。
本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。