当前位置:首页>Linux>RK3506 Linux系统开发(七):串口应用编程

RK3506 Linux系统开发(七):串口应用编程

  • 2026-09-10 01:29:22
RK3506 Linux系统开发(七):串口应用编程

概述

本文描述RK3506 Linux下串口的应用编程示例。在嵌入式行业中,串口编程也是我们的必备技能;

必备的技能

1、Linux下的文件读写编程技能;

2、Linux平台下的多线程编程;

串口编程代码流程

下面是经典的Linux平台上的串口编程框架代码:

#include<termios.h>#include<unistd.h>#include<stdlib.h>#include<fcntl.h>#include<linux/kernel.h>#include<stdio.h>#include<pthread.h>#include<string.h>#include<sys/select.h>#include<sys/time.h>static uart_fd = 0;#define BUFF_LIMIT_OTHER 255char rev_buf[BUFF_LIMIT_OTHER];staticvoidset_baudrate(struct termios *opt, unsignedint baudrate){cfsetispeed(opt, baudrate);cfsetospeed(opt, baudrate);}staticvoidset_stopbit(struct termios *opt, char stopbit){if (stopbit == '1') {        opt->c_cflag &= ~CSTOPB;    }elseif (stopbit == '2') {        opt->c_cflag |= CSTOPB;    }else {        opt->c_cflag &= ~CSTOPB;    }}staticvoidset_data_bit(struct termios *opt, unsignedint databit){    opt->c_cflag &= ~CSIZE;switch (databit) {case8:        opt->c_cflag |= CS8;break;case7:        opt->c_cflag |= CS7;break;case6:        opt->c_cflag |= CS6;break;case5:        opt->c_cflag |= CS5;break;default:        opt->c_cflag |= CS8;break;    }}staticvoidset_parity(struct termios *opt, char parity){switch (parity) {case'N':case'n':        opt->c_cflag &= ~PARENB;break;case'E':case'e':        opt->c_cflag |= PARENB;        opt->c_cflag &= ~PARODD;break;case'O':case'o':        opt->c_cflag |= PARENB;        opt->c_cflag |= ~PARODD;break;case'S':case's':        opt->c_cflag &= ~PARENB;        opt->c_cflag &= ~CSTOPB;        opt->c_iflag |= INPCK;break;default:        opt->c_cflag &= ~PARENB;break;    }}intset_uart_attr(int baudrate, int  databit, char stopbit,char parity, int vtime,int vmin){structtermios opt;tcgetattr(uart_fd, &opt);set_baudrate(&opt, baudrate);set_data_bit(&opt, databit);set_parity(&opt, parity);set_stopbit(&opt, stopbit);    opt.c_cflag &= ~CRTSCTS;    opt.c_cflag |= CLOCAL | CREAD;    opt.c_iflag &= ~(IXON | IXOFF | IXANY);    opt.c_oflag &= ~OPOST;    opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);    opt.c_cc[VMIN] = vmin;    opt.c_cc[VTIME] = vtime;tcflush (uart_fd, TCIFLUSH);return (tcsetattr (uart_fd, TCSANOW, &opt));}intget_uart_speed(int baudrate){int speed = 0;switch (baudrate) {case2400:        speed = B2400;break;case4800:        speed = B4800;break;case9600:        speed = B9600;break;case19200:        speed = B19200;break;case38400:        speed = B38400;break;default:case115200:        speed = B115200;break;    }return speed;}staticintuart_init(int baudrate, int  databit, char stopbit,  char parity){returnset_uart_attr(get_uart_speed(baudrate), databit, stopbit, parity, 1, BUFF_LIMIT_OTHER);}staticvoidoutput_hex(char *buf, int len){int i;printf("HEX: \n");for(i = 0; i < len; i++) {printf("%x ", buf[i]);    }printf("\n");}staticvoidoutput_ascii(char *buf, int len){printf("ASCII: \n");printf("[%d] %s", len, buf);}intuart_receive_thread(void){int r_count;int i;while(1) {memset(rev_buf, 0, sizeof(rev_buf));        r_count = read(uart_fd, rev_buf, sizeof(rev_buf));if(r_count > 0) {output_hex(rev_buf, r_count);output_ascii(rev_buf, r_count);        }    }}voiduart_send_thread(void){int s_count;char c = 0;char send_buf[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};while (1)    {sleep(2);printf("send: \n");        s_count = write(uart_fd, send_buf, 8);    }}intmain(int argc, char **argv){pthread_t id_Uart_Receive, id_Uart_Send;int ret1, ret2;    uart_fd = open(argv[1], O_RDWR | O_NOCTTY);if(uart_fd == -1) {printf("uart open failed!\n");exit(EXIT_FAILURE);   	}if(uart_init(9600, 8, 1, 'n') == -1) {printf("uart_init failed!\n");exit(EXIT_FAILURE);    }    ret1 = pthread_create(&id_Uart_Receive, NULL, (void *) uart_receive_thread, NULL);    ret2 = pthread_create(&id_Uart_Send, NULL, (void *) uart_send_thread, NULL);if(ret1 != 0) {printf ("Create Uart_Receive_thread error!\n");close(uart_fd);exit (1);    }if(ret2 != 0) {printf ("Create Uart_Send_thread error!\n");close(uart_fd);exit (1);    }while(1) {printf("This is the main process.\n");usleep(-1);    }pthread_join(id_Uart_Receive, NULL);pthread_join(id_Uart_Send, NULL);return0;}

编译测试

编译指令

这是我们第一次为ARM平台编译C程序。我们使用vmware + ubuntu下使用gcc编译,只能编译出在x86平台上运行的程序,为了能在RK3506 Linux平台上运行该程序,我们需要安装arm交叉工具链的东西,用来编译arm平台的程序,安装交叉编译指令如下所示:

sudo apt install -y gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf
安装完以后,我们将上面的代码保存为一个.c的文本文件,然后使用如下的指令进行编译
arm-linux-gnueabihf-gcc uart.c -o uart -lpthread
编译完成后,生成uart的可执行程序,我们可以使用file uart指令,可以看到该程序是arm平台运行的:

测试指令

我们使用如下的命令安装adb工具,

sudo apt install android-sdk-platform-tools

当我们编译后程序后,我们使用一个叫做adb工具,将该程序推送到RK3506 板子上

执行adb devices 检查我们的RK3506 板子是否已经连接

adb devices

如果RK3506 板子已经连接,可以看到如下的截图

然后,我们使用adb push命令将程序推送到板子上

adb push uart /userdata

我们使用如下的指令登录到我们的板子

adb shell

然后我们执行cd  /userdata,切换到userdata目录,然后执行ls uart 可以看到我们推送的文件

我们执行如下的指令开始测试

./uart /dev/ttyS3

测试结果如下所示:

总结

    本文是Linux 平台上串口编程框架代码和在RK3506 Linux平台上的实验过程。下一章,我们讲述基于串口的嵌入式行业常用的modbus协议解析。

最新文章

随机文章