嵌入式linux UART驱动

来源:互联网 发布:win10装mac系统 编辑:程序博客网 时间:2024/05/18 03:40
 

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <string.h>

#include "appuart.h"

static int speed_arr[] = { B115200, B57600, B38400, B19200, B9600,
                            B4800, B2400, B1200, B600, B300,
                         };
static int name_arr[] = { 115200, 57600, 38400,  19200,  9600,
                            4800,  2400,  1200,  600, 300,
                        } ;

static int fd_uart[MAXNUM_UART] = {-1, -1, -1, -1};

//extern int semgprsuart;
extern struct gprsdev_t *gprs_devp;

#define SIZE_APPUART_RCVBUF  2048
struct appuart_rcvst
{
    char buf[SIZE_APPUART_RCVBUF];
    int len;
    int head;
};
static struct appuart_rcvst appuart_rcvbuf[MAXNUM_UART];

int appuart_open(unsigned int port)
{
    char dev[16];
    int fd;

    if(port >= MAXNUM_UART)
        return 1;

    if(-1 != fd_uart[port])
        close(fd_uart[port]);

    sprintf(dev, "/dev/ttyS%d", port+1);
    fd = open(dev, O_RDWR|O_NONBLOCK);
    if(-1 == fd)
        return 1;
// printf("uartport:%d,fd:%d\n",port,fd); //add by boll
    fd_uart[port] = fd;
    appuart_rcvbuf[port].len = 0;

    return 0;
}

void appuart_close(unsigned int port)
{
    if((port >= MAXNUM_UART) || (-1 == fd_uart[port]))
        return;

    close(fd_uart[port]);
    fd_uart[port] = -1;
}

void appuart_set_speed(unsigned int port, int speed)
{
    int i;
    int status;
    struct termios   Opt;
    int fd;

    if(port >= MAXNUM_UART)
        return;
    fd = fd_uart[port];
    if(fd < 0)
        return;

    tcgetattr(fd, &Opt);
    for ( i= 0;  i < sizeof(speed_arr) / sizeof(int);  i++)
    {
        if  (speed == name_arr[i])
        {
            tcflush(fd, TCIOFLUSH);
            cfsetispeed(&Opt, speed_arr[i]);
            cfsetospeed(&Opt, speed_arr[i]);
            status = tcsetattr(fd, TCSANOW, &Opt);
            if  (status != 0)
            {
                perror("tcsetattr fd1");
                return;
            }
            tcflush(fd,TCIOFLUSH);
        }
    }
}

void appuart_set_parity(unsigned int port, int databits,int stopbits, char parity)
{
    struct termios options;
    int fd;

    if(port >= MAXNUM_UART)
        return;
    fd = fd_uart[port];
    if(fd < 0)
        return;
    if(tcgetattr(fd, &options) != 0)
        return;

    options.c_iflag = 0;
    options.c_cflag &= ~CSIZE;

    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:
        return;
    }

    switch (parity)
    {
    case 'n':
    case 'N':
        options.c_cflag &= ~PARENB;  
        options.c_iflag &= ~INPCK;    
        break;
    case 'o':
    case 'O':
        options.c_cflag |= (PARODD | PARENB);
        options.c_iflag |= INPCK;            
        break;
    case 'e':
    case 'E':
        options.c_cflag |= PARENB;    
        options.c_cflag &= ~PARODD;  
        options.c_iflag |= INPCK;      
        break;
    case 'S':
    case 's': 
        options.c_cflag &= ~PARENB;
        options.c_cflag &= ~CSTOPB;
        break;
    default:
        return;
    }

   
    switch(stopbits)
    {
    case 1:
        options.c_cflag &= ~CSTOPB;
        break;
    case 2:
        options.c_cflag |= CSTOPB;
        break;
    default:
        return;
    }

    options.c_iflag &= ~(INLCR|IGNCR|ICRNL|IUCLC);  //add 2007-10-19
    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); 
    options.c_oflag &= ~OPOST;  

   
   

    tcflush(fd, TCIFLUSH);
    options.c_cc[VTIME] = 0;
    options.c_cc[VMIN] = 0;
    if (tcsetattr(fd, TCSANOW, &options) != 0)
        return;
}

void appuart_set(unsigned int port, int speed, int databits, int stopbits, char parity)
{
    appuart_set_speed(port, speed);
    appuart_set_parity(port, databits, stopbits, parity);
}

int appuart_send(unsigned int port, unsigned char *buf, int len)
{
    int fd;

    //if(0 == port) print_logo(0, "gprs port send\r\n");
    if(port >= MAXNUM_UART)
        return 1;

    //if(1 == port) print_logo(0, "232port send\r\n");
    fd = fd_uart[port];

    if(fd < 0)
        return 1;

// printf("Uart %d Send %d bytes:\nHEX:\n",port,len); //add by boll
// print_hexbuf(buf,len); //add by boll

    write(fd, (char *)buf, len);

// if(UART_GPRS == port) printf("gprssnd %s\n",buf);

   

    return 0;
}

int appuart_recv(unsigned int port, unsigned char *buf, int len)
{
    int fd, rtn;

    if(port >= MAXNUM_UART)
        return -1;
    fd = fd_uart[port];
    if(fd < 0)
        return -1;
    if(appuart_rcvbuf[port].len <= 0)
    {
        appuart_rcvbuf[port].len = 0;
        appuart_rcvbuf[port].head = 0;
        rtn = read(fd,appuart_rcvbuf[port].buf,SIZE_APPUART_RCVBUF);
        if((rtn <=0) || (rtn > SIZE_APPUART_RCVBUF))
            return 0;
        appuart_rcvbuf[port].len = rtn;
    }

    if(appuart_rcvbuf[port].len > len)
        rtn = len;
    else
        rtn = appuart_rcvbuf[port].len;

    memcpy(buf, &appuart_rcvbuf[port].buf[appuart_rcvbuf[port].head], rtn);
    appuart_rcvbuf[port].len -= rtn;
    appuart_rcvbuf[port].head += rtn;

    return rtn;
}

int appuart_getch(unsigned int port, unsigned char *buf)
{
    int fd, rtn;

    if(port >= MAXNUM_UART) return -1;
    fd = fd_uart[port];
    if(fd < 0) return -1;

    if(appuart_rcvbuf[port].len <= 0)
    {
        appuart_rcvbuf[port].len = 0;
        appuart_rcvbuf[port].head = 0;
        rtn = read(fd, appuart_rcvbuf[port].buf, SIZE_APPUART_RCVBUF);
        if((rtn <=0) || (rtn > SIZE_APPUART_RCVBUF)) return 0;
        appuart_rcvbuf[port].len = rtn;
        //printf( "rx %d\n",rtn);

    }

    if(appuart_rcvbuf[port].len > 0)
    {
        *buf = appuart_rcvbuf[port].buf[appuart_rcvbuf[port].head++];
        appuart_rcvbuf[port].len --;
        // print_hexbuf((UCHAR*)buf,12);
        return 1;
    }
    return -1;
}

int appuart_getfd(unsigned int port)
{
    if(port >= MAXNUM_UART)
        return -1;
    return(fd_uart[port]);
}