【发布时间】:2017-02-16 15:41:49
【问题描述】:
我买了一个 GSM 模块,我试图通过 USB 转串口(FT232 命名组件)来控制它。
我在 GSM 模块之前编写了一个小程序来测试 FT232(通过将 TX 连接到 RX),我遇到了一个问题。
我可以发送数据(通常是“AT\r”)并且可以接收相同的数据(希望如此),但我会一次又一次地接收数据(通常是“0x0A”,有时是原始数据:“AT\r”)。 ..
你能帮我解决这个问题吗?
main.c 的代码
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <termios.h>
#include <unistd.h>
int open_serial();
int close_serial(int serial_fd);
int read_serial (int fd);
int main ()
{
int serial_fd = open_serial();
if (serial_fd == EXIT_FAILURE)
return EXIT_FAILURE;
struct termios old_termios;
struct termios serial_termios;
// Port configuration backup
tcgetattr(serial_fd, &old_termios);
serial_termios = old_termios;
// Port setup
serial_termios.c_cflag |= (B9600 | CS8 | CLOCAL | CREAD);
serial_termios.c_lflag |= (ICANON);
// Port configuration update
tcsetattr(serial_fd, TCSANOW, &serial_termios);
int num_char;
char* str2send = "AT\r";
num_char = write(serial_fd, str2send, strlen(str2send));
if (num_char < 0)
{
fputs("FAIL !\n", stderr);
}
else
{
printf("%d char sended\n", num_char);
}
fd_set serial_in;
int count=0;
while ((read_serial(serial_fd) > 0) & (count < 25))
count++;
// Port configuration restore
tcsetattr(serial_fd, TCSANOW, &old_termios);
return close_serial(serial_fd);
}
int open_serial()
{
int serial_fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
printf("Serial port opening...\n");
if (serial_fd == -1)
{
printf("FAIL !\n");
perror("open()");
return EXIT_FAILURE;
}
printf("SUCCESS ! [FD] : [%02d]\n", serial_fd);
return serial_fd;
}
int close_serial(int serial_fd)
{
printf("Serial port closing...\n[FD] : [%02d]\n", serial_fd);
if (close(serial_fd) == -1)
{
printf("FAIL !\n");
perror("close()");
return EXIT_FAILURE;
}
printf("SUCCESS !\n");
return EXIT_SUCCESS;
}
int read_serial (int fd)
{
char rcv_serial [256];
int max_fd = fd + 1;
fd_set input;
FD_ZERO(&input);
FD_SET(fd, &input);
int count;
// 1sec timeout
struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
int nb_char, ret_read;
int ret_sel = select(max_fd, &input, NULL, NULL, &timeout);
if (ret_sel < 0)
{
perror("select() :");
}
else if (ret_sel == 0)
{
printf("TIMEOUT\n");
}
else
{
if (FD_ISSET(fd, &input))
{
nb_char = 10;
ioctl(fd, FIONREAD, &nb_char);
printf("%d chars availables\n", nb_char);
ret_read = read(fd, &rcv_serial, nb_char);
printf("[ RET READ : %d]\n", ret_read);
rcv_serial[ret_read] ='\0';
for (count = 0; count < ret_read; count++)
printf("[%02X]", rcv_serial[count]);
printf("\n");
//printf("[%s]\n", rcv_serial);
}
}
return ret_sel;
}
结果
Serial port opening...
SUCCESS ! [FD] : [03]
3 char sended
3 chars availables
[ RET READ : 3]
[41][54][0A]
3 chars availables
[ RET READ : 3]
[41][54][0A]
1 chars availables
[ RET READ : 1]
[0A]
3 chars availables
[ RET READ : 3]
[41][54][0A]
1 chars availables
[ RET READ : 1]
[0A]
1 chars availables
[ RET READ : 1]
[0A]
1 chars availables
[ RET READ : 1]
[0A]
3 chars availables
[ RET READ : 3]
[41][54][0A]
1 chars availables
[ RET READ : 1]
[0A]
1 chars availables
[ RET READ : 1]
[0A]
1 chars availables
[ RET READ : 1]
[0A]
Serial port closing...
【问题讨论】:
-
如果在没有新数据的情况下继续读DR,还是一样的。 AT 命令以
"\r\n"结尾,'\n可能以' == 0xA结尾,所以说得通。 -
感谢您的回答。这个命令很有意义,但是我怎么知道是有新消息还是来电?我应该不断检查串口吗?
-
@Fiddling-Bits,您说芯片的寄存器在没有收到新数据时不会改变,因此包含收到的最后一个字符。很有意义。知道他拨打
read_serial有什么问题吗?在没有收到新数据时它应该阻塞还是返回零? -
read_serial 返回选择的值。就我而言,它总是返回一个 > 0 的值,就好像有新数据一样
-
我添加了输出,我们可以看到,输出有时会发生变化。我不明白为什么
标签: c linux serial-port