| /** | |
| * ±¾³ÌÐò·ûºÏGPLÌõÔ¼ | |
| * Beneboy 2003-5-16 | |
| */ | |
| #include <stdio.h> // printf | |
| #include <fcntl.h> // open | |
| #include <string.h> // bzero | |
| #include <stdlib.h> // exit | |
| #include <sys/times.h> // times | |
| #include <sys/types.h> // pid_t | |
| #include <termios.h> //termios, tcgetattr(), tcsetattr() | |
| #include <unistd.h> | |
| #include <sys/ioctl.h> // ioctl | |
| #include "port_com.h" | |
| #include "amt.h" | |
| // ½ÓÊÕ³¬Ê± | |
| #define TIMEOUT_SEC(buflen,baud) (buflen*20/baud+1) | |
| #define TIMEOUT_USEC 0 | |
| // serial port information | |
| portinfo_t g_sPortInfo = | |
| { | |
| '0', // print prompt after receiving | |
| 115200, // baudrate: 115200 | |
| '8', // databit: 8 | |
| '0', // debug: off | |
| '0', // echo: off | |
| '0', // flow control: software | |
| '0', // default tty: COM1 | |
| '0', // parity: none | |
| '1', // stopbit: 1 | |
| 0 // reserved | |
| }; | |
| /** | |
| * ²¨ÌØÂÊת»¯×ª»»º¯Êý | |
| */ | |
| int convbaud(unsigned long int baudrate) | |
| { | |
| switch (baudrate) | |
| { | |
| case 2400: | |
| return B2400; | |
| case 4800: | |
| return B4800; | |
| case 9600: | |
| return B9600; | |
| case 19200: | |
| return B19200; | |
| case 38400: | |
| return B38400; | |
| case 57600: | |
| return B57600; | |
| case 115200: | |
| return B115200; | |
| case 921600: | |
| return B921600; | |
| default: | |
| return B9600; | |
| } | |
| } | |
| /** | |
| * Setup comm attr | |
| * fd: ´®¿ÚÎļþÃèÊö·û, pportinfo: ´ýÉèÖõĶ˿ÚÐÅÏ¢s | |
| * | |
| */ | |
| int PortSet(int fd) | |
| { | |
| struct termios termios_old, termios_new; | |
| int baudrate, tmp; | |
| char databit, stopbit, parity, fctl; | |
| bzero(&termios_old, sizeof(termios_old)); | |
| bzero(&termios_new, sizeof(termios_new)); | |
| cfmakeraw(&termios_new); | |
| tcgetattr(fd, &termios_old); //get the serial port attributions | |
| /*------------ÉèÖö˿ÚÊôÐÔ----------------*/ | |
| //baudrates | |
| baudrate = convbaud(g_sPortInfo.baudrate); | |
| cfsetispeed(&termios_new, baudrate); // ÌîÈë´®¿ÚÊäÈë¶Ë²¨ÌØÂÊ | |
| cfsetospeed(&termios_new, baudrate); // ÌîÈë´®¿ÚÊä³ö¶Ë²¨ÌØÂÊ | |
| termios_new.c_cflag |= CLOCAL; // ¿ØÖÆÄ£Ê½, ±£Ö¤³ÌÐò²»»á³ÉΪ¶Ë¿ÚµÄÕ¼ÓÐÕß | |
| termios_new.c_cflag |= CREAD; // ¿ØÖÆÄ£Ê½, ʹÄܶ˿ڶÁÈ¡ÊäÈëµÄÊý¾Ý | |
| // ¿ØÖÆÄ£Ê½, flow control | |
| fctl = g_sPortInfo.fctl; | |
| switch (fctl) | |
| { | |
| case '0': | |
| { | |
| termios_new.c_cflag &= ~CRTSCTS; //no flow control | |
| } | |
| break; | |
| case '1': | |
| { | |
| termios_new.c_cflag |= CRTSCTS; //hardware flow control | |
| } | |
| break; | |
| case '2': | |
| { | |
| termios_new.c_iflag |= IXON | IXOFF | IXANY; //software flow control | |
| } | |
| break; | |
| default: | |
| { | |
| printf("Unknown fctl %c\n", fctl); | |
| break; | |
| } | |
| } | |
| // ¿ØÖÆÄ£Ê½, data bits | |
| termios_new.c_cflag &= ~CSIZE; // ¿ØÖÆÄ£Ê½, ÆÁ±Î×Ö·û´óСλ | |
| databit = g_sPortInfo.databit; | |
| switch (databit) | |
| { | |
| case '5': | |
| termios_new.c_cflag |= CS5; | |
| //lint -fallthrough | |
| case '6': | |
| termios_new.c_cflag |= CS6; | |
| //lint -fallthrough | |
| case '7': | |
| termios_new.c_cflag |= CS7; | |
| //lint -fallthrough | |
| default: | |
| termios_new.c_cflag |= CS8; | |
| } | |
| // ¿ØÖÆÄ£Ê½ parity check | |
| parity = g_sPortInfo.parity; | |
| switch (parity) | |
| { | |
| case '0': | |
| { | |
| termios_new.c_cflag &= ~PARENB; // no parity check | |
| } | |
| break; | |
| case '1': | |
| { | |
| termios_new.c_cflag |= PARENB; // odd check | |
| termios_new.c_cflag &= ~PARODD; | |
| } | |
| break; | |
| case '2': | |
| { | |
| termios_new.c_cflag |= PARENB; // even check | |
| termios_new.c_cflag |= PARODD; | |
| } | |
| break; | |
| default: | |
| { | |
| printf("Unknown parity %c\n", parity); | |
| break; | |
| } | |
| } | |
| // ¿ØÖÆÄ£Ê½, stop bits | |
| stopbit = g_sPortInfo.stopbit; | |
| if (stopbit == '2') | |
| { | |
| termios_new.c_cflag |= CSTOPB; // 2 stop bits | |
| } | |
| else | |
| { | |
| termios_new.c_cflag &= ~CSTOPB; // 1 stop bits | |
| } | |
| //other attributions default | |
| termios_new.c_oflag &= ~OPOST; // Êä³öģʽ, ÔʼÊý¾ÝÊä³ö | |
| termios_new.c_cc[VMIN] = 1; // ¿ØÖÆ×Ö·û, ËùÒª¶ÁÈ¡×Ö·ûµÄ×îСÊýÁ¿ | |
| termios_new.c_cc[VTIME] = 1; // ¿ØÖÆ×Ö·û, ¶ÁÈ¡µÚÒ»¸ö×Ö·ûµÄµÈ´ýʱ¼ä, unit: (1/10)second | |
| tcflush(fd, TCIFLUSH); // Òç³öµÄÊý¾Ý¿ÉÒÔ½ÓÊÕ,µ«²»¶Á | |
| tmp = tcsetattr(fd, TCSANOW, &termios_new); // ÉèÖÃÐÂÊôÐÔ, TCSANOW: ËùÓɸıäÁ¢¼´ÉúЧ | |
| tcgetattr(fd, &termios_old); | |
| return(tmp); | |
| } | |
| /** | |
| * Open serial port | |
| * tty: ¶Ë¿ÚºÅ ttyS0, ttyS1, .... | |
| * ·µ»ØÖµÎª´®¿ÚÎļþÃèÊö·û | |
| */ | |
| int PortOpen(pportinfo_t pportinfo, int mode) | |
| { | |
| UNUSED(pportinfo); | |
| UNUSED(mode); | |
| return 0; | |
| } | |
| /** | |
| * Close serial port | |
| */ | |
| void PortClose(int fd) | |
| { | |
| close(fd); | |
| } | |
| /** | |
| * PortSend | |
| * fd: ´®¿ÚÃèÊö·û, | |
| * data: ´ý·¢ËÍÊý¾ÝÖ¸Õë | |
| * datalen: Êý¾Ý³¤¶È | |
| * flag: ·¢ËÍ·½Ê½±êʶ | |
| * ·µ»ØÊµ¼Ê·¢Ëͳ¤¶È | |
| */ | |
| int PortSend(int fd, unsigned char* data, int datalen, int flag) | |
| { | |
| int snRet = 0; | |
| if (flag == WAIT_ALL) | |
| { | |
| int offset = 0; | |
| while (offset < datalen) | |
| { | |
| snRet = write(fd, (data + offset), min(datalen - offset, 4096)); | |
| if (snRet > 0) | |
| { | |
| offset += snRet; | |
| } | |
| else | |
| { | |
| usleep(2*1000); | |
| } | |
| } | |
| return offset; | |
| } | |
| else | |
| { | |
| snRet = write(fd, data, datalen); | |
| return snRet; | |
| } | |
| } | |
| /** | |
| * PortRecv | |
| * ²ÎÊý£º | |
| * fd: ´®¿ÚÃèÊö·û, | |
| * data: ´ý½ÓÊÕÊý¾ÝÖ¸Õë | |
| * datalen: Êý¾Ý³¤¶È | |
| * flag: ½ÓÊÕ·½Ê½±êʶ | |
| * ·µ»ØÊµ¼Ê¶ÁÈëµÄ×Ö½ÚÊý | |
| */ | |
| int PortRecv(int fd, unsigned char* data, int datalen, int flag) | |
| { | |
| int snRet = 0; | |
| if (flag == WAIT_ALL) | |
| { | |
| int offset = 0; | |
| while (offset < datalen) | |
| { | |
| snRet = read(fd, (data + offset), (datalen - offset)); | |
| if (snRet > 0) | |
| { | |
| offset += snRet; | |
| } | |
| else | |
| { | |
| return snRet; | |
| } | |
| } | |
| return offset; | |
| } | |
| else | |
| { | |
| snRet = read(fd, data, datalen); | |
| return snRet; | |
| } | |
| } | |
| int uart_set(int fd) | |
| { | |
| struct termios termios_old, termios_new; | |
| int baudrate, tmp; | |
| char databit, stopbit, parity, fctl; | |
| portinfo_t uart_Info = | |
| { | |
| '0', // print prompt after receiving | |
| 921600, // baudrate: 921600 | |
| '8', // databit: 8 | |
| '0', // debug: off | |
| '0', // echo: off | |
| '0', // flow control: software | |
| '0', // default tty: COM1 | |
| '0', // parity: none | |
| '1', // stopbit: 1 | |
| 0 // reserved | |
| }; | |
| bzero(&termios_old, sizeof(termios_old)); | |
| bzero(&termios_new, sizeof(termios_new)); | |
| cfmakeraw(&termios_new); | |
| tcgetattr(fd, &termios_old); //get the serial port attributions | |
| /*------------ÉèÖö˿ÚÊôÐÔ----------------*/ | |
| //baudrates | |
| baudrate = convbaud(uart_Info.baudrate); | |
| cfsetispeed(&termios_new, baudrate); // ÌîÈë´®¿ÚÊäÈë¶Ë²¨ÌØÂÊ | |
| cfsetospeed(&termios_new, baudrate); // ÌîÈë´®¿ÚÊä³ö¶Ë²¨ÌØÂÊ | |
| termios_new.c_cflag |= CLOCAL; // ¿ØÖÆÄ£Ê½, ±£Ö¤³ÌÐò²»»á³ÉΪ¶Ë¿ÚµÄÕ¼ÓÐÕß | |
| termios_new.c_cflag |= CREAD; // ¿ØÖÆÄ£Ê½, ʹÄܶ˿ڶÁÈ¡ÊäÈëµÄÊý¾Ý | |
| // ¿ØÖÆÄ£Ê½, flow control | |
| fctl = uart_Info.fctl; | |
| switch (fctl) | |
| { | |
| case '0': | |
| { | |
| termios_new.c_cflag &= ~CRTSCTS; //no flow control | |
| } | |
| break; | |
| case '1': | |
| { | |
| termios_new.c_cflag |= CRTSCTS; //hardware flow control | |
| } | |
| break; | |
| case '2': | |
| { | |
| termios_new.c_iflag |= IXON | IXOFF | IXANY; //software flow control | |
| } | |
| break; | |
| default: | |
| { | |
| printf("Unknown fctl %c\n", fctl); | |
| break; | |
| } | |
| } | |
| // ¿ØÖÆÄ£Ê½, data bits | |
| termios_new.c_cflag &= ~CSIZE; // ¿ØÖÆÄ£Ê½, ÆÁ±Î×Ö·û´óСλ | |
| databit = uart_Info.databit; | |
| switch (databit) | |
| { | |
| case '5': | |
| termios_new.c_cflag |= CS5; | |
| //lint -fallthrough | |
| case '6': | |
| termios_new.c_cflag |= CS6; | |
| //lint -fallthrough | |
| case '7': | |
| termios_new.c_cflag |= CS7; | |
| //lint -fallthrough | |
| default: | |
| termios_new.c_cflag |= CS8; | |
| } | |
| // ¿ØÖÆÄ£Ê½ parity check | |
| parity = uart_Info.parity; | |
| switch (parity) | |
| { | |
| case '0': | |
| { | |
| termios_new.c_cflag &= ~PARENB; // no parity check | |
| } | |
| break; | |
| case '1': | |
| { | |
| termios_new.c_cflag |= PARENB; // odd check | |
| termios_new.c_cflag &= ~PARODD; | |
| } | |
| break; | |
| case '2': | |
| { | |
| termios_new.c_cflag |= PARENB; // even check | |
| termios_new.c_cflag |= PARODD; | |
| } | |
| break; | |
| default: | |
| { | |
| printf("Unknown parity %c\n", parity); | |
| break; | |
| } | |
| } | |
| // ¿ØÖÆÄ£Ê½, stop bits | |
| stopbit = uart_Info.stopbit; | |
| if (stopbit == '2') | |
| { | |
| termios_new.c_cflag |= CSTOPB; // 2 stop bits | |
| } | |
| else | |
| { | |
| termios_new.c_cflag &= ~CSTOPB; // 1 stop bits | |
| } | |
| //other attributions default | |
| termios_new.c_oflag &= ~OPOST; // Êä³öģʽ, ÔʼÊý¾ÝÊä³ö | |
| termios_new.c_cc[VMIN] = 1; // ¿ØÖÆ×Ö·û, ËùÒª¶ÁÈ¡×Ö·ûµÄ×îСÊýÁ¿ | |
| termios_new.c_cc[VTIME] = 1; // ¿ØÖÆ×Ö·û, ¶ÁÈ¡µÚÒ»¸ö×Ö·ûµÄµÈ´ýʱ¼ä, unit: (1/10)second | |
| tcflush(fd, TCIFLUSH); // Òç³öµÄÊý¾Ý¿ÉÒÔ½ÓÊÕ,µ«²»¶Á | |
| tmp = tcsetattr(fd, TCSANOW, &termios_new); // ÉèÖÃÐÂÊôÐÔ, TCSANOW: ËùÓɸıäÁ¢¼´ÉúЧ | |
| tcgetattr(fd, &termios_old); | |
| return(tmp); | |
| } | |