嵌入式Linux应用开发笔记:串口

2023-10-27

目的

串口(UART)是嵌入式设备中比较常用的功能。这篇文章将记录下应用程序中串口操作相关内容。

这篇文章中内容均在下面的开发板上进行测试:
《新唐NUC980使用记录:自制开发板(基于NUC980DK61YC)》

这篇文章是在下面文章基础上进行的:
《新唐NUC980使用记录(5.10.y内核):在用户应用中使用GPIO》

基础说明

Linux中应用程序对于串口的使用可以参考下面文章: https://digilander.libero.it/robang/rubrica/serial.htm
https://blog.csdn.net/qq_37932504/article/details/121125906

这里简单介绍下相关内容。Linux中应用程序对于串口的使用基本上也就是文件操作,使用 open / write / read 等方法。此外通常使用前需要通过 ioctl 方法来获取与设置串口的波特率、数据位、停止位、流控制等。对于串口而言部分设置在 ioctl 方法之上封装了一些函数,可以方便的进行操作。

串口的设置都集中在下面的结构体中:

struct termio
{
	unsigned short c_iflag; /* 输入模式标志 */
	unsigned short c_oflag; /* 输出模式标志 */
	unsigned short c_cflag; /* 控制模式标志*/
	unsigned short c_lflag; /*本地模式标志 */
	unsigned char c_line; /* 行规程标志 */
	unsigned char c_cc[NCC]; /* 控制字符标志 */
};

结构体中具体内容与设置可以参考上面文章。

开发准备

设备树

首先需要调整设备树来启用串口:

# cd ~/nuc980-sdk/NUC980-linux-5.10.y/
gedit arch/arm/boot/dts/nuc980-dev-v1.0.dts

这里启用了 uart1

uart1: serial@b0071000 {
	status = "okay";
};

根据 nuc980.dtsi 文件的中的定义 uart1 默认使用引脚为 PA0 - RXDPA1 - TXD

# 设置编译工具链
export ARCH=arm; export CROSS_COMPILE=arm-buildroot-linux-gnueabi-
export PATH=$PATH:/home/nx/nuc980-sdk/buildroot-2023.02/output/host/bin

# 编译生成设备树文件
make dtbs

# 编译完成后拷贝到电脑上再拷贝到SD卡中
# sudo cp arch/arm/boot/dts/nuc980-dev-v1.0.dtb /media/sf_common/

# 我这里开发环境和开发板在同一局域网中,所以可以直接通过网络将dtb文件拷贝到开发板上
# 在开发板中挂载boot分区
# mount /dev/mmcblk0p1 /mnt/
# 在ubuntu中使用scp命令拷贝dtb文件到开发板上
# scp arch/arm/boot/dts/nuc980-dev-v1.0.dtb root@192.168.31.142:/mnt/
# 拷贝完成后重启开发板即可测试
# reboot

加载新的设备树之后就可以测试新串口的功能了,使用外部的串口模块连接开发板和电脑:
在这里插入图片描述
可以看到使用默认波特率发送数据其实很简单,但是实际的使用过程中往往还需要修改串口设置以及接收数据等,所以就需要编写应用程序来处理。

应用程序

cd ~

# 创建目应用程序录并进入
mkdir -p ~/nuc980-sdk/apps/uart
cd ~/nuc980-sdk/apps/uart

# 创建应用程序文件
gedit uart_test.c

# 应用程序代码见下面章节

# 设置编译工具链
export ARCH=arm; export CROSS_COMPILE=arm-buildroot-linux-gnueabi-
export PATH=$PATH:/home/nx/nuc980-sdk/buildroot-2023.02/output/host/bin

# 编译生成目标应用程序
arm-linux-gcc -o uart_test uart_test.c

# 编译完成后拷贝到电脑上再拷贝到SD卡中
# sudo cp uart_test /media/sf_common/

# 我这里开发环境和开发板在同一局域网中,所以可以直接通过网络将文件拷贝到开发板上
# 在ubuntu中使用scp命令拷贝文件到开发板上
# scp uart_test root@192.168.31.142:/root/

应用程序与演示

代码

#include <stdio.h>   /* Standard input/output definitions */
#include <string.h>  /* String function definitions */
#include <unistd.h>  /* UNIX standard function definitions */
#include <fcntl.h>   /* File control definitions */
#include <errno.h>   /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */

