1、前言

       串口驱动是最简单的一种驱动了,在Linux下一切设备都认为是文件,打开设备就像打开文件一样简单,直接上代码

2、RS485.c

//--------------------------------------------------------------------------------------------------
// Include head files
//--------------------------------------------------------------------------------------------------
#include <stdio.h>
#include <string.h>
#include <fcntl.h> 
#include <termios.h> 
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/socket.h>

#include "RS485.h"

//-------------------------------------------------------------------------------------------------
// Private Definitions
//-------------------------------------------------------------------------------------------------

//-------------------------------------------------------------------------------------------------
// Private Members
//-------------------------------------------------------------------------------------------------


//-------------------------------------------------------------------------------------------------
// Private Functions
//-------------------------------------------------------------------------------------------------
static int SetAttributes(int fd, RS485PARA Rs485Para)
{
    struct termios newtio;

    bzero(&newtio, sizeof(newtio));

    newtio.c_cflag |= CLOCAL | CREAD;
    newtio.c_cflag &= ~CSIZE;

    switch (Rs485Para.m_Bits)
    {
        case SEVEN:
            newtio.c_cflag |= CS7;
            break;
        case EIGHT:
            newtio.c_cflag |= CS8;
            break;
        default:
            newtio.c_cflag |= CS8;
    }

    switch (Rs485Para.m_Parity)
    {
        case O:
            newtio.c_cflag |= PARENB;
            newtio.c_cflag |= PARODD;
            newtio.c_iflag |= (INPCK);
            break;
        case E:
            newtio.c_iflag |= (INPCK);
            newtio.c_cflag |= PARENB;
            newtio.c_cflag &= ~PARODD;
            break;
        case N:
            newtio.c_cflag &= ~PARENB;
            break;
        default:
            newtio.c_cflag &= ~PARENB;
    }

    switch (Rs485Para.m_BaudRate)
    {
        case B_9600:
            cfsetispeed(&newtio, B9600);
            break;
        case B_19200:
            cfsetispeed(&newtio, B19200);
            break;
        case B_38400:
            cfsetispeed(&newtio, B38400);
            break;
        case B_57600:
            cfsetispeed(&newtio, B57600);
            break;
        case B_115200:
            cfsetispeed(&newtio, B115200);
            break;
        default:
            cfsetispeed(&newtio, B19200);
    }

    if (Rs485Para.m_Stop == ONE)
    {
        newtio.c_cflag &= ~CSTOPB;
    }
    else if (Rs485Para.m_Stop == TWO)
    {
        newtio.c_cflag |= CSTOPB;
    }
    else
    {
        newtio.c_cflag &= ~CSTOPB;
    }

    newtio.c_cc[VTIME] = 5;
    newtio.c_cc[VMIN] = 0;

	tcflush(fd, TCOFLUSH);

    if ((tcsetattr(fd, TCSADRAIN, &newtio)) != 0)
    {
        printf("com set error:%s\n", strerror(errno));
        return -1;
    }

    return 0;
}

//-------------------------------------------------------------------------------------------------
// Public Functions
//-------------------------------------------------------------------------------------------------
int RS485Open(const char* pDevname, RS485PARA Rs485Para)
{
    int ret = 0;
	int fd = 0;
	int nZero = 0;

    if (NULL == pDevname)
    {
        printf("RS485 device name is null\n");
        return -1;
    }

    fd = open(pDevname, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
	
    if (fd > 0)
    {
        ret = SetAttributes(fd, Rs485Para);

        if (ret != 0)
        {
            printf("Set RS485 port failed, error=%s\n", strerror(errno));
            return -1;
        }
    }
    else
    {
        printf("Can't open the port %s,error=%s\n", pDevname, strerror(errno));
        return -1;
    }

    return fd;
}

int RS485Read(int fd, void* buf, int size)
{
    int nleft;
    int nread;
    char* ptr = NULL;

    ptr = buf;
    nleft = size;
 
    while (nleft > 0)
    {
    	nread = read(fd, ptr, nleft);
        if (nread <= 0)
        {
			break;
        }
            
        nleft -= nread;
        ptr += nread;
    }
	
    return (size - nleft);

}

int RS485Write(int fd, const void* buf, int size)
{
    int nleft = 0;
    int nwritten = 0;
    const char* ptr = NULL;
 	struct termios option;
	
    ptr = buf;
    nleft = size;
 
    while (nleft > 0)
    {
    	nwritten = write(fd, ptr, nleft);
    	if (nwritten <= 0)
        {
			break;
        }
		
        nleft -= nwritten;
        ptr   += nwritten;
    }
	
    return size;
}

int RS485Close(int fd)
{
    if (fd > 0)
    {
        close(fd);
    }
    else
    {
        return -1;
    }
    

    return 0;
}

3、RS485.h

#ifndef RS485_H
#define RS485_H

//-------------------------------------------------------------------------------------------------
// Public Includes
//-------------------------------------------------------------------------------------------------


//-------------------------------------------------------------------------------------------------
// Public Definitions
//-------------------------------------------------------------------------------------------------
enum BaudRate
{
    B_9600   = 0,
    B_19200  = 1,
    B_38400  = 2,
    B_57600  = 3,
    B_115200 = 4,
    B_40000  = 5,
    B_25000  = 6,
};

enum Bits
{
    SEVEN = 7,
    EIGHT = 8,
};

enum Parity
{
    O = 0,
    E = 1,
    N = 3,
};

enum Stop
{
    ONE = 1,
    TWO = 2,
};


//-------------------------------------------------------------------------------------------------
// Public Types
//-------------------------------------------------------------------------------------------------
typedef struct tag_RS485PARA
{
    unsigned char m_BaudRate;
    unsigned char m_Bits;
    unsigned char m_Parity;
    unsigned char m_Stop;
}RS485PARA;

//-------------------------------------------------------------------------------------------------
// Public Functions
//-------------------------------------------------------------------------------------------------

/**
 * Description: open a uart , rturn the fd
 *
 * @param pDevname          [in]  uart name with path
 * @param Rs485Para         [in]  uart parater which run correctly 
 * @return                  [out] fd value
 */
extern int RS485Open(const char *pDevname, RS485PARA Rs485Para);

/**
 * Description: read data to buf from fd
 *
 * @param fd                [in]  uart fd
 * @param buf               [in]  store data from uart 
 * @param size              [in]  data len from uart  
 * @return                  [out] data len to be read
 */
extern int RS485Read(int fd, void* buf, int size);

/**
 * Description: read data to buf from fd
 *
 * @param fd                [in]  uart fd
 * @param buf               [in]  store data from uart 
 * @param size              [in]  data len of buf  
 * @return                  [out] data len to be writen
 */
extern int RS485Write(int fd, const void *buf, const int size);

/**
 * Description: read data to buf from fd
 *
 * @param fd                [in]  uart fd
 * @return                  [out] RET_STATUS_OK if OK
 */
extern int RS485Close(int fd);
 
 
#endif 

4、总结

注意设置的方式是非阻塞,500毫秒等待时间,在外部程序中使用select/epool等方式去调用read读取数据就可以了

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