blob: 8136259eaf6575ac697c3e195c96de3161b8d0b4 [file] [log] [blame]
/**
* ±¾³ÌÐò·ûºÏ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);
}