linuxcici
串口通信遇到麻烦.请各位帮忙
用一条RS232线连接两台LINUX .用了命令测试串口和发消息是保证系统和线是没问题的.
在两端用同一样的代码. 也试过一台LINUX read.另外一台write. 还是不行.
问题就是在read那里阻塞. 读不到数据. 但write那边是正确的喔. 什么原因呢
代码是书上的
代码:
[code]
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<fcntl.h>
#include<errno.h>
#include<termios.h>
int open_port(void)
{
int fd;
fd=open("/dev/ttyS0",O_RDWR|O_NOCTTY|O_NDELAY);
if(fd==-1)
{
printf(" unable to open /dev/ttyS1/n");
}
else
{
printf("/nOpen serial Ok~/n");
fcntl(fd,F_SETFL,0);
}
return(fd);
}
void init_serial(int fd)
{
struct termios options;
tcgetattr(fd,&options);
cfsetispeed(&options,B115200);
cfsetospeed(&options,B115200);
options.c_cflag|=(CLOCAL|CREAD);
options.c_cflag&=~CSIZE;
options.c_cflag|=CS8;
tcsetattr(fd,TCSANOW,&options);
}
int read_data(int fd)
{
char buffer[255];
char *bufptr;
int nbytes;
bufptr=buffer;
while((nbytes=read(fd,bufptr,buffer+sizeof(buffer)-bufptr-1))>0)
{
bufptr+=nbytes;
if(bufptr[-1]=='/n'|| bufptr[-1]=='/r')
break;
}
*bufptr='/0';
printf("/n%s/n",buffer);
return(0);
}
int write_port(int fd)
{
int n;
printf("in F_write_port/n");
n=write(fd,"hello world!/r",12);
if(n<0)
{
fputs("failed!/n",stderr);
}
else
{
printf("write ok/n");
}
return 0;
}
int main(void)
{
int fd;
fd=open_port();
if(fd!=-1)
{
init_serial(fd);
// write_port(fd);
read_data(fd);
}
close(fd);
return 0;
}
[/code]
linuxcici
在A机器运行:cat /dev/ttyS0
在B机器运行:echo 'test1234' > /dev/ttyS0 , A机器是能收到的.
但在B机器运行上面代码.[只用write_port这涵数]的话. 运行后A机器没反应.但如果再运行一次:
echo 'test1234' > /dev/ttyS0 . A机器就显示:hello worltest1234 把原来B机器的程序的消息也连同命令的消息发送出去了. 为什么呢?
xi2008wang
fd=open("/dev/ttyS0",O_RDWR|O_NOCTTY|O_NDELAY);
if(fd==-1)
{
printf(" unable to open /dev/ttyS1/n");
书上也有这样的代码?
cccccc
机器的流模式设置不对吧。在两台机器里运行 stty -a -F /dev/ttyS1看看
cjaizss
你两边链路层设置不一样
再者,通信之前应该tcflush一下
[[i] 本帖最后由 cjaizss 于 2008-2-14 12:39 编辑 [/i]]
linuxcici
[code]
while((nbytes=read(fd,bufptr,buffer+sizeof(buffer)-bufptr-1))>0)
{
bufptr+=nbytes;
if(bufptr[-1]=='/n'|| bufptr[-1]=='/r')
break;
}
*bufptr='/0';
printf("/n%s/n",buffer);
return(0);
}
[/code]
这段代码. 我写了:write(fd,"hello World!/r",12);
这个read老是运行了两次. 要是我发:write(fd,"hello World!",12);简直什么都收不到.
请问串口发信息,字符串是以什么结束的呢? 我又改了: read(fd, buffer,sizeof(buffer))这样的标准形式去读. 但是什么都读不到. 请各位有经验的大牛能贴一下代码吗? 真的很急..
cccccc
char tmp="hello word/n";
write(fd,tmp,sizeof(tmp));
这样试试
linuxcici
[code]
#include <stdio.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <string.h>
/*
* 串口初始化函数。
* dev:串口设备名,串口1是"/dev/ttyS0",串口2是"/dev/ttyS1",依此类推。
* USB转串口的设备名是"/dev/ttyUSB0"、"/dev/ttyUSB1"等等。
* speed:串口波特率,可以是230400, 115200, 57600, 38400, 19200, 9600, 4800, 2400, 1200, 300, 0。
* databits:数据位,值是5、6、7或者8。
* parity:奇偶校验。值为'N','E','O','S'。
* stopbits:停止位,值是1或者2。
* hwf:硬件流控制。1为打开,0为关闭。
* swf:软件流控制。1为打开,0为关闭。
*/
int SerialPortInit(char *dev,int speed,int databits,int parity,int stopbits,int hwf,int swf)
{
int fd,i,ret;
struct termios tty;
int speed_arr[] = {B230400, B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, B300,B0};
int name_arr[] = {230400, 115200, 57600, 38400, 19200, 9600, 4800, 2400, 1200, 300, 0};
fd=open(dev,O_RDWR|O_NOCTTY);
if(!fd)
{
printf("cannot open %s/n",dev);
return -1;
}
ret=tcgetattr(fd, &tty);
if(ret<0)
{
printf("tcgetattr error/n");
close(fd);
return -1;
}
//设置波特率
for(i= 0; i < sizeof(speed_arr) / sizeof(int); i++)
{
if(speed == name_arr[i])
{
cfsetispeed(&tty, speed_arr[i]);
cfsetospeed(&tty, speed_arr[i]);
break;
}
if(name_arr[i] == 0)
{
printf("speed %d is not support,set to 9600/n",speed);
cfsetispeed(&tty, B9600);
cfsetospeed(&tty, B9600);
}
}
//设置数据位
switch (databits)
{
case 5:
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS5;
break;
case 6:
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS6;
break;
case 7:
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS7;
break;
case 8:
default:
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;
break;
}
//设置停止位
if(stopbits == 2)
tty.c_cflag |= CSTOPB;
else
tty.c_cflag &= ~CSTOPB;
//设置奇偶校验
switch (parity)
{
//无奇偶校验
case 'n':
case 'N':
tty.c_cflag &= ~PARENB; /* Clear parity enable */
tty.c_iflag &= ~INPCK; /* Enable parity checking */
break;
//奇校验
case 'o':
case 'O':
tty.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/
tty.c_iflag |= INPCK; /* Disable parity checking */
break;
//偶校验
case 'e':
case 'E':
tty.c_cflag |= PARENB; /* Enable parity */
tty.c_cflag &= ~PARODD; /* 转换为偶效验*/
tty.c_iflag |= INPCK; /* Disable parity checking */
break;
//等效于“无奇偶校验”
case 'S':
case 's': /*as no parity*/
tty.c_cflag &= ~PARENB;
tty.c_cflag &= ~CSTOPB;
break;
default:
tty.c_cflag &= ~PARENB; /* Clear parity enable */
tty.c_iflag &= ~INPCK; /* Enable parity checking */
break;
}
//设置硬件流控制
if (hwf)
tty.c_cflag |= CRTSCTS;
else
tty.c_cflag &= ~CRTSCTS;
//设置软件流控制
if (swf)
tty.c_iflag |= IXON | IXOFF;
else
tty.c_iflag &= ~(IXON|IXOFF|IXANY);
//设置为RAW模式
tty.c_iflag &= ~(IGNBRK | IGNCR | INLCR | ICRNL | IUCLC |
IXANY | IXON | IXOFF | INPCK | ISTRIP);
tty.c_iflag |= (BRKINT | IGNPAR);
tty.c_oflag &= ~OPOST;
tty.c_lflag &= ~(XCASE|ECHONL|NOFLSH);
tty.c_lflag &= ~(ICANON | ISIG | ECHO);
tty.c_cflag |= (CLOCAL | CREAD);
tty.c_cc[VTIME] = 1; /*(非阻塞模式)操作超时,单位为0.1秒*/
tty.c_cc[VMIN] = 1; /* 1为阻塞模式,0为非阻塞模式*/
//设置串口属性
ret = tcsetattr(fd, TCSANOW, &tty);
if(ret < 0)
{
printf("error while setting %s attribe/n");
close(fd);
return -1;
}
tcflush(fd,TCIOFLUSH);
return fd;
}
main()
{
int fd;
char *data="hello";
char buf[10];
fd=SerialPortInit("/dev/ttyS0",9600,8,'N',1,0,0);
if(fd)
{
read(fd,buf,10);
close(fd);
}
}
[/code]
[[i] 本帖最后由 linuxcici 于 2008-2-20 09:56 编辑 [/i]]
linuxcici
现在可以通信的. 问题就是同步的问题.
例如:
PC1: PC2:
while(read()) while(write())
如果wirte发的是"aaa"
但在PC1中的read因为在不停的在read有时候它收到的可能是全部的aaa, 但有时候收到的只是一个a. 剩下的两个a在下一次才收到. 请问怎么判断同步的问题呢?一定要在read里面去判断的吗?还是在设计串口的参数里面可以设置好的呢?
jamesr
以前发过类似的帖子没有人回复。串口参数是最复杂的了,你那个只有遇到/n才收到数据就是参数没有设置好。
搜到一个代码,希望有帮助。这部分主要是靠翻手册:
[url]http://www.tongyi.net/os/linux/1045036.html[/url]
sleetboy
回复 #12 linuxcici 的帖子
用select试过没有?
另外read的buffer改小一点儿试试