linux 中的串口驱动

1.流程描述

        打开串口设备:首先需要打开串口设备文件,通常是/dev/ttyX(如/dev/ttyUSB0,/dev/ttyS0等)。可以使用open()系统调用打开串口设备文件,获取一个文件描述符。
        配置串口属性:打开串口后,需要配置串口的属性,例如波特率、数据位、奇偶校验、停止位等。可以使用termios库来设置串口属性。
        读写数据:串口配置完成后,可以使用read()和write()系统调用来进行串口数据的读取和写入。

        此外,还可以通过select()或poll()等系统调用进行多路复用,实现同时监听串口和其他文件描述符上的事件

2.open函数标志位的含义

在打开串口设备时,可以使用一些标志位(flags)来设置打开模式和行为。下面是常见的一些标志位及其含义:

  1. O_RDWR:以读写模式打开设备。允许读取和写入设备数据。

  2. O_NOCTTY:如果设备是终端设备(例如串口),不将它作为进程的控制终端。这通常用于防止串口设备接管终端特性(如终端窗口)。一般在打开串口设备时使用这个标志位。

  3. O_NDELAY(也叫O_NONBLOCK):将文件描述符设置为非阻塞模式。在非阻塞模式下,读取和写入文件描述符将立即返回。如果没有数据可读取,读取操作将返回-1,并将errno设置为EAGAIN。如果写入操作无法立即完成,将返回-1,并将errno设置为EAGAIN。不建议在打开串口时使用此标志位,因为在阻塞式读取串口数据时,我们希望等待数据的到达。

  4. O_RDONLY:以只读模式打开设备。只允许读取设备数据。

  5. O_WRONLY:以只写模式打开设备。只允许写入设备数据。

  6. O_CREAT:如果设备不存在,创建设备。在使用此标志位时,需要提供另外的参数,如文件权限。

  7. O_EXCL:与O_CREAT一起使用,确保创建新设备而不是打开现有设备。

  8. O_APPEND:以追加模式打开设备。每次写入操作都将数据追加到文件末尾。

  9. O_TRUNC:打开设备之前,先将其内容截断为零长度。

3.实现

/**
  ******************************************************************************
  * @file    bsp_uart.c
  * @author  cj
  * @version V1.0
  * @date    2019/4
  * @brief
  ******************************************************************************
  * @attention

  ******************************************************************************
  */

#include "bsp_uart.h"
#include "typedef.h"
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

static UartStatus initComm(const char *ttyDir, const int stop, const unsigned speed)
{
    UartStatus uartStatus;

    uartStatus.fd = -1;
    uartStatus.isEnabled = false;

    int retry = 60;

    uartStatus.fd = open(ttyDir, O_RDWR | O_NOCTTY /*| O_NDELAY*/);
    if (uartStatus.fd < 0)
    {
        CJdebug("can not open this driver\n");
        return uartStatus;
    }

    while (lockf(uartStatus.fd, F_TLOCK, 0) < 0)
    {
        sleep(1);
        retry--;
        if (retry <= 0)
        {
            CJdebug("Devcie %s locked.\n", ttyDir);
            close(uartStatus.fd);
            return uartStatus;
        }
    }

    unsigned currentSpeed = B9600;

    switch (speed)
    {
    case 9600:
        currentSpeed = B9600;
        break;
    case 38400:
        currentSpeed = B38400;
        break;
    case 57600:
        currentSpeed = B57600;
        break;
    case 115200:
        currentSpeed = B115200;
        break;
    default:
        CJdebug("speed error\n");
        return uartStatus;
    }

    struct termios Opt;
    tcgetattr(uartStatus.fd, &Opt);
    cfsetispeed(&Opt, currentSpeed);
    cfsetospeed(&Opt, currentSpeed);
    tcsetattr(uartStatus.fd, TCSANOW, &Opt);
    tcflush(uartStatus.fd, TCIOFLUSH);

    tcgetattr(uartStatus.fd, &Opt);

    /* Set data bit 8bit */
    Opt.c_cflag &= ~CSIZE;
    Opt.c_cflag |= CS8;

    Opt.c_cflag |= IXON | IXOFF | IXANY;
    /* Set parity bit: None parity bit */
    Opt.c_cflag &= ~PARENB;

    /* stop bit */
    switch (stop)
    {
    case 1:
        Opt.c_cflag &= ~CSTOPB;
        break;
    case 2:
        Opt.c_cflag |= CSTOPB;
        break;
    default:
        Opt.c_cflag &= ~CSTOPB;
        break;
    }

    Opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    Opt.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
    Opt.c_oflag &= ~OPOST;

    /* set timeout in deciseconds for non-canonical read */
    Opt.c_cc[VTIME] = 150; //over time
    Opt.c_cc[VMIN] = 0;    //DATA_LEN;

    if (tcsetattr(uartStatus.fd, TCSANOW, &Opt) < 0)
    {
        perror(ttyDir);
        close(uartStatus.fd);
        return uartStatus;
    }

    tcflush(uartStatus.fd, TCIOFLUSH);

    uartStatus.isEnabled = true;

    return uartStatus;
}

/**
 * @brief Uart_init
 * @param speed
 * @param stop
 * @param name
 * @return
 */
UartStatus uartInit(const unsigned speed, const int stop, const char *name)
{
    char dev[64] = {0};
    memset(dev, 0, sizeof(dev));
    sprintf(dev, "/dev/%s", name);
    UartStatus status = initComm(dev, stop, speed);

    return status;
}

int uart_readComm(UartStatus *uart, char *data, int dataLen)
{
    return read(uart->fd, data, dataLen);
}

bool uart_writeComm(UartStatus *uart, unsigned char *data, int dataLen)
{
    if(write(uart->fd, data, dataLen) < dataLen)
    {
        CJdebug("uartComm write error !\n");
        return false;
    }

    return true;
}

#ifndef BSP_UART_H
#define BSP_UART_H

#ifdef __cplusplus
extern "C" {
#endif

#include "typedef.h"

typedef struct _UartStatus
{
    int fd;
    bool isEnabled;
} UartStatus;

UartStatus uartInit(const unsigned speed, const int stop, const char *name);
bool uart_writeComm(UartStatus *uart, unsigned char *data, int dataLen);
int uart_readComm(UartStatus *uart, char *data, int dataLen);

#ifdef __cplusplus
}
#endif

#endif

 

你可能感兴趣的:(LINUX,linux,串口)