Linux驱动:UART串口程序(亲测好用!)

1、前言

        本篇代码是配置串口的一些基本配置:波特率、校验位、数据位等。前提是内核中有对应的设备节点,可以在各自的开发板开发手册中找到串口所对应的设备节点。也是找了很多篇博主的文章参照,不过一开始配置的时候有问题打不开,最终还是一个一个配出来了。

2、代码

如果不能成功打开设备,使用则 ls /dev/ 命令看设备是否存在,若存在,可以用sudo chmod 666 /dev/tty 修改文件权限后重新运行程序。需要改变的该串口设备节点的权限

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>


int uart_open(const char *p_path)
{

    return open(p_path, O_RDWR | O_NOCTTY);
}

/**
 * 设置串口属性
 * fd:打开的串口设备的文件描述符
 * baudrate:波特率
 * {0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800,
 *              2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400}
 * bits:数据位
 *            #{5, 6, 7, 8}
 * parity:校验
 *            #'n'/'N':无校验
 *            #'o'/'O':奇校验
 *            #'e','E':偶校验
 * stop:停止位
 *            #1:1个停止位
 *            #2:2个停止位
 * flow:流控
 *            #'n'/'N':不使用流控
 *            #'h'/'H':使用硬件流控
 *            #'s'/'S':使用软件流控
 */
int uart_set(int fd, int baudrate, int bits, char parity, int stop, char flow)
{
    struct termios termios_uart;
    int ret = 0;
    speed_t uart_speed = 0;

    /* 获取串口属性 */
    memset(&termios_uart, 0, sizeof(termios_uart));
    ret = tcgetattr(fd, &termios_uart);
    if (ret == -1) {
        printf("tcgetattr failed\n");
        return -1;
    }

    //__print_termios(&termios_uart);

    /* 设置波特率 */
    switch (baudrate) {
        case 0:      uart_speed = B0;      break;
        case 50:     uart_speed = B50;     break;
        case 75:     uart_speed = B75;     break;
        case 110:    uart_speed = B110;    break;
        case 134:    uart_speed = B134;    break;
        case 150:    uart_speed = B150;    break;
        case 200:    uart_speed = B200;    break;
        case 300:    uart_speed = B300;    break;
        case 600:    uart_speed = B600;    break;
        case 1200:   uart_speed = B1200;   break;
        case 1800:   uart_speed = B1800;   break;
        case 2400:   uart_speed = B2400;   break;
        case 4800:   uart_speed = B4800;   break;
        case 9600:   uart_speed = B9600;   break;
        case 19200:  uart_speed = B19200;  break;
        case 38400:  uart_speed = B38400;  break;
        case 57600:  uart_speed = B57600;  break;
        case 115200: uart_speed = B115200; break;
        case 230400: uart_speed = B230400; break;
        default: printf("Baud rate not supported\n"); return -1;
    }
    cfsetspeed(&termios_uart, uart_speed);

    /* 设置数据位 */
    switch (bits) {
        case 5:     /* 数据位5 */
            termios_uart.c_cflag &= ~CSIZE;
            termios_uart.c_cflag |= CS5;
        break;

        case 6:     /* 数据位6 */
            termios_uart.c_cflag &= ~CSIZE;
            termios_uart.c_cflag |= CS6;
        break;

        case 7:     /* 数据位7 */
            termios_uart.c_cflag &= ~CSIZE;
            termios_uart.c_cflag |= CS7;
        break;

        case 8:     /* 数据位8 */
            termios_uart.c_cflag &= ~CSIZE;
            termios_uart.c_cflag |= CS8;
        break;

        default:
            printf("Data bits not supported\n");
            return -1;
    }

    /* 设置校验位 */
    switch (parity) {
        case 'n':   /* 无校验 */
        case 'N':
            termios_uart.c_cflag &= ~PARENB;
            termios_uart.c_iflag &= ~INPCK;        /* 禁能输入奇偶校验 */
        break;

        case 'o':   /* 奇校验 */
        case 'O':
            termios_uart.c_cflag |= PARENB;
            termios_uart.c_cflag |= PARODD;
            termios_uart.c_iflag |= INPCK;        /* 使能输入奇偶校验 */
            termios_uart.c_iflag |= ISTRIP;       /* 除去第八个位(奇偶校验位) */
        break;

        case 'e':   /* 偶校验 */
        case 'E':
            termios_uart.c_cflag |= PARENB;
            termios_uart.c_cflag &= ~PARODD;
            termios_uart.c_iflag |= INPCK;        /* 使能输入奇偶校验 */
            termios_uart.c_iflag |= ISTRIP;       /* 除去第八个位(奇偶校验位) */
        break;

        default:
            printf("Parity not supported\n");
            return -1;
    }

    /* 设置停止位 */
    switch (stop) {
        case 1: termios_uart.c_cflag &= ~CSTOPB; break; /* 1个停止位 */
        case 2: termios_uart.c_cflag |= CSTOPB;  break; /* 2个停止位 */
        default: printf("Stop bits not supported\n");
    }

    /* 设置流控 */
    switch (flow) {
        case 'n':
        case 'N':   /* 无流控 */
            termios_uart.c_cflag &= ~CRTSCTS;
            termios_uart.c_iflag &= ~(IXON | IXOFF | IXANY);
        break;

        case 'h':
        case 'H':   /* 硬件流控 */
            termios_uart.c_cflag |= CRTSCTS;
            termios_uart.c_iflag &= ~(IXON | IXOFF | IXANY);
        break;

        case 's':
        case 'S':   /* 软件流控 */
            termios_uart.c_cflag &= ~CRTSCTS;
            termios_uart.c_iflag |= (IXON | IXOFF | IXANY);
        break;

        default:
            printf("Flow control parameter error\n");
            return -1;
    }

    /* 其他设置 */
    termios_uart.c_cflag |= CLOCAL;    /* 忽略modem(调制解调器)控制线 */
    termios_uart.c_cflag |= CREAD;    /* 使能接收 */

    termios_uart.c_oflag &= ~OPOST;

    termios_uart.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);//设置本地模式位原始模式

    termios_uart.c_cc[VTIME] = 1;   /* 设置等待时间,单位1/10秒 */
    termios_uart.c_cc[VMIN]  = 1;    /* 最少读取一个字符 */

    tcflush(fd, TCIFLUSH);          /* 清空读缓冲区 */

    /* 写入配置 */
    ret = tcsetattr(fd, TCSANOW, &termios_uart);
    if (ret == -1) {
        printf("tcsetattr failed\n");
    }

    return ret;
}

int main(int argc, const char *argv[])
{
	unsigned char buf[100];
    /* 打开串口设备 */
    int fd = uart_open("/dev/ttyUSB0");
    if (fd < 0) {
        printf("open %s failed\n", UART_DEV_PATH);
        return 0;
    }

	int ret = uart_set(fd, 9600, 8, 'n', 1, 'n');
	if (ret == -1) {
		return 0;
	}

	int i = 0;
	int read_num = 0;
	int x = 0;
	while(1)
	{
		int num = read(fd, buf, sizeof(buf));
		write(fd, buf, sizeof(buf));
	}
	close(fd);
	return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zhaorming.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值