一、需求描述:
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.receiveMessage
this.scroller.scrollTo({ xOffset: 0, yOffset: 0 })
}
} else {
this.isStart = false
this.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 string
this.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),失败-1
export 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; //接收数据,成功返回接收字符串,失败返回-1
export const getBandRate: (serial_port: number) => number; //查询波特率,成功返回波特率,失败返回-1
3、完整应用工程源码,私信
声明:非本人允许,严禁转载,演示开发板为厦门贝启科技的BQ3568HM产品
(1)首页-贝启科技官方企业店-淘宝网
(2)厦门贝启科技有限公司-Bearkey-官网