串口二进制传输改回车return
Serial port binary transfer changes carriage return
上周我一直在尝试用 C 实现一个原始的串行文件传输协议,但我遇到了一个非常奇怪的问题,我似乎无法在网上找到解决方案。我设法通过串行端口传输二进制数据并接收它,但在此过程中,所有“0D”字节都转换为“0A”。以下是我的代码。
#include <stdlib.h>
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <signal.h>
#include <sys/ioctl.h>
#include <termios.h>
//eventually plan to set up a proper communication protocol
#define ACK 0x01
#define NAK 0x00
int setAttribs (int fd, int speed, int parity);
unsigned char* readFile(char* filename, int* file_size);
int main(void){
//set up ports
int fd = 0, r = 0, i = 0;
fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);//sending port
if(fd<0){
perror("open port ttyUSB0 failed");
return -1;
}
setAttribs(fd,1500000,0);
int rd =0, file_size=0, bytes=0;
rd = open("/dev/ttyUSB1", O_RDWR | O_NOCTTY | O_NDELAY);//receiving port
setAttribs(rd,1500000,0);
//create file to which the binary data will be written
FILE *newFile;
newFile = fopen("t.bin","wb");
if(newFile<0){
printf("open file failed\n");
return -1;
}
//This character array will hold the file to be transferred
unsigned char* data = '[=11=]';
data = readFile("t.odt", &file_size);
ioctl(rd, TCFLSH, &bytes);//port flush which does not seem to work
do{
//write data in 1024 byte chunks
write(fd,data+i,1024);
//wait for write to finish
usleep(8500);
//buffer to hold received bytes
unsigned char buffer[1024];
//ensure buffer is empty
memset(buffer,0,1024);
//read in 1024 byte chunks
read(rd, buffer, 1024);
//printing bytes in the buffer to check for errors
for(r=0;r<1024;r++){
if(r%16==0)
printf("\n");
printf("%02X ", buffer[r]);
}
//write to file in 1024 byte chunks
fwrite(buffer, 1,1024,newFile);
//increase counter
i+=1024;
}while(i<8197);//its an 8088 byte file
printf("Done!\n");
return 0;
}
unsigned char* readFile(char* filename, int* file_size){
unsigned char *buffer = NULL;
int string_size, i;
FILE *handler = fopen(filename, "rb");
if (handler)
{
// Seek the last byte of the file
fseek(handler, 0, SEEK_END);
// Offset from the first to the last byte, or in other words, filesize
string_size = ftell(handler);
printf("File length: %d\n",string_size);
*file_size = string_size;
// go back to the start of the file
rewind(handler);
// Allocate a string that can hold it all
buffer = (unsigned char*) malloc(sizeof(unsigned char) * (string_size + 1) );
// Read it all in one operation
for(i=0;i<string_size;i++){
fread(buffer+i, sizeof(unsigned char),1, handler);
if(i%16==0)
printf("\n");
printf("%02X ",*(buffer+i));
}
// fread doesn't set it so put a [=11=] in the last position
// and buffer is now officially a string
// buffer[string_size] = '[=11=]';
printf("Finished read\n");
// Always remember to close the file
fclose(handler);
}
return buffer;
}
int setAttribs (int fd, int speed, int parity)
{
struct termios tty;
memset (&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0)
{
fputs("error %d from tcgetattr", stderr);
}
cfsetospeed (&tty, speed);
cfsetispeed (&tty, speed);
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
// disable IGNBRK for mismatched speed tests; otherwise receive break
// as [=11=]0 chars
tty.c_iflag &= ~IGNBRK; // disable break processing
tty.c_lflag = 0; // no signaling chars, no echo,
// no canonical processing
tty.c_oflag = 0; // no remapping, no delays
tty.c_cc[VMIN] = 0; // read doesn't block
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
// enable reading
tty.c_cflag &= ~(PARENB | PARODD); // shut off parity
tty.c_cflag |= parity;
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CRTSCTS;
if (tcsetattr (fd, TCSANOW, &tty) != 0)
{
fputs("error %d from tcsetattr", stderr);
}
return 1;
}
它所做的只是在一个端口中写入 USB 串行转换器,并在另一个端口中读取。我只是用一个 8088 字节的 ODT 文件 (Hello World) 测试它,并尝试不同的波特率和写入块大小。经过反复试验,我发现这种配置(1500000 bps 和 1024 字节块)既快又相对可靠。唯一的错误如下所示。
Transmitted bytes: 70 6E 67 89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49
Received bytes: 70 6E 67 89 50 4E 47 0A 0A 1A 0A 00 00 00 0A 49
如您所见,所有“0D”字节都已更改为“0A”。我尝试了较低的波特率和较小的块大小,但问题仍然存在。我知道它们分别是 carriage return 和 line feed 值以及 line feed在Linux中用作异步通信的控制值;但我不明白为什么这会影响 carriage return 值。 回车return在串口通信中有什么特殊意义吗?在这种情况下,有没有办法发送“0D”字节?
TL;DR: 原始串行通信导致“0D”字节被“0A”替换。知道为什么吗?有什么办法解决吗?
非常感谢,它成功了!!我从来不知道有 ICRNL 选项可以将换行符转换为回车 returns。一旦我用
设置它和其他人
tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); //tty is the name of the struct termios
它是金色的。
上周我一直在尝试用 C 实现一个原始的串行文件传输协议,但我遇到了一个非常奇怪的问题,我似乎无法在网上找到解决方案。我设法通过串行端口传输二进制数据并接收它,但在此过程中,所有“0D”字节都转换为“0A”。以下是我的代码。
#include <stdlib.h>
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <signal.h>
#include <sys/ioctl.h>
#include <termios.h>
//eventually plan to set up a proper communication protocol
#define ACK 0x01
#define NAK 0x00
int setAttribs (int fd, int speed, int parity);
unsigned char* readFile(char* filename, int* file_size);
int main(void){
//set up ports
int fd = 0, r = 0, i = 0;
fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);//sending port
if(fd<0){
perror("open port ttyUSB0 failed");
return -1;
}
setAttribs(fd,1500000,0);
int rd =0, file_size=0, bytes=0;
rd = open("/dev/ttyUSB1", O_RDWR | O_NOCTTY | O_NDELAY);//receiving port
setAttribs(rd,1500000,0);
//create file to which the binary data will be written
FILE *newFile;
newFile = fopen("t.bin","wb");
if(newFile<0){
printf("open file failed\n");
return -1;
}
//This character array will hold the file to be transferred
unsigned char* data = '[=11=]';
data = readFile("t.odt", &file_size);
ioctl(rd, TCFLSH, &bytes);//port flush which does not seem to work
do{
//write data in 1024 byte chunks
write(fd,data+i,1024);
//wait for write to finish
usleep(8500);
//buffer to hold received bytes
unsigned char buffer[1024];
//ensure buffer is empty
memset(buffer,0,1024);
//read in 1024 byte chunks
read(rd, buffer, 1024);
//printing bytes in the buffer to check for errors
for(r=0;r<1024;r++){
if(r%16==0)
printf("\n");
printf("%02X ", buffer[r]);
}
//write to file in 1024 byte chunks
fwrite(buffer, 1,1024,newFile);
//increase counter
i+=1024;
}while(i<8197);//its an 8088 byte file
printf("Done!\n");
return 0;
}
unsigned char* readFile(char* filename, int* file_size){
unsigned char *buffer = NULL;
int string_size, i;
FILE *handler = fopen(filename, "rb");
if (handler)
{
// Seek the last byte of the file
fseek(handler, 0, SEEK_END);
// Offset from the first to the last byte, or in other words, filesize
string_size = ftell(handler);
printf("File length: %d\n",string_size);
*file_size = string_size;
// go back to the start of the file
rewind(handler);
// Allocate a string that can hold it all
buffer = (unsigned char*) malloc(sizeof(unsigned char) * (string_size + 1) );
// Read it all in one operation
for(i=0;i<string_size;i++){
fread(buffer+i, sizeof(unsigned char),1, handler);
if(i%16==0)
printf("\n");
printf("%02X ",*(buffer+i));
}
// fread doesn't set it so put a [=11=] in the last position
// and buffer is now officially a string
// buffer[string_size] = '[=11=]';
printf("Finished read\n");
// Always remember to close the file
fclose(handler);
}
return buffer;
}
int setAttribs (int fd, int speed, int parity)
{
struct termios tty;
memset (&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0)
{
fputs("error %d from tcgetattr", stderr);
}
cfsetospeed (&tty, speed);
cfsetispeed (&tty, speed);
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
// disable IGNBRK for mismatched speed tests; otherwise receive break
// as [=11=]0 chars
tty.c_iflag &= ~IGNBRK; // disable break processing
tty.c_lflag = 0; // no signaling chars, no echo,
// no canonical processing
tty.c_oflag = 0; // no remapping, no delays
tty.c_cc[VMIN] = 0; // read doesn't block
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
// enable reading
tty.c_cflag &= ~(PARENB | PARODD); // shut off parity
tty.c_cflag |= parity;
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CRTSCTS;
if (tcsetattr (fd, TCSANOW, &tty) != 0)
{
fputs("error %d from tcsetattr", stderr);
}
return 1;
}
它所做的只是在一个端口中写入 USB 串行转换器,并在另一个端口中读取。我只是用一个 8088 字节的 ODT 文件 (Hello World) 测试它,并尝试不同的波特率和写入块大小。经过反复试验,我发现这种配置(1500000 bps 和 1024 字节块)既快又相对可靠。唯一的错误如下所示。
Transmitted bytes: 70 6E 67 89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49
Received bytes: 70 6E 67 89 50 4E 47 0A 0A 1A 0A 00 00 00 0A 49
如您所见,所有“0D”字节都已更改为“0A”。我尝试了较低的波特率和较小的块大小,但问题仍然存在。我知道它们分别是 carriage return 和 line feed 值以及 line feed在Linux中用作异步通信的控制值;但我不明白为什么这会影响 carriage return 值。 回车return在串口通信中有什么特殊意义吗?在这种情况下,有没有办法发送“0D”字节?
TL;DR: 原始串行通信导致“0D”字节被“0A”替换。知道为什么吗?有什么办法解决吗?
非常感谢,它成功了!!我从来不知道有 ICRNL 选项可以将换行符转换为回车 returns。一旦我用
设置它和其他人tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); //tty is the name of the struct termios
它是金色的。