hi3516 uart1 485


原文链接: hi3516 uart1 485

Linux下串口编程

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

#define RS485_DEV                        "/dev/ttyAMA1"

CRS485::CRS485()
{
    hasRs485Inited = false;
    mFd = -1;
}

CRS485::~CRS485()
{
    DEBUG_INFO(DEV_MNG, "RS485 exit");
    if( mFd != -1 )
    {
        close( mFd );
    }
    hasRs485Inited = false;
}

int CRS485::setRS485(int band, int stopBit, int parity, int dataBit)
{
    int status = -1;

    struct termios options;
    tcgetattr( mFd, &options );
    tcflush( mFd, TCIOFLUSH ); // discard data written to RS485 that hasn't not been transmitted
    // set band rate
    switch( band )
    {
    case 1200:
        cfsetispeed( &options, B1200 );
        cfsetospeed( &options, B1200 );
        break;
    case 2400:
        cfsetispeed( &options, B2400 );
        cfsetospeed( &options, B2400 );
        break;
    case 4800:
        cfsetispeed( &options, B4800 );
        cfsetospeed( &options, B4800 );
        break;
    case 9600:
        cfsetispeed( &options, B9600 );
        cfsetospeed( &options, B9600 );
        break;
    case 19200:
        cfsetispeed( &options, B19200 );
        cfsetospeed( &options, B19200 );
        break;
    case 38400:
        cfsetispeed( &options, B38400 );
        cfsetospeed( &options, B38400 );
        break;
    case 57600:
        cfsetispeed( &options, B57600 );
        cfsetospeed( &options, B57600 );
        break;
    default:
        DEBUG_ERROR(DEV_MNG, "Band rate:%d is not supported, now use 9600", band);
        cfsetispeed( &options, B9600 );
        cfsetospeed( &options, B9600 );
        break;
    }
    status = tcsetattr( mFd, TCSANOW, &options );
    if( status != 0 )
    {
        DEBUG_API_ERROR( DEV_MNG, "tcsetattr(TCSANOW)");
        return -1;
    }
    tcflush( mFd, TCIOFLUSH );

    status = tcgetattr( mFd, &options );
    if( status < 0 )
    {
        DEBUG_API_ERROR( DEV_MNG, "tcgetattr()");
        return -1;
    }

    // set data bits
    options.c_cflag &= (~CSIZE);
    switch( dataBit )
    {
    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:
        DEBUG_ERROR(DEV_MNG, "Unsupported data bits(%d)", dataBit);
        return -1;
        break;
    }

    // set parity
    switch( parity )
    {
    case 0: // None
        options.c_cflag &= (~PARENB);
        options.c_iflag &= (~INPCK);
        break;
    case 1: // ODD
        options.c_cflag |= (PARODD | PARENB);
        options.c_iflag |= INPCK;
        break;
    case 2: // Even
        options.c_cflag |= PARENB;
        options.c_cflag &= (~PARODD);
        options.c_iflag |= INPCK;
        break;
    default:
        DEBUG_ERROR(DEV_MNG, "Unsupported parity type:%d", parity);
        return -1;
        break;
    }

    // set stop bits
    switch( stopBit )
    {
    case 1:
        options.c_cflag &= (~CSTOPB);
        break;
    case 2:
        options.c_cflag |= CSTOPB;
        break;
    default:
        DEBUG_ERROR(DEV_MNG, "Unsupported stop bits:%d", stopBit);
        return -1;
        break;
    }
    /* Set input parity option */
    if (parity != 0)
        options.c_iflag |= INPCK;
    /* Set Raw Mode */
    options.c_lflag  &= ~(ICANON | ECHO | ECHOE | ISIG);  /*Input*/
    options.c_oflag  &= ~OPOST;   /*Output*/
    tcflush( mFd, TCIFLUSH );
    options.c_cc[VTIME] = 150;
    options.c_cc[VMIN] = 7;

    status = tcsetattr( mFd, TCSANOW, &options );
    if( status != 0 )
    {
        DEBUG_API_ERROR(DEV_MNG, "tcsetattr()");
        return -1;
    }

    return 0;
}

int CRS485::init(int band, int stopBit, int parity, int dataBit)
{
    if( hasRs485Inited )
    {
        DEBUG_ERROR(DEV_MNG, "RS485 has been inited");
        return -1;
    }

    int ret = -1;

    // open device
    mFd = open( RS485_DEV, O_RDWR );
    if( mFd < 0 )
    {
        DEBUG_API_ERROR(DEV_MNG, "open()");
        return -1;
    }

    ret = setRS485(band, stopBit, parity, dataBit);
    if(ret == -1)
        goto ERROR;

    // success
    hasRs485Inited = 1;
    DEBUG_INFO(DEV_MNG, "RS485 init success");
    return 0;

ERROR:
    close( mFd );
    return -1;
}

int CRS485::sendData(char *data, int dataLen)
{
    if( data == NULL )
        return -1;
    if( dataLen <= 0 )
        return -1;

    if( hasRs485Inited != 1 )
    {
        DEBUG_ERROR(DEV_MNG, "Can't send 485 data before inited");
        return -1;
    }

    return write( mFd, data, dataLen );
}

int CRS485::recvData(char *data, int dataLen, int maxWaitTime)
{
    if( data == NULL )
        return -1;
    if( dataLen <= 0 )
        return -1;

    if( hasRs485Inited != 1 )
    {
        DEBUG_ERROR(DEV_MNG, "Can't recv 485 data before inited");
        return -1;
    }

    int index = 0;
    int rc = 0;
    int rcnum = dataLen;
    struct timeval tv;
    fd_set readfd;
    tv.tv_sec = maxWaitTime / 1000;
    tv.tv_usec = maxWaitTime % 1000 * 1000;
    FD_ZERO(&readfd);
    FD_SET(mFd, &readfd);
    rc = select(mFd + 1, &readfd, NULL, NULL, &tv);
    if(rc > 0)
    {
        while(dataLen)
        {
            rc = read(mFd, &data[index], 1);
            if(rc > 0)
                index = index + 1;
            dataLen = dataLen - 1;
        }
        if(index != rcnum)
            return -1;
        return rcnum;
    }
    else
    {
        return -1;
    }
    return -1;

    //return read( mFd, data, dataLen );
}
`