int main(int argc, char **argv)
{
    int fd, ret;
    struct termios opt;
    char c;

	if (argc != 2)
	{
		printf("Usage: uart_test </dev/ttyX>\n");
		return -1;
	}

    /* 打开串口 */
    fd = open(argv[1], O_RDWR | O_NOCTTY | O_NDELAY);
    if (fd == -1)
    {
        printf("NX applog: can not open %s\n", argv[1]);
        return -1;
    }
    fcntl(fd, F_SETFL, 0); // 读取使用阻塞方式

    /* 设置串口属性 */
    // tcgetattr(fd, &opt); // 获取现有串口属性
    bzero(&opt, sizeof(opt)); // 以0填充结构体

    cfsetspeed(&opt, B115200); // 设置串口波特率

    opt.c_cflag |= CS8; // 8位数据位
    // opt.c_cflag &= ~PARENB; // 没有校验位
    // opt.c_cflag &= ~CSTOPB; // 1位停止位

    opt.c_cflag |= CREAD | CLOCAL;

	opt.c_cc[VMIN] = 1;	// 每次读取至少读到一个字节
	opt.c_cc[VTIME] = 0; // 读取操作不会超时

    tcflush(fd, TCIOFLUSH); // 清空当前输入/输出缓冲区数据

    ret = tcsetattr(fd, TCSANOW, &opt); // 使能串口设置
    if (ret != 0)
	{
		printf("NX applog: port set error\n");
		return -1;
	}

    /* 数据收发测试 */
    while (1) 
    {
        read(fd, &c, 1); // 
        printf("NX applog: read 0x%02x %c\n", c, c);
        write(fd, &c, 1);
    }

    close(fd);

    return 0;
}

演示

上面代码的作用是接收数据并回传,演示如下:
在这里插入图片描述

总结

串口操作总体来说并不复杂。另外虽然串口有很多可以设置的属性,但是目前很多属性已经不怎使用了,最常见需要修改的也就波特率了。

设备树文件

/*
 * Device Tree Source for NUC980 DEV board
 *
 * Copyright (C) 2018 Nuvoton Technology Corp.
 *
 * The code contained herein is licensed under the GNU General Public
 * License. You may obtain a copy of the GNU General Public License
 * Version 2 or later at the following locations:
 *
 * http://www.opensource.org/licenses/gpl-license.html
 * http://www.gnu.org/copyleft/gpl.html
 */
/dts-v1/;

#include "nuc980.dtsi"

/ {
	model = "Nuvoton NUC980 DEV V1.0";
	compatible = "nuvoton,nuc980-dev-v1.0", "nuvoton,nuc980";

	chosen {
		bootargs = "console=ttyS0,115200n8 noinitrd rootfstype=ext4 root=/dev/mmcblk0p2 rw rootwait mem=64M";
	};

	apb {
		uart1: serial@b0071000 {
			status = "okay";
		};

		uart2: serial@b0072000 {
			status = "disabled";
		};

		uart3: serial@b0073000 {
			status = "disabled";
		};

		uart4: serial@b0074000 {
			status = "disabled";
		};

		uart5: serial@b0075000 {
			status = "disabled";
		};

		uart6: serial@b0076000 {
			status = "disabled";
		};

		uart7: serial@b0077000 {
			status = "disabled";
		};

		uart8: serial@b0078000 {
			status = "disabled";
		};

		uart9: serial@b0079000 {
			status = "disabled";
		};

		can0: can@b00a0000 {
			status = "disabled";
		};

		can1: can@b00a1000 {
			status = "disabled";
		};

		rtc: rtc@b0041000 {
			status = "disabled";
		};

		gpio: gpio@b0004000 {
			pinctrl-0 = <>;
			eint2-config = <0 0 0>;
			eint3-config = <0 0 0>;
		};

		nadc: nadc@b0043000 {
			status = "disabled";
		};

		pwm0: pwm@b0058000 {
			status = "disabled";
		};

		pwm1: pwm@b0059000 {
			status = "disabled";
		};


		etimer0: etimer0@b0050000 {
			status = "disabled";
		};

		etimer1: etimer1@b0050100 {
			status = "disabled";
		};

		etimer2: etimer2@b0051000 {
			status = "disabled";
		};

		etimer3: etimer3@b0051100 {
			status = "disabled";
		};

		i2c0: i2c0@b0080000 {
			status = "disabled";
		};

		i2c1: i2c1@b0081000 {
			status = "disabled";
			pinctrl-0 = <&pinctrl_i2c1_PB>;
		};


		i2c2: i2c2@b0082000 {
			status = "disabled";
			pinctrl-0 = <&pinctrl_i2c2_PB>;
		};

	};

	ahb {

		usbh_ehci@b0015000 {
			pinctrl-0 = <>; /*disable PWREN and OVC*/
			ov_active = <1>;/*disable PWREN and OVC*/
			status = "okay";
		};
		usbh_ohci@b0017000{
			status = "okay";
		};

		usbdev@b0016000 {
			status = "okay";
		};

		fmi@b0019000 {
			status = "disabled";
		};

		sdh@b0018000 {
			status = "okay";
		};

		emac0@b0012000 {
			status = "okay";
		};
		emac1@b0022000 {
			status = "disabled";
		};
		ccap0@b0024000 {
			status = "disabled";
		};
		i2c_gpio0: i2c-gpio-0 {
			status = "disabled";
		};
		ccap1@b0014000 {
			status = "disabled";
		};
		i2c_gpio1: i2c-gpio-1 {
			status = "disabled";
		};
		dma@b0008000 {
			status = "okay";
		};

		i2s: i2s@b0020000 {
			status = "disabled";
		};

		i2s_pcm: i2s_pcm {
			status = "disabled";
		};

		sound {
			compatible = "nuvoton,nuc980-audio";
			i2s-controller = <&i2s>;
			i2s-platform = <&i2s_pcm>;
			status = "disabled";
		};
		ebi: ebi@b0010000 {
			status = "disabled";
		};
	};

	nx_node@0 {
		compatible = "nx_dts_node";
		str = "Naisu 233!";
		num = <0x00000000 0x00000020>;
	};
	
	nx_node@1 {
		compatible = "nx_dts_node";
		str = "Hello Naisu!";
		num = <0x000000 0x00000040>;
	};
};
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

