Linux串口应用编程

news/2025/2/26 11:29:39

一、 串口API

在这里插入图片描述
在Linux系统中,操作设备的统一接口就是:open/ioctl/read/write。
对于UART,又在ioctl之上封装了很多函数,主要是用来设置行规程。
所以对于UART,编程的套路就是:

  • open
  • 设置行规程,比如波特率、数据位、停止位、检验位、RAW模式、一有数据就返回
  • read/write
    怎么设置行规程?行规程的参数用结构体termios来表示,可以参考Linux串口—struct termios结构体
typedef unsigned char 	cc_t;
typedef unsigned int 	speed_t;
typedef unsgined int 	tcflag_t;

#define NCCS 19
struct termios {
	tcflag_t c_iflag;		/* input mode flags */
	tcflag_t c_oflag;		/* output mode flags */
	tcflag_t c_cflag;		/* control mode flags */
	tcflag_t c_lflag;		/* local mode flags */
	cc_t c_line;			/* line discipline */
	cc_t c_cc[NCCS];		/* control characters */
};

这些函数在名称上有一些惯例:

  • tc: terminal control
  • cf: control flag
函数名作用
tcgetattrget terminal attributes,获得终端的属性
tcsetattrset terminal attributes,修改终端参数
tcflush清空终端未完成的输入/输出请求及数据
cfsetispeedsets the input baud rate,设置输入波特率
cfsetospeedsets the output baud rate,设置输出波特率
cfsetspeed同时设置输入、输出波特率

函数不多,主要是需要设置好termios中的参数,这些参数很复杂,可以参考Linux串口—struct termios结构体。

二、编程

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

int set_opt(int fd, int nSpeed, int nBits, char nEvent, int nStop)
{
	struct termios newtio, oldtio;
	
	if(tcgetattr(fd, &oldtio) != 0) {
		perror("SetupSerial 1");
		return -1;
	}

	bzero(&newtio, sizeof(newtio));
	newtio.c_cflag |= CLOCAL|CREAD;
	newtio.c_cflag &= ~CSIZE;

	newtio.c_lflag &= ~(ICANON|ECHO|ECHOE|ISIG);
	newtio.c_oflag &= ~OPOST;

	switch(nBits) {
	case 7:
		newtio.c_cflag |= CS7;
		break;
	case 8:
		newtio.c_cflag |= CS8;
		break;
	}

	switch(nEvent) {
	case 0:
		newtio.c_cflag |= PARENB;
		newtio.c_cflag |= PARODD;
		newtio.c_iflag |= (INPCK | ISTRIP);
		break;
	case 'E':
		newtio.c_iflag |= (INPCK|ISTRIP);
		newtio.c_cflag |= PARENB;
		newtio.c_cflag &= ~PARODD;
		break;
	case 'N':
		newtio.c_cflag &= ~PARENB;
		break;
	}

	switch(nSpeed) {
	case 2400:
		cfsetispeed(&newtio, B2400);
		cfsetospeed(&newtio, B2400);
		break;
	case 4800:
		cfsetispeed(&newtio, B4800);
		cfsetospeed(&newtio, B4800);
		break;
	case 9600:
		cfsetispeed(&newtio, B9600);
		cfsetospeed(&newtio, B9600);
		break;
	case 115200:
		cfsetispeed(&newtio, B115200);
		cfsetospeed(&newtio, B115200);
		break;
	default:
		cfsetispeed(&newtio, B9600);
		cfsetospeed(&newtio, B9600);
		break;
	}


	if(nStop == 1)
		newtio.c_cflag &= ~CSTOPB;
	else if(nStop == 2)
		newtio.c_cflag |= CSTOPB;

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

	tcflush(fd, TCIFLUSH);
	if((tcsetattr(fd, TCSANOW, &newtio)) != 0) {
		perror("com set error");
		return -1;
	}

	return 0;
}

int open_port(char *com)
{
	int fd;
	fd = open(com, O_RDWR|O_NOCTTY);
	if(-1 == fd) {
		return -1;
	}

	if(fcntl(fd, F_SETFL, 0) < 0) {
		printf("fcntl failed\n");
		return -1;
	}
	return fd;
}

