/** | |
* ±¾³ÌÐò·ûºÏ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); | |
} | |