嵌入式Linux应用开发笔记:串口 的相关文章

  • C#4做COM的时候需要调用Marshal.ReleaseComObject吗?

    我有 VS2010 并向我的项目添加了对 COM 库的引用 并且 VS 在项目中嵌入了主要互操作 如果我引用COM库中的对象并且我想快速处理它们而不等待GC 是否需要调用ReleaseComObject Marshal ReleaseCom
  • 如何从脚本编辑 /etc/sudoers?

    我需要编辑 etc sudoers从脚本中添加 删除白名单中的内容 假设我有一个可以处理普通文件的命令 我如何将其应用到 etc sudoers 我可以复制并修改它 然后有visudo用修改后的副本替换原始版本 通过提供我自己的脚本 EDI
  • Qt 嵌入式触摸屏 QMouseEvents 在收到 MouseButtonRelease 之前未收到

    我在带有触摸屏的小型 ARM 嵌入式 Linux 设备上使用 Qt 4 8 3 我的触摸屏配置了 tslib 并对其进行了校准 因此 etc 中有一个 pointcal 文件 我的触摸事件的位置工作得很好 但无论如何我都会在鼠标按下或鼠标释
  • 如何通过ssh获取远程命令的退出代码

    我正在通过 ssh 从远程计算机运行脚本 ssh some cmd my script 现在 我想在本地计算机上存储 shell 脚本的退出状态 我该怎么做 假设没有任何问题ssh其本身 其退出状态是在远程主机上执行的最后一个命令的退出状态
  • 选择fasta文件中氨基酸超过300个且“C”出现至少4次的序列

    我有一个包含蛋白质序列的 fasta 文件 我想选择超过 300 个氨基酸且半胱氨酸 C 氨基酸出现超过 4 次的序列 我使用此命令来选择具有超过 300 个 aa 的序列 cat 72hDOWN fasta fasta bioawk c
  • 如何将一个文本文件拆分为多个 *.txt 文件?

    我有一个文本文件file txt 12 MB 包含 something1 something2 something3 something4 有没有办法分开file txt分成 12 个 txt 文件 比方说file2 txt file3 t
  • Linux中如何避免sleep调用因信号而中断?

    我在 Linux 中使用实时信号来通知串行端口中新数据的到达 不幸的是 这会导致睡眠呼叫在有信号时被中断 有人知道避免这种行为的方法吗 我尝试使用常规信号 SIGUSR1 但我不断得到相同的行为 来自 nanosleep 联机帮助页 nan
  • 任何退出 bash 脚本但不退出终端的方法

    当我使用exitshell 脚本中的命令 该脚本将终止终端 提示符 有什么方法可以终止脚本然后停留在终端中吗 我的剧本run sh预计通过直接获取或从另一个脚本获取来执行 编辑 更具体地说 有两个脚本run2 sh as run sh ec
  • C++ Microsoft:如何将 uuid/guid 与模板专业化相关联

    我想将 uuid guid 与模板专业化相关联 以下代码可用于将 uuid 与非模板接口 类 结构 关联 interface declspec uuid CECA446F 2BE6 4AAC A117 E395F27DF1F8 ITest
  • 在本地主机上使用相同的 IP 和端口创建套接字

    我在 Linux 上看到奇怪的行为 我看到远程端和本地端都显示相同的 IP 和端口组合 以下是 netstat 输出 netstat anp 网络统计grep 6102 tcp 0 0 139 185 44 123 61020 0 0 0
  • Vagrant 遇到问题 - “404 - 未找到”

    我正在尝试使用 Vagrant 制作一个 LAMP 盒子 有人告诉我它使用起来非常简单 我对网络和虚拟机完全陌生 对 Linux Ubuntu 的经验也很少 我目前已尝试按照官方文档页面上的教程进行操作 http docs vagrantu
  • 在ubuntu中打开spyder

    我想在ubuntu中打开spyder Python IDE 通常我会在 shell 中编写 spyder 它会打开spyder IDE 现在 当我在shell中编写spyder时 它只是换行 什么也没有发生 类似于按 enter 我如何找回
  • Docker忽略limits.conf(试图解决“打开文件太多”错误)

    我正在运行一个 Web 服务器 该服务器正在处理数千个并发 Web 套接字连接 为了实现这一点 在 Debian linux 我的基本镜像是 google debian wheezy 在 GCE 上运行 上 打开文件的默认数量设置为 100
  • Python glob,操作系统,相对路径,将文件名放入列表中[重复]

    这个问题在这里已经有答案了 我正在尝试创建一个目录中所有文件的列表 其中文件名以 root 结尾 在阅读了论坛中的一些文章后 我尝试使用 glob 和 os listdir 的基本策略 但我都遇到了麻烦 首先 当我使用 import glo
  • Linux shell 从用户输入中获取设备 ID

    我正在为一个程序编写安装脚本 该程序需要在其配置中使用 lsusb 的设备 ID 因此我正在考虑执行以下操作 usblist lsusb put the list into a array for each line use the arr
  • COM 互操作注册

    我有一个正在暴露的 NET 程序集COM http en wikipedia org wiki Component Object Model 该程序集有两个公共接口和一个公共类 当我构建程序集时 我收到此警告 AssemblyName dl
  • 如何从 C++ 程序中重新启动 Linux?

    我有一个 Qt 4 GUI 我需要在下拉菜单中提供一个选项 允许用户选择重新启动计算机 我意识到这对于以其他方式重新启动计算机的能力来说似乎是多余的 但选择需要保留在那里 我尝试使用 system 来调用以下内容 suid root she
  • Linux无法删除文件

    当我找到文件时 我在删除它们时遇到问题 任务 必须找到带有空格的文件并将其删除 我的尝试 rm find L root grep i 但我有错误 rm cannot remove root test No such file or dire
  • Pythoncom - 将相同的 COM 对象传递给多个线程

    你好 对于 COM 对象 我是一个完全的初学者 非常感谢任何帮助 我正在开发一个Python程序 该程序应该以客户端 服务器的方式读取传入的MS Word文档 即客户端发送一个请求 一个或多个MS Word文档 服务器使用pythoncom
  • 找不到包“gdk-pixbuf-2.0”

    我正在尝试在 Amazon Linux 发行版实例上构建 librsvg 我已经通过 yum 安装了大部分依赖项 其中一些在实例上启用的默认 yum 存储库中不可用 因此必须从头开始构建它们 我已经走了很远 但还停留在最后一点 跑步时sud

