当前位置: 首页 > news >正文

rk3568 OpenHarmony 串口uart与电脑通讯开发案例

一、需求描述:

        rk3568开发板运行OpenHarmony4.0,通过开发板上的uart串口与电脑进行通讯,相互收发字符串。

二、案例展示

        1、开发环境:

        (1)rk3568开发板

        (2)系统:OpenHarmony

        (3)电脑:Windows11笔记本,串口调试助手

        (4)Deveco Studio:evEco Studio 4.0 Release (4.0.0.600)

2、下载并运行开发案例

        下载开发案例,使用Deveco Studio打开运行编译、下载应用到rk3568开发板。开发板运行demo界面如下图所示。(.hap应用文件,见附件)

        (1)点击波特率选择按钮,选择相应的波特率;点击地址输入框,输入使用的串口的设备地址,这里以uart5(设备地址/dev/ttyS5)为例,选择波特率9600。  
 

        (2)将开发板通过串口转USB的转接线,将开发板与笔记本连接起来,电脑打开一个串口调试助手,如下图所示。

        (3)开发板点击“开启按钮”打开串口,然后点击“发送”按钮,想电脑通过串口发送输入框的字符串,电脑运行的串口调试助手接信息,并回显接收到的字符串;同理电脑通过串口调试助手想开发板发送字符串,开发板接收信息,并在回显框中回显接收到的字符串,如下图所示。

        (4)测试效果

OpenHarmony串口通讯展示

        注意:运行demo,应确保开发板的串口节点已被引出可用,且读写权限已被允许

三、应用开发流程

       该应用的开发,使用NAPI方式来编写使用串口的NAPI函数,通过这些函数,来对串口进行设置,打开,发送和接收数据(NAPI使用,详见NAPI篇)。在应用界面编写中,引用NAPI函数进行逻辑构建,完成应用开发。

         1、应用界面编写(Index.ets)