int main(int argc, char *argv[])
{
	int fd;
	int iRet;
	char c;

	if(argc != 2) {
		printf("Usage: \n");
		printf("%s </dev/ttySAC1 or other>\n", argv[0]);
		return -1;
	}

	fd = open_port(argv[1]);
	if(fd < 0) {
		printf("open %s err!\n", argv[1]);
		return -1;
	}

	iRet = set_opt(fd, 115200, 8, 'N', 1);
	if(iRet) {
		printf("set port err!\n");
		return -1;
	}

	printf("Enter a char: ");
	while(1) {
		scanf("%c", &c);
		iRet = write(fd, &c, 1);
		iRet = read(fd, &c, 1);
		if(iRet == 1) {
			printf("get: %02x %c\n", c, c);
		} else {
			printf("can not get data\n");
		}
	}

	return 0;
}

三、上机实验

短接串口的RX和TX

root@npi:~/test# ./a.out /dev/ttymxc2 
Enter a cahr: a
get: 61 a
get: 0a 


get: 0a 

 
get: 0a 

a 
get: 61 a
get: 0a 


http://www.niftyadmin.cn/n/156035.html

相关文章

python绘制图像中心坐标二维分布曲线

数据和代码如下所示&#xff1a; import pandas as pd import numpy as np import matplotlib.pyplot as plt import xlrd from scipy.stats import multivariate_normal from mpl_toolkits.mplot3d import Axes3D np.set_printoptions(suppressTrue)# 根据均值、标准差,求指定…

es6的generator

一.generator函数的大致介绍 generator函数是es6引入的&#xff0c;主要用于异步编程 generator最大特点是交出函数的执行权&#xff08;即暂停执行&#xff0c;通过yield实现该功能&#xff09; 二.与普通函数写法的不同&#xff1a; 1. 函数名之前有个星号&#xff0c;以示…

《水经注地图服务》快速发布MBTiles数据

&#xff08;本文首发于“水经注GIS”公号&#xff0c;订阅“水经注GIS”公号&#xff0c;为你分享更多GIS技术 &#xff09;1、概述《水经注地图服务》的快速发布功能是一个能够帮助用户实现快速发布地图服务的功能&#xff0c;并且提供常规情况下大多数用户所需的默认配置&am…

Baklib在线帮助文档制作平台:让企业操作指南更容易编写的解决方案

Baklib在线帮助文档制作平台是一个免费的在线产品手册和帮助文档制作工具&#xff0c;专门为企业和普通用户提供方便和高效的帮助文档管理解决方案。在今天的商业环境中&#xff0c;企业需要随时随地根据客户和员工的需求提供最新和最有用的信息。因此&#xff0c;有一个易于使…

【论文翻译未完成】翻给自己看的 A Neural Probabilistic Language Model

学习路线&#xff1a;NLP经典论文导读&#xff08;推荐阅读顺序&#xff09; 原文&#xff1a;https://jmlr.csail.mit.edu/papers/v3/bengio03a.html 参考&#xff1a;论文阅读&#xff1a; 一种神经概率语言模型神经概率语言模型论文阅读&#xff1a; 一种神经概率语言模…

Java实现乐观锁和悲观锁

在开发中有些业务我们可能会使用到乐观锁或者悲观锁&#xff0c;但是具体使用场景需要结合具体业务需求和并发情况进行选择。下面用代码来简单实现两种锁 一、乐观锁 概念&#xff1a; 乐观锁从字面上来看就知道它是比较乐观的&#xff0c;它认为数据一般不会产生冲突&#xf…

opessh 在 arm linux 上移植

1 源码 版本匹配和兼容很重要&#xff0c;我不知道网上一些组合的版本是怎么调成功的&#xff0c;我这里使用 openssl-0.9.8以上的版本均失败。 版本&#xff1a;openssh-6.3.P1 wget -c https://github.com/openssh/openssh-portable/archive/refs/tags/V_6_3_P1.tar.gz tar…

C++中的利剑——vector的模拟实现

前文vector是stl库中非常重要的一个容器&#xff0c;熟练使用vector可以有效提高我们的代码效率以及逼格&#xff0c;而模拟实现vector能使我们深入了解vector一些重要机制以及使用方法。本文将带领铁子们完成vector一些重要接口的实现老规矩&#xff0c;源码结尾自取。一,vect…