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-官网

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/865794.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

又一个被催的相亲对象!家庭不和,是因为智慧不够?——早读(逆天打工人爬取热门微信文章解读)

你相亲过吗? 引言Python 代码第一篇 洞见 家庭不和,是因为智慧不够第二篇 口播结尾 引言 yue 昨天居然忘记了 正事:拍视频j 居然忘记了 别着急 让我找下理由(借口) 前天我妈给我介绍了个相亲对象 推给我了她的微信 我…

网络攻防——kali操作系统基本使用

1.阅读前的声明 本文章中生成的木马带有一定的攻击性,使用时请遵守网络安全相关的法律法规(恶意攻击操作系统属于违法行为)。 2.环境安装 生成木马主要需要如下工具:kali操作系统,VMware15(搭建kali操作…

Beyond Compare 解锁版下载及安装教程 (文件和文件夹比较工具)

前言 Beyond Compare 是一款功能强大的文件和文件夹比较工具。它支持文件夹比较、文件夹合并与同步、文本比较、表格比较、图片比较、16进制比较、注册表比较、版本比较等多种功能。通过 Beyond Compare,您可以轻松调查文件和文件夹之间的不同之处,并使…

【Qwen2部署实战】探索Qwen2-7B:通过FastApi框架实现API的部署与调用

系列篇章💥 No.文章1【Qwen部署实战】探索Qwen-7B-Chat:阿里云大型语言模型的对话实践2【Qwen2部署实战】Qwen2初体验:用Transformers打造智能聊天机器人3【Qwen2部署实战】探索Qwen2-7B:通过FastApi框架实现API的部署与调用4【Q…

电脑恢复技巧:如何在 Windows 10 中恢复删除的文件夹

丢失文件和文件夹是一件非常可怕的事情,尤其是当你不知情的情况下删除它们时。别撒谎。我们知道你也经历过这种情况,而且你也知道我们在说什么! 我们都曾有过这样的经历,而且大多数人很快就会再次经历。在 Windows 中&#xff0c…

从内外参推导IPM变换方程及代码实现(生成AVM环视拼接图)

一、前言 最近想实现AVM拼接,看了不少博客和论文,不过比较愚钝,一直没能很好理解原理,尤其是怎么在实现时把下文式1与式2中Z1和Z2消除的,所以严谨的推导了一下对应的公式,如有不对,水平有限&am…

Qt Group与华为合作开发OpenHarmony版本,打造无缝跨设备操作系统

在华为开发者大会2024上,跨平台软件开发和质量保证工具的领先供应商 Qt Group(Nasdaq, Helsinki: QTCOM)荣幸地宣布成为OpenHarmony生态系统合作伙伴。这是继近几年华为采用Qt开发框架和自动化测试工具Squish的商业许可后,Qt Grou…

Elasticsearch集群部署(下)

目录 上篇:Elasticsearch集群部署(上)-CSDN博客 七. Filebeat 部署 八. 部署Kafka 九. 集群测试 链接:https://pan.baidu.com/s/1AFXSmDdY5xBb7g35ipKoaw?pwdfa9m 提取码:fa9m 七. Filebeat 部署 为什么用 F…

搭建基础库~

前言 项目中会用到工具库、函数库以及一些跟框架绑定的组件,如果这些基础模块每个项目都实现一套,维护起来那真的头大,你说呢😉 搭建流程 准备工作 创建文件夹myLib、安装Git以及pnpm 目录大概就系这样子: myLib ├…

Vue跨域获取ip和ip位置城市等归属地信息

由于端口设置与查询服务器不一致,所以不能直接从ip138网上抓取,只能跨域查询。实现跨域查询,简单的方法是使用jsonp方式,只支持get请求,同时也需要查询的服务器支持jsonp。这时找到了腾讯位置服务。参考文章&#xff0…

Appium Inspector介绍和使用

一、什么是Appium Inspector 官方介绍:Overview - Appium Inspector 检查器的主要目的是提供应用程序页面源代码的检查功能。它主要用于测试自动化开发,但也可用于应用程序开发 - 或者如果只是想查看应用程序的页面源代码! 从本质上讲&…

API Object设计模式

API测试面临的问题 API测试由于编写简单,以及较高的稳定性,许多公司都以不同工具和框架维护API自动化测试。我们基于seldom框架也积累了几千条自动化用例。 •简单的用例 import seldomclass TestRequest(seldom.TestCase):def test_post_method(self…

vue3项目图片压缩+rem+自动重启等plugin使用与打包配置

一、Svg配置 每次引入一张 SVG 图片都需要写一次相对路径,并且对 SVG 图片进行压缩优化也不够方便。 vite-svg-loader插件加载SVG文件作为Vue组件,使用SVGO进行优化。 插件网站https://www.npmjs.com/package/vite-svg-loader 1. 安装 pnpm i vite-svg…

步进电机(STM32+28BYJ-48)

一、简介 步进电动机(stepping motor)把电脉冲信号变换成角位移以控制转子转动的执行机构。在自动控制装置中作为执行器。每输入一个脉冲信号,步进电动机前进一步,故又称脉冲电动机。步进电动机多用于数字式计算机的外部设备&…

DOM 中包含哪些重要方法

1. alert 带有指定消息的警告框 alert("hello world"); 2. confirm 带有确定和取消的对话框,点击确定返回 true,点击取消返回 false confirm("你好吗"); 3. prompt 显示一个提示框,允许用户输入文本,点击…

CST电磁仿真创建独特的天线

在日益无线化的世界中,一切都取决于天线,从我们用于医疗保健、工作和娱乐的智能设备到将我们从一个地方带到另一个地方的车辆。它们如此融入我们的日常生活,以至于我们大多数人甚至没有想到它们——即使想到了,我们也会想象屋顶上…

ubnutu20.04-vscode安装leetcode插件流程

1.在vscode插件商城选择安装leetcode 2.安装node.js 官网下载一个版本安装流程: ①tar -xvf node-v14.18.0-linux-x64.tar.xz ①sudo ln -s /app/software/nodejs/bin/npm /usr/local/bin/ ②ln -s /app/software/nodejs/bin/node /usr/local/bin/ 查看版本&…

nginx的LNMP构建+discuz论坛

一、LNMP: L:linux 操作系统 N:nginx前端页面的web服务 P:PHP,是一种开发动态页面的编程语言,解析动态页面,起到中间件的作用(在nginx和数据库的中间),在中…

横截面数据回归

横截面数据回归 一些笔记 观测值一定要比参数值多 p值<0.05,拒绝H0. 参数显著&#xff0c;不能说明模型对 AIC与BIC准则&#xff0c;越小越好的指标值AIC 回归分析一定要进行残差的正态性检验。所有的残差都大于0&#xff0c;小于0&#xff0c;都不正常。残差正常应该是分…

小学校园“闲书”交易平台的设计与实现-计算机毕业设计源码04282

小学校园“闲书”交易平台的设计与实现 摘 要 小学校园“闲书”交易平台是为了解决小学生之间的书籍交流和阅读兴趣培养而设计的。该平台通过使用现代技术手段&#xff0c;如移动应用开发和互联网技术&#xff0c;构建了一个功能齐全的交易平台。平台支持用户注册与登录&#x…