import BQNapi from 'libentry.so';//引入NAPI
import promptAction from '@ohos.promptAction';const TAG = "uartToComputer"@Entry
@Component
struct Index {@State isStart: boolean = false;private dateTime: Date = new Date();private scroller: Scroller = new Scroller()@State receiveMessage: string = '';@State sendMessage: string = 'https://www.bearkey.net/';@State currentUart: string = '';private UartPort: string = '/dev/ttyS5'private UartBand: string[] = ['9600', '19200', '38400', '57600', '115200']private UartBand_N: number[] = [9600, 19200, 38400, 57600, 115200]@State currentUartBandIndex: number = 0@State bandRate: number = 0;private fd: number = -1;private setIntervalID: number = -1;aboutToAppear() {// this.fd = BQNapi.open_port(this.currentUart, 115200);// console.log(TAG, `打开串口${this.currentUart},ret=${this.fd}`)this.setIntervalID = setInterval(() => {//判断是否有串口开启if (this.fd > 0) {//获取开启状态this.isStart = true//获取波特率this.bandRate = BQNapi.getBandRate(this.fd)let temp: string = BQNapi.series_receive_data(this.fd);if (temp === "-1") {console.log(TAG, '未接收到数据或接收失败');} else {this.dateTime = new Date();let year: number = this.dateTime.getFullYear(); //当前年let month = this.dateTime.getMonth() + 1;let date = this.dateTime.getDate();let hours = this.dateTime.getHours();let minutes = this.dateTime.getMinutes();let seconds = this.dateTime.getSeconds();let curryDateTime: string = year + '-' + month + '-' + date + ' ' + hours + ':' + minutes + ':' + seconds;temp = curryDateTime + '\n' + temp;this.receiveMessage = temp + this.receiveMessagethis.scroller.scrollTo({ xOffset: 0, yOffset: 0 })}} else {this.isStart = falsethis.bandRate = 0;this.currentUart = '-'}}, 300)}aboutToDisappear() {console.log(TAG, `退出应用`)clearInterval(this.setIntervalID);if (this.fd > 0) {let e: number = BQNapi.close_port(this.fd);console.log(TAG, `关闭串口${this.currentUart},ret=${e}`)if (e == 0) {console.log(TAG, `关闭成功`)} else {console.log(TAG, `关闭失败`)}}}build() {Column() {Row() {Text('回显框').fontSize(25).size({ width: '50%', height: 30 })Button('清空窗口').fontSize(30).size({ width: 160, height: 40 }).onClick(() => {this.receiveMessage = '';});}.justifyContent(FlexAlign.SpaceAround).margin({ top: 10, }).size({ width: '100%', height: 50 })Scroll(this.scroller) {Column() {Text(this.receiveMessage).fontSize(20).size({ width: '100%' }).constraintSize({ minHeight: 30 }).margin({ top: 10, bottom: 10 }).padding(10).textAlign(TextAlign.Start)}.size({ width: '100%' }).constraintSize({ minHeight: 300 }).justifyContent(FlexAlign.Start)}.size({ width: '100%', height: 150 }).border({ width: 1, style: BorderStyle.Solid, radius: 10 })Row() {Text('输入框').fontSize(25).size({ width: '100%', height: 40 })}.justifyContent(FlexAlign.SpaceAround).margin({ top: 10, }).size({ width: '100%', height: 50 })TextInput({ placeholder: "请输入需要发送的内容...", text: this.sendMessage }).fontSize(25).size({ width: '100%', height: 50 }).border({ width: 1, style: BorderStyle.Solid, radius: 10 }).margin({ bottom: 10 }).onChange((value) => {this.sendMessage = value;})Row() {Button('发送').fontSize(30).enabled(this.isStart).size({ width: 120, height: 40 }).onClick(() => {let a: number = BQNapi.series_send_data(this.sendMessage, this.fd)if (a === 0) {console.log(TAG, "发送成功!");} else {console.log(TAG, "发送失败!");}})Button('清空').fontSize(30).enabled(this.isStart).size({ width: 120, height: 40 }).onClick(() => {this.sendMessage = '';})}.justifyContent(FlexAlign.SpaceAround).margin({ top: 10, }).size({ width: '100%', height: 50 })Row() {Text('当前串口信息').fontSize(25).size({ width: '100%', height: 30 })}.justifyContent(FlexAlign.SpaceAround).margin({ top: 10, }).size({ width: '100%', height: 50 })Column() {Row() {Text('波特率:').fontSize(25).size({ width: '40%', height: 30 }).textAlign(TextAlign.Center)Text(this.bandRate.toString()).fontSize(28).size({ width: '60%', height: 30 }).textAlign(TextAlign.Center)}.justifyContent(FlexAlign.SpaceAround).size({ width: '100%', height: 40 })Row() {Text('当前串口:').fontSize(25).size({ width: '40%', height: 30 }).textAlign(TextAlign.Center)Text(this.currentUart).fontSize(28).size({ width: '60%', height: 30 }).textAlign(TextAlign.Center)}.justifyContent(FlexAlign.SpaceAround).size({ width: '100%', height: 40 })}.size({ width: '100%', height: 100 }).justifyContent(FlexAlign.SpaceAround).border({ width: 1, style: BorderStyle.Solid, radius: 10 })Row() {Button(this.UartBand[this.currentUartBandIndex]).fontSize(25).size({ width: '30%', height: 45 }).onClick(() => {this.showPickerDialogForUartBand()})TextInput({ placeholder: "请输入串口地址", text: this.UartPort }).fontSize(25).border({ width: 1, style: BorderStyle.Solid, radius: 10 }).size({ width: '60%', height: 45 }).onChange((value) => {this.UartPort = value;})}.justifyContent(FlexAlign.SpaceAround).margin({ top: 10, }).size({ width: '100%', height: 50 })Row() {Button("开启").fontSize(35).size({ width: '30%', height: 45 }).backgroundColor(this.isStart ? Color.Green : Color.Blue).onClick(() => {if (this.isStart) {promptAction.showToast({message: "请先停止当前串口",duration: 500})} else {this.fd = BQNapi.open_port(this.UartPort, this.UartBand_N[this.currentUartBandIndex]);if (this.fd > 0) {console.log(TAG, `打开串口${this.currentUart},ret=${this.fd}`)this.currentUart = this.UartPort;promptAction.showToast({message: "开启成功",duration: 500})} else {promptAction.showToast({message: "开启失败",duration: 500})}}})Button('停止').fontSize(35).size({ width: '30%', height: 45 }).backgroundColor(this.isStart ? Color.Red : Color.Blue).onClick(() => {if (this.isStart) {let e: number = BQNapi.close_port(this.fd);console.log(TAG, `关闭串口${this.currentUart},ret=${e}`)if (e == 0) {promptAction.showToast({message: "关闭成功",duration: 500})this.fd = -1;this.currentUart = '...'console.log(TAG, `关闭成功`)} else {console.log(TAG, `关闭失败`)promptAction.showToast({message: "关闭失败",duration: 500})}} else {promptAction.showToast({message: "未启用串口",duration: 500})}})}.justifyContent(FlexAlign.SpaceAround).margin({ top: 20, }).size({ width: '100%', height: 50 })}.size({ width: '100%', height: '100%' }).padding(10).justifyContent(FlexAlign.Start).alignItems(HorizontalAlign.Center)}showPickerDialogForUartBand() {TextPickerDialog.show({range: this.UartBand,selected: this.currentUartBandIndex,disappearTextStyle: { color: Color.Red, font: { size: 15, weight: FontWeight.Lighter } },textStyle: { color: Color.Black, font: { size: 20, weight: FontWeight.Normal } },selectedTextStyle: { color: Color.Blue, font: { size: 30, weight: FontWeight.Bolder } },onAccept: (value: TextPickerResult) => {let temp = value.value as stringthis.currentUartBandIndex = value.index as number},onCancel: () => {console.info(TAG, "TextPickerDialog:onCancel()")},onChange: (value: TextPickerResult) => {console.info(TAG, "TextPickerDialog:onChange()" + JSON.stringify(value))}})}
}

