[英]Reading from Serial Port in linux using C language
I am new to serail programing in Linux (Fedora 12) using C Language.我是使用 C 语言在 Linux (Fedora 12) 中进行 serail 编程的新手。 I have a simple device, it is supposed to get 3 bytes command in hex (wirte) like {0x02,0x03,0x0D} and return 4 bytes response.
我有一个简单的设备,它应该以十六进制(写入)获取 3 个字节的命令,例如 {0x02,0x03,0x0D} 并返回 4 个字节的响应。
First I wrote a simple java program on windows, and I get the correct response.. as and when,I switch to linux, I can't read from serial com port neither using java nor C language.首先,我在 Windows 上编写了一个简单的 java 程序,并得到了正确的响应.. 当我切换到 linux 时,无论使用 java 还是 C 语言,我都无法从串行 com 端口读取。
I tried using libraries like rs232 .. but still the problem remains.我尝试使用像rs232 .. 这样的库,但问题仍然存在。 I can open "/dev/ttyS0", and write on it .. (none of them returns any Error), but read is not possible ..
我可以打开“/dev/ttyS0”,然后在上面写..(它们都没有返回任何错误),但无法读取..
If I use canonical mode, the program blocks on reading until i kill the program.. If use non-canonical mode, with VMIN=0 and VTIME=5, read function returns whith -107725432 bytes for example .. (I have tried reading and writing byte by byte or all at the same time .. no difference ..)如果我使用规范模式,程序会阻止读取,直到我杀死程序。并逐字节写入或同时写入所有内容..没有区别..)
rs232.c rs232.c
#include "rs232.h"
int Cport[6],
error;
struct termios new_port_settings,
old_port_settings[6];
char comports[6][16]={"/dev/ttyS0","/dev/ttyS1","/dev/ttyS2","/dev/ttyS3","/dev/ttyS4","/dev/ttyS5"};
int RS232_OpenComport(int comport_number, int baudrate, const char *mode)
{
int baudr,
status;
if((comport_number>5)||(comport_number<0))
{
printf("illegal comport number\n");
return(1);
}
switch(baudrate)
{
case 2400 : baudr = B2400;
break;
case 4800 : baudr = B4800;
break;
case 9600 : baudr = B9600;
break;
case 19200 : baudr = B19200;
break;
default : printf("invalid baudrate\n");
return(1);
break;
}
int cbits=CS8,
cpar=0,
ipar=IGNPAR,
bstop=0;
if(strlen(mode) != 3)
{
printf("invalid mode \"%s\"\n", mode);
return(1);
}
switch(mode[0])
{
case '8': cbits = CS8;
break;
case '7': cbits = CS7;
break;
case '6': cbits = CS6;
break;
case '5': cbits = CS5;
break;
default : printf("invalid number of data-bits '%c'\n", mode[0]);
return(1);
break;
}
switch(mode[1])
{
case 'N':
case 'n': cpar = 0;
ipar = IGNPAR;
break;
case 'E':
case 'e': cpar = PARENB;
ipar = INPCK;
break;
case 'O':
case 'o': cpar = (PARENB | PARODD);
ipar = INPCK;
break;
default : printf("invalid parity '%c'\n", mode[1]);
return(1);
break;
}
switch(mode[2])
{
case '1': bstop = 0;
break;
case '2': bstop = CSTOPB;
break;
default : printf("invalid number of stop bits '%c'\n", mode[2]);
return(1);
break;
}
Cport[comport_number] = open(comports[comport_number], O_RDWR | O_NOCTTY);
if(Cport[comport_number]==-1)
{
perror("unable to open comport ");
return(1);
}
/* lock access so that another process can't also use the port */
if(flock(Cport[comport_number], LOCK_EX | LOCK_NB) != 0)
{
close(Cport[comport_number]);
perror("Another process has locked the comport.");
return(1);
}
error = tcgetattr(Cport[comport_number], old_port_settings + comport_number);
if(error==-1)
{
close(Cport[comport_number]);
perror("unable to read portsettings ");
return(1);
}
memset(&new_port_settings, 0, sizeof(new_port_settings)); /* clear the new struct */
new_port_settings.c_cflag = cbits | cpar | bstop | CLOCAL | CREAD;
new_port_settings.c_iflag = ipar;
new_port_settings.c_oflag = 0;
new_port_settings.c_lflag = 0;
new_port_settings.c_cc[VMIN] = 0; /* block untill n bytes are received */
new_port_settings.c_cc[VTIME] = 5; /* block untill a timer expires (n * 100 mSec.) */
cfsetispeed(&new_port_settings, baudr);
cfsetospeed(&new_port_settings, baudr);
error = tcsetattr(Cport[comport_number], TCSANOW, &new_port_settings);
if(error==-1)
{
close(Cport[comport_number]);
perror("unable to adjust portsettings ");
return(1);
}
if(ioctl(Cport[comport_number], TIOCMGET, &status) == -1)
{
perror("unable to get portstatus");
return(1);
}
status |= TIOCM_DTR; /* turn on DTR */
status |= TIOCM_RTS; /* turn on RTS */
if(ioctl(Cport[comport_number], TIOCMSET, &status) == -1)
{
perror("unable to set portstatus");
return(1);
}
return(0);
}
int RS232_PollComport(int comport_number, unsigned char *buf, int size)
{
int n;
n = read(Cport[comport_number], buf, size);
return(n);
}
int RS232_SendBuf(int comport_number, unsigned char *buf, int size)
{
return(write(Cport[comport_number], buf, size));
}
void RS232_CloseComport(int comport_number)
{
int status;
if(ioctl(Cport[comport_number], TIOCMGET, &status) == -1)
{
perror("unable to get portstatus");
}
status &= ~TIOCM_DTR; /* turn off DTR */
status &= ~TIOCM_RTS; /* turn off RTS */
if(ioctl(Cport[comport_number], TIOCMSET, &status) == -1)
{
perror("unable to set portstatus");
}
tcsetattr(Cport[comport_number], TCSANOW, old_port_settings + comport_number);
close(Cport[comport_number]);
flock(Cport[comport_number], LOCK_UN); /* free the port so that others can use it. */
}
void RS232_flushRXTX(int comport_number)
{
tcflush(Cport[comport_number], TCIOFLUSH);
}
and和
main.c主文件
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include "rs232.h"
int main()
{
int cport_nr=0, bdrate=9600; /* 9600 baud */
char mode[]={'8','N','1',0},
str[512];
unsigned char buf[6000];
memset(buf, '\0' , 6000);
int buf_SIZE=sizeof(buf);
if(RS232_OpenComport(cport_nr, bdrate, mode))
{
printf("Can not open comport\n");
return(0);
}
unsigned char wr_buff[5];
memset(wr_buff, '\0', 5);
wr_buff[0] = 0x02;
wr_buff[1] = 0x01;
wr_buff[2] = 0x0D;
int cnt = RS232_SendBuf(cport_nr, wr_buff, 3);
printf("Number of bytes that has been written: %d\n",cnt);
if (cnt <= 0 )
return(-1);
cnt =0 ;
usleep(100000);
printf("Start Reading ... \n");
int i = 0;
do {
cnt = RS232_PollComport(cport_nr,(buf+i), 1);
i++;}
while(cnt>0);
printf ("%d bytes have been read\n");
RS232_CloseComport(cport_nr);
return (1);
}
I am really confused .. I tried almost every samples on the Internet .. An我真的很困惑..我几乎尝试了互联网上的所有样本..
y Idea Please?! y 想法好吗?! I have traced the program, using strace ..
我已经使用 strace 跟踪了该程序。
...
...
write(3,"\\2\\3\\r",3) = 3
写(3,"\\2\\3\\r",3) = 3
fstat64(1 , {st_mode=S_IFREG| 0755, st_size =0,..}) = 0
fstat64(1, {st_mode=S_IFREG| 0755, st_size =0,..}) = 0
mmap2(NULL,4096,PROT_READ|PROT_WRITE, MAP_PRIVATE| MAP_ANONYMOUS,-1,0) = 0Xb78b4000
mmap2(NULL,4096,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0) = 0Xb78b4000
nanosleep({0, 100000000}, NULL) = 0
nanosleep({0, 100000000}, NULL) = 0
read(3,"",1) = 0
读(3,“”,1)= 0
.....
.....
Can the problem be related to fedora12?问题可能与fedora12有关吗?
PS : if I haven't got response in windows, I was sure that its a problem with the device. PS:如果我在 Windows 中没有得到响应,我确定是设备有问题。
Solved ...解决了 ...
it was a mistake of me ... In fact, every thing was ok, the problem was in the way I print number of bytes have been read.. I had forgotten to put "cnt" in respect of %d ...这是我的一个错误......事实上,一切都很好,问题在于我打印已读取字节数的方式......我忘记在 %d 中放置“cnt”......
printf ("%d bytes have been read\\n");
printf ("%d 个字节已被读取\\n"); --> printf ("%d bytes have been read\\n",cnt);
--> printf ("%d 个字节已被读取\\n",cnt);
also i should have read only 4 bytes based on the protocol of communication with my device ..根据与我的设备的通信协议,我也应该只读取 4 个字节..
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.