问题描述
上周我一直在尝试用 C 语言实现一个原始的串行文件传输协议,但遇到了一个非常奇怪的问题,我似乎无法在线找到解决方案.我已经设法通过串行端口传输二进制数据并接收它,但在此过程中,所有的0D"字节被转换为0A".以下是我的代码.
I have been trying to implement a primitive serial file transfer protocol in C this past week and I've come across a really weird problem which I can't seem to find the solution for online. I've managed to transfer binary data over the serial port and receive it but in the process, all the "0D" bytes are converted to "0A". The following is my code.
#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
");
return -1;
}
//This character array will hold the file to be transferred
unsigned char* data = ' ';
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("
");
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!
");
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
",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("
");
printf("%02X ",*(buffer+i));
}
// fread doesn't set it so put a in the last position
// and buffer is now officially a string
// buffer[string_size] = ' ';
printf("Finished read
");
// 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 00 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 字节(Hello World)的 ODT 文件对其进行测试,并尝试不同的波特率和写入块大小.经过反复试验,我发现这种配置(1500000 bps 和 1024 字节块)既快速又相对更可靠.唯一的错误如下所示.
All it does is write to a USB-Serial converter in one port and read through the one in the other. I was just testing it with an ODT file which is 8088 bytes (Hello World) and was trying out different baudrates and write block sizes. After some trial and error, I found that this configuration (1500000 bps and 1024 byte blocks) was both fast and relatively more reliable. The only errors are as shown below.
传输字节数:70 6E 67 89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49
接收字节数:70 6E 67 89 50 4E 47 0A 0A 1A 0A 00 00 00 0A 49
Received bytes: 70 6E 67 89 50 4E 47 0A 0A 1A 0A 00 00 00 0A 49
如您所见,所有的0D"字节更改为0A".我尝试了较低的波特率和较小的块大小,但问题仍然存在.我理解它们分别是回车和换行值,换行在Linux中用作异步通信的控制值;但我不明白为什么这会影响 回车 值.回车在串口通信中有什么特殊意义吗?有没有办法发送0D"?在那种情况下跨字节?
As you can see all the "0D" bytes are changed to "0A". I've tried lower baudrates and smaller block sizes and the problem persists. I understand that they are the carriage return and line feed values respectively and that line feed is used as a control value for asynchronous communication in Linux; but I don't get why that would affect the carriage return values. Is there some special significance for carriage return in serial communication? Is there a way to send "0D" byte across in that case?
TL;DR: 原始串行通信导致0D";字节被替换为0A".知道为什么吗?有什么办法解决吗?
TL;DR: Raw serial communication results in "0D" bytes being replaced with "0A". Any idea why? Any way to solve?
推荐答案
非常感谢它成功了!我从来不知道有 ICRNL 选项可以将换行符转换为回车符.一旦我把它和其他人设置为
Thank you so much it worked!! I never knew that there was the ICRNL option which translates line feeds to carriage returns. Once I set that and others off with
tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); //tty is the name of the struct termios
它是金色的.
这篇关于串口二进制传输改回车的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!