        2、NAPI函数引出声明(index.d.ts)

export const open_port: (port_address: string, band_rate: number) => number; //打开串口,打开成功返回描述符(int),失败-1export const close_port: (serial_port: number) => number; //关闭串口,关闭成功返回0,失败则返回-1.export const series_send_data: (tx_data: string, serial_port: number) => number; //发送数据export const series_receive_data: (serial_port: number) => string; //接收数据,成功返回接收字符串,失败返回-1export const getBandRate: (serial_port: number) => number; //查询波特率,成功返回波特率,失败返回-1

        3、完整应用工程源码,私信

声明:非本人允许,严禁转载,演示开发板为厦门贝启科技的BQ3568HM产品

(1)首页-贝启科技官方企业店-淘宝网

(2)厦门贝启科技有限公司-Bearkey-官网

相关文章:

rk3568 OpenHarmony 串口uart与电脑通讯开发案例

一、需求描述: rk3568开发板运行OpenHarmony4.0,通过开发板上的uart串口与电脑进行通讯,相互收发字符串。 二、案例展示 1、开发环境: (1)rk3568开发板 (2)系统:OpenHar…...

canvas画布旋转问题

先说一下为什么要旋转的目的:因为在画布上签名,在不同的设备上我需要不同方向的签名图片,电脑是横屏,手机就是竖屏,所以需要把手机的签名旋转270,因此写了这个方法。 关于画布旋转的重点就是获取到你的画布…...

vue3 【提效】自动导入框架方法 unplugin-auto-import 实用教程

是否还在为每次都需要导入框架方法而烦恼呢? // 每次都需手动导入框架方法 import { ref } from vuelet num ref(0)用 unplugin-auto-import 来帮你吧,以后只需这样写就行啦! let num ref(0)官方示例如下图 使用流程 1. 安装 unplugin-au…...

clip系列改进Lseg、 group ViT、ViLD、Glip

Lseg 在clip后面加一个分割head,然后用分割数据集有监督训练。textencoder使用clip,frozen住。 group ViT 与Lseg不同,借鉴了clip做了真正的无监督学习。 具体的通过group block来做的。使用学习的N个group token(可以理解为聚类…...

Ubuntu下TensorRT与trtexec工具的安装

新版(这里测试的是10.1版)的onnx转tensorrt engine工具trtexec已经集成在TensorRT中,不需要额外单独安装。 教程来源于此网页:https://medium.com/moshiur.faisal01/install-tensorrt-with-command-line-wrapper-trtexec-on-unun…...

MySQL定时任务

事件调度器操作 查看事件调度器是否开启:ON 表示已开启。 show variables like %event_scheduler%; ------------------------ | Variable_name | Value | ------------------------ | event_scheduler | ON | ------------------------ 开启和关闭事件调度器…...

Pandas实用Excel数据汇总

Pandas 是一个开源的 Python 库,由 Wes McKinney 开发,专门用于高效地处理和分析数据,无论是小规模的数据实验还是大规模的数据处理任务。它构建在 NumPy 之上,这意味着它利用了 NumPy 的高性能数组计算能力。Pandas 的核心数据结…...

【计算机网络】[第4章 网络层][自用]

1 概述 (1)因特网使用的TCP/IP协议体系(四层)的网际层,提供的是无连接、不可靠的数据报服务; (2)ATM、帧中继、X.25的OSI体系(七层)中的网络层,提供的是面向连接的、可靠的虚电路服务。 (3)路由选择分两种: 一种是由用户or管理员人工进行配置(只适用于规…...

Unity3D Entity_CacheService实现详解

Unity3D是一款广泛使用的游戏开发引擎,它提供了丰富的功能和工具来帮助开发者创建高质量的游戏和互动体验。在Unity开发过程中,资源管理是一个重要的环节,特别是当项目规模逐渐增大,资源数量变多时。为了优化资源的加载和管理&…...

DLMS/COSEM协议—(Green-Book)Gateway protocol

DLMS/COSEM协议 — Gateway protocol 10.10 Gateway protocol (网关协议)10.10.1 概述10.10.2 网关协议 (The gateway protocol)10.10.3 HES在WAN/NN中作为发起者(拉取操作)10.10.4 LAN中的终端设备作为发起…...

Android高级面试_12_项目经验梳理

Android 高级面试-1:Handler 相关 问题:Handler 实现机制(很多细节需要关注:如线程如何建立和退出消息循环等等) 问题:关于 Handler,在任何地方 new Handler 都是什么线程下? 问题&#xff1a…...

【项目实训】解决前后端跨域问题

由于前端框架使用vue,后端使用flask,因此需要解决前后端通信问题 在vue.config.js中修改 module.exports defineConfig({transpileDependencies: true,lintOnSave:false, }) // 跨域配置 module.exports {devServer: { //记住&#x…...

Java反射API详解与应用场景

一、Java反射API简介: 一、什么是反射: 反射是一种强大的工具,它允许我们在运行时检查类、方法和字段的信息,甚至允许我们动态的调用特定类的方法或改变字段的值。编程语言中的反射机制通常用于从类、对象或方法中检索元数据,或者更特别的说,从代码本身中获取信息。这就…...

【例子】webpack 开发一个可以加载 markdown 文件的加载器 loader 案例

Loader 作为 Webpack 的核心机制,内部的工作原理却非常简单。接下来我们一起来开发一个自己的 Loader,通过这个开发过程再来深入了解 Loader 的工作原理。 这里我的需求是开发一个可以加载 markdown 文件的加载器,以便可以在代码中直接导入 m…...

揭秘!这款电路设计工具让学校师生都爱不释手——SmartEDA的魔力何在?

随着科技的飞速发展,电子设计已成为学校师生们不可或缺的技能之一。而在众多的电路设计工具中,有一款名为SmartEDA的工具,凭借其强大的功能和友好的用户体验,迅速赢得了广大师生的青睐。今天,就让我们一起探索SmartEDA…...

onlyoffice实现打开文档的功能

后端代码 import api from api import middlewareasync def doc_callback(request):data await api.req.get_json(request)print("callback ", data)# status 2 文档准备好被保存# status 6 文档编辑会话关闭return api.resp.success()app api.Api(routes[api.…...

基于 SpringBoot + Vue 的图书购物商城项目

本项目是一个基于 SpringBoot 和 Vue 的图书购物商城系统。系统主要实现了用户注册、登录,图书浏览、查询、加购,购物车管理,订单结算,会员折扣,下单,个人订单管理,书籍及分类管理,用…...

如何使用kimi智能助手:您的智能生活小助手

Kimi智能助手是一款功能强大的AI工具,旨在帮助用户提高工作效率和生活品质。下面小编将详细介绍如何使用Kimi智能助手,涵盖其主要功能以及一些实用技巧。 一、Kimi智能助手的主要功能 多语言对话能力:Kimi擅长中文和英文的对话,可…...

sql操作

1. 按条件将表A的数据更新到表B中: update B b set b.col1 (select col1 from A a where b. id a.code), b.col2 (select col2 from A a where b. id a.code), ………… 2. 将表A的全量数据插入到表B中 insert into B (col1, col2, col3, col4,……&am…...

开关电源调试记录-基于DK112(DK1203也一样)作为开关主控芯片的开关电源

调试了一款DK112(datasheet)开关电源控制芯片。 1、原理图如下: 2、测试波形 a.输出波形,图中标识“5V”的位置 b.芯片VCC引脚,图中标识“4”的位置 c.芯片FB引脚,图中标识“3”的位置 对于FB引脚&…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误

HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

IP如何挑?2025年海外专线IP如何购买?

你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...

如何更改默认 Crontab 编辑器 ?

在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...

苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会

在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...

基于鸿蒙(HarmonyOS5)的打车小程序

1. 开发环境准备 安装DevEco Studio (鸿蒙官方IDE)配置HarmonyOS SDK申请开发者账号和必要的API密钥 2. 项目结构设计 ├── entry │ ├── src │ │ ├── main │ │ │ ├── ets │ │ │ │ ├── pages │ │ │ │ │ ├── H…...

恶补电源:1.电桥

一、元器件的选择 搜索并选择电桥,再multisim中选择FWB,就有各种型号的电桥: 电桥是用来干嘛的呢? 它是一个由四个二极管搭成的“桥梁”形状的电路,用来把交流电(AC)变成直流电(DC)。…...