随机推荐

  • TDR土壤水分检测传感器方案设计

    1 TDR土壤水分检测传感器方案 TDR 时域反射 法是介电测量中的高速测量技术 以 Feidegg 1969 等人对许多液体介电特性的研究为基础而发展起来的 最初被用来定位通讯电缆的缺陷 TDR 是一个类似于雷达系统的系统 有较强的独立性
  • chatgpt赋能python:如何把Python添加到Path

    如何把Python添加到Path Python是一种流行的编程语言 但是如果您想在命令行或终端中使用它 您需要将它添加到您的环境变量中 这篇文章将向您展示如何将Python添加到PATH中 以便您可以在任何地方使用Python 什么是PAT
  • 青少年编程python一级真题_青少年编程能力等级测评试卷二及答案 Python编程(一级)...

    青少年编程能力等级测评试卷 Python编程 一级 考试时间90分钟 满分100分 一 单项选择题 共20题 每题2 5分 共50分 1 运行下方代码段 输出是6 则输入的可能是 C a eval input print a A 8 2B
  • 《数据库系统概念》11-扩展的E-R特性

    虽然基本的E R特性可以应对大部分数据库建模 但为了使用方便 也提供扩展的E R特性一 特化Specialization有时一个实体集会保护若干子集 这些子集各自具有不同的属性 比如person可以包含employee和student子集
  • vsCode 配置 html 文件警告

    vsCode 配置 html 文件警告 问题描述 IDE vsCode 会默认根据自己的规则来检测 html 文件书写格式 但是在实际项目中模板的格式可能会有与规则有些不同 比如 第一行必须为声明 属性不能为空等 本人有点偏强迫症 要找办法
  • 创新造型,引领未来——探索OLED透明屏造型的创新与应用

    OLED透明屏作为一项颠覆性的显示技术 正在以其卓越的透明度和灵活性在各个行业中崭露头角 而在OLED透明屏的应用中 造型设计的创新成为了吸引消费者和提升用户体验的重要因素 一 OLED透明屏的特点 OLED透明屏采用有机发光二极管技术 其
  • python加载dll_C#初识 *.dll文件及动手编写简单应用

    DLL的概念 DLL Dynamic Link Library 文件为动态链接库文件 又称 应用程序拓展 是软件文件类型 在Windows中 许多应用程序并不是一个完整的可执行文件 它们被分割成一些相对独立的动态链接库 即DLL文件 放置于
  • SGD和Adam(转载)

    https blog csdn net weixin 42398658 article details 84525917 另在一篇文章中 我们介绍了随机梯度下降的细节以及如何解决陷入局部最小值或鞍点等问题 在这篇文章中 我们看看另一个困扰神
  • Unity3D编辑器扩展——EditorWindow交互响应事件

    重点 需要在OnGUI方法里监听事件 Unity的编辑器界面中由这么一些事件 EventType MouseDown 鼠标按下 MouseUp 鼠标抬起 MouseDrag 鼠标拖动 KeyDown 按键按下 KeyUp 按键抬起 Scro
  • js sum函数

    addnum function num1 num2 const num1Digits num1 toString split 1 length const num2Digits num2 toString split 1 length co
  • Qt新建项目No valid kits found解决思路

    第一次用Qt Creator创建Project时 进入Kit Selection窗口后 会提示No Valid kits found Please add a kit in the options
  • web性能测试基本性能指标

    文章出处 https blog csdn net qiguiting article details 11584397 Web性能测试的部分概况一般来说 一个Web请求的处理包括以下步骤 1 客户发送请求 2 web server接受到请求
  • Source Insight 4.0常用设置

    1 删除某一个或多个无用的project 历史project 用十六进制编辑器打开 我的文档 Source Insight 4 0 Projects project list sidb 文件 找到你要删除的项目路径及名称字符串 用0替换相关
  • TortoiseGit实现分支的新增、合并、删除详细教程

    分支的新增 合并 删除 关于git分支的操作 内容较多 所以从上篇博客 Windows下TortoiseGit客户端安装 中单独提取了出来 16 创建分支 Create Branch 关于Git Branch 在实际的项目开发过程中 这个非
  • ROS学习笔记(一)

    一 ROS安装与测试 Ubuntu和ROS版本的对应关系 网上教程很多 本人主要参考以下几篇 官网教程 全英文 ROS安装教程 ROS kinetic 超详细安装教程 安装过程中报错以及参考文章 均能有效解决 安装完ROS后 初始化rosd
  • 总结Pyinstaller的坑及终极解决方法

    一 首先要有个稳定环境 下面是博主经测试的觉得坑比较少的环境搭配 Python3 4 PyQt5 4 Pyinstaller3 2 1 Python3 5 PyQt5 8 Pyinstaller3 2 1 二 Pyinstaller遇到坑没
  • el-table表头无法居中显示(使用了cell-style和header-cell-style属性,也没有效果)----解决办法

    解决办法 cell style和header cell style属性要写在style前面
  • Windows Server 2016组策略限制用户登录到本机

    打开组策略 编辑 设置允许本地登录 拒绝本地登录 刷新组策略
  • 【EI会议征稿】第三届机械自动化与电子信息工程国际学术会议(MAEIE 2023)

    第三届机械自动化与电子信息工程国际学术会议 MAEIE 2023 第三届机械自动化与电子信息工程国际学术会议 MAEIE 2023 将于2023年12月15 17日在江苏南京举行 本会议通过与业内众多平台 社会各团体协力 聚集机械自动化 电
  • 嵌入式Linux应用开发笔记:串口

    文章目录 目的 基础说明 开发准备 设备树 应用程序 应用程序与演示 代码 演示 总结 设备树文件 目的 串口 UART 是嵌入式设备中比较常用的功能 这篇文章将记录下应用程序中串口操作相关内容 这篇文章中内容均在下面的开发板上进行测试 新