#include <stdio.h>
#include <termios.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <strings.h>
#include <linux/types.h>
#include <stdarg.h>
static speed_t get_baudrate(unsigned int speed)
{
switch(speed)
{
case 0 : return B0;
case 50 : return B50;
case 75 : return B75;
case 110 : return B110;
case 134 : return B134;
case 150 : return B150;
case 200 : return B200;
case 300 : return B300;
case 600 : return B600;
case 1200 : return B1200;
case 1800 : return B1800;
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 230400 : return B230400;
case 460800 : return B460800;
case 500000 : return B500000;
case 576000 : return B576000;
case 921600 : return B921600;
case 1000000 : return B1000000;
case 1152000 : return B1152000;
case 1500000 : return B1500000;
case 2000000 : return B2000000;
case 2500000 : return B2500000;
case 3000000 : return B3000000;
case 3500000 : return B3500000;
case 4000000 : return B4000000;
default : return -1;
}
}
int uart_set(int fd, unsigned int speed, unsigned int databits,
unsigned int parity, unsigned int stopbits)
{
struct termios opts;
if(tcgetattr(fd, &opts))
{
printf("fail to tcgetattr in %s\b", __func__);
return -1;
}
cfsetispeed(&opts, get_baudrate(speed));
cfsetospeed(&opts, get_baudrate(speed));
opts.c_cflag &= ~CSIZE;
switch(databits)
{
case 7:
opts.c_cflag |= CS7;
break;
case 8:
opts.c_cflag |= CS8;
break;
default:
printf("invalid databits param in %s\n", __func__);
return -1;
}
switch(parity)
{
case 'n':
case 'N':
case 's':
case 'S':
opts.c_cflag &= ~PARENB;
opts.c_iflag &= ~INPCK;
break;
case 'o':
case 'O':
opts.c_cflag |= (PARODD | PARENB);
opts.c_iflag |= INPCK;
break;
case 'e':
case 'E':
opts.c_cflag |= PARENB;
opts.c_cflag &= ~PARODD;
opts.c_iflag |= INPCK;
break;
default:
printf("invalid parity param in %s\n", __func__);
return -1;
}
switch(stopbits)
{
case 1:
opts.c_cflag &= ~CSTOPB;
break;
case 2:
opts.c_cflag |= CSTOPB;
break;
default:
printf("invalid stopbits param in %s\n", __func__);
return -1;
}
opts.c_cc[VTIME] = 0; // 100ms为单位
opts.c_cc[VMIN] = 0;
tcflush(fd, TCIFLUSH);
opts.c_cflag |= CLOCAL;
opts.c_cflag |= CREAD;
opts.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
opts.c_oflag &= ~OPOST;
opts.c_iflag = 0x0;
if(tcsetattr(fd, TCSANOW, &opts))
{
printf("fail to tcsetattr in %s\n", __func__);
return -1;
}
return 0;
}
int init_uart(const char *name, unsigned int speed, unsigned int databits,
unsigned int parity, unsigned int stopbits)
{
int fd;
fd = open(name, O_RDWR | O_NOCTTY | O_NDELAY);
if(fd < 0)
{
printf("fail to open %s, in %s\n", name, __func__);
return -1;
}
if(uart_set(fd, speed, databits, parity, stopbits))
{
printf("fail to uart_set, in %s\n", __func__);
return -1;
}
return fd;
}
int send_uart(int fd, unsigned char *data, int len)
{
int ret;
int i;
tcflush(fd,TCOFLUSH);
if( (ret = write(fd, data, len)) != len)
{
printf("fail to write in %s, ret=%d\n", __func__, ret);
return -1;
}
return 0;
}
int recv_uart(int fd, unsigned char *data, unsigned int len, int flush, int sec, int usec)
{
int ret;
fd_set rfds;
struct termios opts;
struct timeval tv;
if(tcgetattr(fd, &opts))
{
printf("fail to tcgetattr in %s\n", __func__);
return -1;
}
opts.c_cc[VMIN] = len;
if(tcsetattr(fd, TCSANOW, &opts))
{
printf("fail to tcsetattr in %s\n", __func__);
return -1;
}
if(flush == 1)
{
tcflush(fd,TCIFLUSH);
}
while(1)
{
FD_ZERO(&rfds);
FD_SET(fd,&rfds);
if(sec < 0 || usec < 0)
{
ret = select(fd+1, &rfds, NULL, NULL, NULL);
}
else
{
tv.tv_sec = sec;
tv.tv_usec = usec;//100000us = 0.1s
ret = select(fd+1, &rfds, NULL, NULL, &tv);
}
if(ret < 0)
{
printf("fail to select in %s\n", __func__);
return -1;
}
else if(ret == 0) // time out
{
printf("select time out in %s\n", __func__);
return -1;
}
else
{
if(FD_ISSET(fd, &rfds))
{
if((ret = read(fd, data, len)) != len)
{
printf("fail to read in %s, ret=%d != len=%d\n", __func__, ret, len);
return -1;
}
else // success
{
return 0;
}
}
}
}
}
void deinit_uart(int fd)
{
close(fd);
}