(编辑于2/1/14 - 配对代码特定于此问题。使用较小的代码进行测试。编辑此姿势以显示仍然存在相同问题的全新代码。)
我正在使用POSIX序列指南在Angstrom Linux发行版内核3.8中使用beagle bone black。
我有一组函数来处理serial.c中定义的串行通信。我想将它们用作其他程序使用的库。 我在函数定义之前在serial.c的顶部将这些函数的许多公共变量声明为static。我的意图是这些将像全局变量,但只是对于serial.c中的函数,并且它们将在函数调用之间保持它们的值。看起来好像这样按照我的意图工作。
其中一个函数是send_serial()。它完全按照它所说的,将数据发送到串行端口。 如果我在serial.c中编写一个main()函数然后从同一个文件中调用它,那么send_serial()就会按预期工作。一旦程序使用send_serial()命中行,数据立即被写入串口。我可以看到发送和接收灯闪烁,我收回了预期的数据。
然而,当我尝试从不同的文件中使用send_serial()时,它表现得很奇怪。它执行正常并返回正确的字节数,程序继续到下一行,除了根本没有实际的串口通信。直到程序结束或我在串口上调用close,才会在串口上实际发送数据。
为什么它会在同一个文件中正常工作,但它从另一个文件中运行不正常。在两种情况下,我都使用完全相同的功能来设置和打开串口。
serial.h
#ifndef _PUP_SERIAL_ /* Include guard */
#define _PUP_SERIAL_
#define MAXBUF 1024
typedef struct byte_array {
unsigned char byte[MAXBUF];
int count;
} byte_array;
void set_serial_debug(int debug_value);
void close_serial();
int setup_serial_port(char * port_name);
int send_serial(byte_array message);
byte_array read_serial();
byte_array test_message();
#endif
serial.c
//#define _SERIAL_IS_MAIN_ // comment out this line for this file to be a library instead of main function
#include <stdio.h> /* Standard input/output definitions */
#include <fcntl.h> /* File control definitions */
#include <termios.h> /* POSIX terminal control definitions */
#include <sys/time.h>
#include "serial.h"
static int debug;
static int fd;
static struct termios options;
void print_bytes_as_hex(char * str, byte_array message)
{
int n;
int i;
printf(str);
if (message.count > 0)
for (i = 0; i < message.count; i++)
{
n = (int) message.byte[i];
printf("0x%.2x ", n);
}
else
printf("-x--");
printf("\n");
} // end of print bytes as hex
int setup_serial_port(char * port_name)
{
fd = open(port_name, O_RDWR | O_NOCTTY | O_NDELAY);
printf("Opened up port %s as number %d",port_name,fd);
tcgetattr(fd, &options);
if (port_name == "/dev/ttyUSB0")<--Fixed by changing to: if (strcmp(port_name,"/dev/ttyUSB0")==0)
options.c_cflag &= ~CRTSCTS; // set NO RTS control for USB
else
options.c_cflag |= CRTSCTS; // set RTS control for ttyO#
cfsetispeed(&options, B9600);
cfsetospeed(&options, B9600);
// set No parity (8N1):
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
options.c_iflag |= IGNBRK;
options.c_iflag &= ~(IXON | IXOFF | IXANY); // No software handshake
options.c_lflag = 0;
options.c_oflag = 0;
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // Raw Input
//options.c_lflag |= (ICANON | ECHO | ECHOE); // Canonical input
options.c_cc[VMIN] = 1; // 1 means read dos not block
options.c_cc[VTIME] = 1; // 1 means 0.1 seconds read timeout
options.c_cflag |= (CLOCAL | CREAD); // Enable the receiver and set local mode
/* Make raw */
cfmakeraw(&options);
/* Flush Port, then applies attributes */
tcflush( fd, TCIFLUSH );
fcntl(fd, F_SETFL, 0);
tcsetattr(fd, TCSANOW, &options); // Set the new options for the port
if (fd == -1)
{ //Could not open the port.
perror("open_port: Unable to open");
printf("Could not open port %s\n",port_name);
}
else // port is open
printf("Port %s is open as # %d\n",port_name, fd);
return fd;
} // End of setup_serial_port
void set_serial_debug(int debug_value)
{
debug = debug_value;
}
void close_serial()
{
close(fd);
}
int send_serial(byte_array message)
{
int n;
printf("about to send to serial port...\n");
n = write(fd, message.byte, message.count);
printf("sent %d bytes to serial port %d\n",n,fd);
return n;
}
byte_array read_serial()
{
static byte_array message;
int n;
int i;
printf("Attempting to read from serial port %d...\n",fd);
for (i = 0; i < 8; i++)
n = read(fd, &message.byte[i], 1);
message.count = i;
printf("read %d bytes from the serial port %d\n",message.count,fd);
return message;
}
byte_array test_message()
{
int i;
unsigned char st[] = {0x02, 0x10, 0x27, 0x0D, 0x02, 0x01, 0xFB, 0x43, 0x56, 0x00, 0x00, 0x00, 0x00, 0xDC};
byte_array return_message;
for (i = 0; i < 14; i++)
return_message.byte[i] = st[i];
return_message.count = 14;
return return_message;
}
#ifdef _SERIAL_IS_MAIN_
int main(int Count, char *Strings[])
{
setup_serial_port("/dev/ttyUSB0");
byte_array out_message = test_message();
byte_array in_message;
print_bytes_as_hex("sending: ",out_message);
send_serial(out_message);
in_message = read_serial();
print_bytes_as_hex("recieved: ",in_message);
}
#endif
的main.c
#include <stdio.h>
#include "serial.h"
byte_array in_message;
byte_array out_message;
int main(int Count, char *Strings[])
{
setup_serial_port("/dev/ttyUSB0");
byte_array out_message = test_message();
byte_array in_message;
print_bytes_as_hex("sending: ",out_message);
send_serial(out_message);
in_message = read_serial();
print_bytes_as_hex("recieved: ",in_message);
}
如果我调用send_serial(message);从serial.c里面就可以了。
# gcc -o serial serial.c
# ./serial
Opened up port /dev/ttyUSB0 as number 3Port /dev/ttyUSB0 is open as # 3
sending: 0x02 0x10 0x27 0x0d 0x02 0x01 0xfb 0x43 0x56 0x00 0x00 0x00 0x00 0xdc
about to send to serial port...
sent 14 bytes to serial port 3 <-- Send and Receive Lights blink
Attempting to read from serial port 3...
read 8 bytes from the serial port 3
recieved: 0x02 0x10 0x27 0x07 0x81 0x02 0x0e 0xbc
如果我调用send_serial(message);从serial.c的外部开始,直到程序结束才会发送。
(edit serial.c to comment out //#define _SERIAL_IS_MAIN_)
# gcc -o main main.c serial.c
# ./main
Opened up port /dev/ttyUSB0 as number 3Port /dev/ttyUSB0 is open as # 3
sending: 0x02 0x10 0x27 0x0d 0x02 0x01 0xfb 0x43 0x56 0x00 0x00 0x00 0x00 0xdc
about to send to serial port...
sent 14 bytes to serial port 3 <-- comm lights do not blink at all
Attempting to read from serial port 3... <-- Program waits here for ever until CTRL^C
^C <-- Once I press CTRL^C snd and rec comm lights blink
当我从main.c运行这个程序时,它等待read_serial()函数,因为它正在等待我的设备的回复。设备没有发回回复,因为我的程序从未将消息发送到串行端口。它说发了它,但事实并非如此。一旦我按下CTRL ^ C,程序(或者可能是os)发送消息,设备就会收到消息,然后它会回复给我。但是我从来没有收到消息,因为程序不再运行。
答案 0 :(得分:2)
我终于找到了问题所在。 Chux是对的。作为独立程序运行serial.c不使用RTS控件。作为main.c的一部分运行,它使用RTS控件。由于我已将其连接到USB端口,因此不应使用RTS。混淆的原因是setup_serial_port(char * port_name)
:
if (port_name == "/dev/ttyUSB0")
其中port_name是char *。我不确定为什么这在serial.c中工作(返回true)但在main.c中返回false。当我把它改为:
if (strcmp(port_name,"/dev/ttyUSB0")==0)
该程序在两种情况下都按预期工作。
任何人都可以解释为什么if (port_name == "/dev/ttyUSB0")
在serial.c中返回true? (端口名称为/dev/ttyUSB0
,但在调查此问题后,我发现您无法将字符串与==
进行比较。那么为什么在一种情况下它返回true而另一种情况呢?