📄 rcv.c
字号:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h>#include <sys/stat.h> #include <fcntl.h> #include <termios.h> #include <errno.h> #define BL_NO_ERR 1#define BL_ERR_OPEN_COMM 100#define BL_ERR_OPEN_FILE 101#define BL_ERR_FILE_LENGTH 102#define TIMEOUT_SEC(len,baud) ((len)*20/(baud))#define TIMEOUT_USEC 500000#define RCVED_NAN 0x0#define RCVED_LEN 0x1#define RCVING_DATA 0x2#define CH_ACK_OK 0x5A#define CH_ACK_ERR 0xAA#define CH_PACK_LEN 0x55#define CH_PACK_DATA 0x5A#define CH_ACK_LEN_OK 0x55#define CH_ACK_DATA_OK 0x5Aint speed_arr[ ] = { B115200, B38400, B19200, B9600, B4800, B2400, B1200, B300, B115200, B38400, B19200, B9600, B4800, B2400, B1200, B300 };int name_arr[ ] = { 115200, 38400, 19200, 9600, 4800, 2400, 1200, 300, 115200, 38400, 19200, 9600, 4800, 2400, 1200, 300 };int fd_com; // the file descriptor of serial comint fd_file; // the file descriptor of save file int set_com (int fd, int speed, int fctl, int databits, int stopbits, int parity){ struct termios options; bzero(&options,sizeof(options)); cfmakeraw(&options); cfsetispeed(&options, speed); cfsetospeed(&options, speed); options.c_cflag |= CLOCAL; options.c_cflag |= CREAD; switch (fctl) { // flow control case 0: options.c_cflag &= ~CRTSCTS; break; case 1: options.c_cflag |= CRTSCTS; break; case 2: options.c_iflag |= (IXON | IXOFF | IXANY); break; default: printf("flow ctl err!\n"); return (-1); } options.c_cflag &= ~CSIZE; // data bits switch (databits) { case 5: options.c_cflag |= CS5; break; case 6: options.c_cflag |= CS6; break; case 7: options.c_cflag |= CS7; break; case 8: options.c_cflag |= CS8; break; default: printf("unsupported data size!\n"); return (-1); } switch (parity) { case 'n': case 'N': options.c_cflag &= ~PARENB; /* Clear parity enable */ break; case 'o': case 'O': options.c_cflag |= (PARODD | PARENB); break; case 'e': case 'E': options.c_cflag |= PARENB; /* Enable parity */ options.c_cflag &= ~PARODD; break; default: printf("unsupported parity!\n"); return (-1); } switch (stopbits) { case 1: options.c_cflag &= ~CSTOPB; break; case 2: options.c_cflag |= CSTOPB; break; default: printf("unsupported stop bits!\n"); return (-1); } options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /* set to raw input and output */ options.c_oflag &= ~OPOST; options.c_cc[VTIME] = 0; // 0 ms options.c_cc[VMIN] = 1; if (tcsetattr(fd,TCSANOW,&options) != 0) { /*Update the options and do it NOW */ printf("set com cfg err!\n"); return (-1); } tcflush(fd,TCIOFLUSH); // fulshs data received but not read, and data written but not transmitted. return 0;}int read_n (int fd, void *buf, int len){ int cou = 0; int ret = 0; fd_set fs_read; struct timeval tv_timeout; FD_ZERO (&fs_read); FD_SET (fd, &fs_read); tv_timeout.tv_sec = TIMEOUT_SEC (len, 115200); tv_timeout.tv_usec = TIMEOUT_USEC; while (len > 0) { if (select (fd+1, &fs_read, NULL, NULL, &tv_timeout)) { //检查设备是否可读 tv_timeout.tv_usec = 20000; ret = read (fd, (char*)buf+cou, len); if (ret < 1) { break; } cou += ret; len -= ret; } else { break; } } return cou;}int write_n (int fd, void *buf, int len){ int cou = 0; int ret = 0; fd_set fs_write; struct timeval tv_timeout; FD_ZERO (&fs_write); FD_SET (fd, &fs_write); tv_timeout.tv_sec = TIMEOUT_SEC (len, 115200); tv_timeout.tv_usec = TIMEOUT_USEC; while (len > 0) { if (select (fd + 1, NULL, &fs_write, NULL, &tv_timeout)) { tv_timeout.tv_usec = 20000; ret = write(fd, (char*)buf+cou, len); if (ret < 1) { break; } cou += ret; len -= ret; } else { tcflush(fd, TCOFLUSH); return -1; } } return cou;}int init_file_transfer (void){ fd_com = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NONBLOCK); if (-1 == fd_com) { printf("can't open serial port!\n"); return (BL_ERR_OPEN_COMM); } if (-1 == set_com (fd_com, B115200, 0, 8, 1, 'n')) { printf("set serial err!\n"); return (BL_ERR_OPEN_COMM); } //fd_file = open("/qte/myfile/down/mydata.dat", O_RDWR | O_CREAT); fd_file = open("/home/fa/down/mydata.dat", O_RDWR | O_CREAT); if (fd_file == -1) { printf("can't open file!\n"); close(fd_com); return BL_ERR_OPEN_FILE; } return (BL_NO_ERR);}int save_transfer_file (unsigned long total_len){ char buf[1030]; unsigned int save_len = 0; int len; int fd_file_sbr; unsigned long file_len = 0; char path[30]; fsync(fd_file); lseek(fd_file, 0, SEEK_SET); while (save_len < total_len) { len = read_n(fd_file, buf, 19); if (len != 19) { return (-1); } if (buf[0] != 'S') { return (-2); } strcpy(path, "/home/fa/down/"); //strcpy(path, "/qte/myfile/down/"); strcat(path, &buf[1]); //file path fd_file_sbr = open(path, O_RDWR | O_CREAT | O_TRUNC); if (-1 == fd_file_sbr) { return (-3); } //file_len = *(unsigned long*)&buf[15]; file_len = buf[15] | (buf[16] << 8) | (buf[17] << 16) | (buf[18] << 24); //printf("filelen = %d\n",file_len); save_len += (file_len + 20); while (file_len > 0) { if (file_len >= 1024) { len = 1024; } else { len = file_len; } if (len != read_n(fd_file, buf, len)) { close(fd_file_sbr); return (-4); } write_n(fd_file_sbr, buf, len); file_len -= len; } if (1 != read_n(fd_file, buf, 1)) { close(fd_file_sbr); return -5; } close(fd_file_sbr); if (buf[0] != 'E') { return -6; } } return total_len;}void end_file_transfer (void){ close(fd_file); close(fd_com); }int rcv_pack_head (unsigned char* head){ if (1 == read_n(fd_com, head, 1)) { return 0; } return -1; }unsigned char cal_chksum (unsigned char* buf, int len){ unsigned char sum = 0; int i; for (i = 0; i < len; i++) { sum += buf[i]; } return sum; }static unsigned char pack_no = 0; unsigned int rcv_lenth_pack (void){ unsigned char buf[255]; unsigned char ch_ack; unsigned short len; if (2 == read_n (fd_com, &len, 2)) { if (len >= 5 && len == read_n(fd_com, buf, len)) { //printf("rcved lenth = %d!\n", *(unsigned long*)buf); if (buf[len-1] == cal_chksum(buf, len-1)) { ch_ack = CH_ACK_LEN_OK; //printf("chksun ok!\n"); if (1 == write_n(fd_com, &ch_ack, 1)) { pack_no = 0; return *(unsigned long*)buf; } } else { ch_ack = CH_ACK_ERR; write_n(fd_com, &ch_ack, 1); } } } return 0; }unsigned int rcv_data_pack (void){ unsigned char buf[2060]; unsigned char ch_ack; unsigned short len; if (2 == read_n (fd_com, &len, 2)) { //printf("len = %d\n",len); if (len >= 3 && len == read_n(fd_com, buf, len)) { //printf("rcved data\n",len); if (buf[len-1] == cal_chksum(buf, len-1)) { //校验成功 ch_ack = CH_ACK_DATA_OK; if (1 == write_n(fd_com, &ch_ack, 1)) { //printf("snd checksum OK!\n"); if (buf[0] == pack_no) { ; //rcved repeat pack } else if (buf[0] == (unsigned char)(pack_no+1)) { if ((len-2) != write(fd_file, &buf[1], len-2)) { printf("write file err!\n"); } pack_no++; return (len-2); } else { printf("rcved pack_no err,pack_no = %d, rcv_no = %d!\n",pack_no,buf[0]); } } } else { //printf("checksum err!\n"); ch_ack = CH_ACK_ERR; write_n(fd_com, &ch_ack, 1); } } } return 0;}int main (void){ int status = RCVED_NAN; unsigned char head; unsigned long total_len,received_len,len; int percent, cnt = 0; if (BL_NO_ERR != init_file_transfer()) { printf("init file err!\n"); return (-1); } status = RCVED_NAN; while (1) { if (-1 == rcv_pack_head(&head)) { cnt ++; if (status == RCVED_NAN && cnt < 100) { continue; } else if (status == RCVED_LEN && cnt < 20) { continue; } else if (status == RCVING_DATA && cnt < 20) { continue; } else { printf("rcv packhead timeout!\n"); break; } } else { cnt = 0; } //printf("head = %2x\n",head); switch (head) { case CH_PACK_LEN: if (status != RCVING_DATA) { total_len = rcv_lenth_pack(); if (total_len > 0) { status = RCVED_LEN; received_len = 0; } else { total_len = 0; received_len = 0; status = RCVED_NAN; } } break; case CH_PACK_DATA: if (status == RCVED_LEN || status == RCVING_DATA) { len = rcv_data_pack(); if (len > 0) { received_len += len; status = RCVING_DATA; //printf("rcved len = %d\n", received_len); len = 100*received_len/total_len; if (len != percent) { percent = len; printf("receive percent = %d%\n", percent); } } } break; default: printf("unexpected msg!\n"); tcflush(fd_com, TCIFLUSH); break; } if (total_len > 0 && received_len >= total_len) { if (0 >= save_transfer_file (total_len)) printf("save data err!\n"); printf("over,received len = %d!\n", received_len); break; } } end_file_transfer();//save file and close comm port return(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -