目录

Serial Port Communication Development

Overview

The serial port communication module (@ohos.busManager.serial) provides object-oriented serial port management capabilities. It supports functions such as obtaining the list of available serial ports, enabling or disabling serial ports, reading and writing data, controlling hardware signals, and configuring flow control. This module is applicable to scenarios where data needs to be exchanged through serial ports, such as industrial automation, Internet of Things (IoT) device interconnection, embedded device debugging, and GPS module communication.

Basic Concepts

When developing serial port communication, you need to understand the following basic concepts:

Implementation Principle

The core process of the serial port communication service is as follows:

  1. Obtaining the serial port list: The system enumerates the currently available serial port devices and returns the serial port object list.
  2. Opening a serial port: Select the target serial port, configure communication parameters such as the baud rate, data bit, parity bit, and stop bit, and open the serial port. When the serial port is opened for the first time, the system displays a dialog box to request user authorization. The serial port device can be accessed only after the user approves the authorization. If the user rejects the authorization, error code 35700007 is thrown.
  3. Data transmission and reception: Data is sent through the write interface, and data is received through the registered data callback listener.
  4. Hardware signal control: Hardware flow control and status detection are performed through signal lines such as RTS/CTS.
  5. Disabling the serial port: The serial port is disabled after the communication is complete to release resources.

Figure 1 Data flow of serial port communication

Data written by the application layer → Sent by the serial port driver → Physical serial cable → Peer serial port device
                                              ↓
Data read by the application layer ← Buffered by the serial port driver ← Physical serial cable ← Peer serial port device

Constraints

Preparing the Environment

[h2]Environment Requirement

[h2]Setting Up the Environment

Development Guide

[h2]API Description

The following table describes the main APIs for serial port communication.

API Description
SerialPort.getSerialPortList(): Promise<SerialPort[]> Queries the serial port device list. The SerialPort object array is returned. This API uses a promise to return the result.
SerialPort.open(config?: SerialConfigs): Promise<void> Opens a serial port device. When a serial port device is opened for the first time, the system displays a dialog box asking the user to authorize access to the target serial port. If the user rejects the request, error code 35700007 is thrown. The authorization expires upon removal of the USB virtual serial port, system user switching, or restart of the device. Re-authorization is required in this case. This API uses a promise to return the result.
SerialPort.close(): Promise<void> Closes a serial port device. This API uses a promise to return the result.
SerialPort.write(data: Uint8Array, timeout?: number): Promise<number> Sends data to a serial port device. The length range of the data sent each time is (0, 4096]. This API uses a promise to return the result.
SerialPort.onDataRead(callback: Callback<Uint8Array>): void Listens for data receiving events on the serial port. This API uses an asynchronous callback to return the received data. After close is called, all callbacks are cleared.
SerialPort.offDataRead(callback?: Callback<Uint8Array>): void Cancels listening for data receiving events on the serial port. This API uses an asynchronous callback to return the result.
SerialPort.flush(): Promise<void> Flushes the serial port buffer, including the read buffer and write buffer. Data in the buffer will be directly discarded and will not be sent or read. This API uses a promise to return the result.
SerialPort.drain(): Promise<void> Waits until all write requests are complete. This API uses a promise to return the result.
SerialPort.setRts(enable: boolean): Promise<void> Sets the status of the request to send (RTS) signal. This API uses a promise to return the result.
SerialPort.getCts(): Promise<boolean> Obtains the status of the clear to send (CTS) signal. This API uses a promise to return the result.
SerialPort.sendBrk(): Promise<void> Sends a BRK signal. This API uses a promise to return the result.

SerialConfigs parameter description:

Name Type Mandatory Default Value Description
baudRate number No 115200 Baud rate.
dataBits DataBits No DataBits.EIGHT Data bits.
stopBits StopBits No StopBits.ONE Stop bits.
parity Parity No Parity.NONE Parity bit.
rtscts boolean No false Check whether RTS/CTS hardware automatic flow control is enabled. true to enable; false otherwise.
xon boolean No false Check whether XON software flow control is enabled. true to enable; false otherwise.
xoff boolean No false Check whether XOFF software flow control is enabled. true to enable; false otherwise.
xany boolean No false Check whether the software flow control restart for any character is enabled. true to enable; false otherwise.

[h2]Development Procedure

The following sample code is only a necessary process for serial port communication and needs to be executed in a specific method.

  1. Import the module.

    import { serial, BusinessError } from '@kit.BasicServicesKit';
  2. Obtain the serial port device list.

    try {
      const portList = await serial.getSerialPortList();
      console.info(`${TAG} getSerialPortList success, count: ${portList.length}`);
      portList.forEach((port: serial.SerialPort, index: number) => {
        console.info(`${TAG}   [${index}] portName=${port.portInfo.portName}, vendorId=${port.portInfo.vendorId}, productId=${port.portInfo.productId}`);
      });
      if (portList.length > 0) {
        this.port = portList[0];
      }
    } catch (err) {
      const e = err as BusinessError;
      console.error(`${TAG} getSerialPortList failed, code: ${e.code}, message: ${e.message}`);
    }
  3. Open the serial port device.

    try {
      if (!this.port) {
        console.error(`${TAG} No serial port found, please call getSerialPortList first`);
        return;
      }
      const config: serial.SerialConfigs = {
        baudRate: 115200,
        dataBits: serial.DataBits.EIGHT,
        stopBits: serial.StopBits.ONE,
        parity: serial.Parity.NONE
      };
      await this.port.open(config);
      console.info(`${TAG} open success`);
    } catch (err) {
      const e = err as BusinessError;
      console.error(`${TAG} open failed, code: ${e.code}, message: ${e.message}`);
    }
  4. Register a callback to receive data and listen for serial port data.

    try {
      if (!this.port) {
        console.error(`${TAG} No serial port found, please call getSerialPortList first`);
        return;
      }
      this.dataCallback = (data: Uint8Array) => {
        console.info(`${TAG} onDataRead: ${Array.from(data).join(', ')}`);
      };
      this.port.onDataRead(this.dataCallback);
      console.info(`${TAG} onDataRead registered`);
    } catch (err) {
      const e = err as BusinessError;
      console.error(`${TAG} onDataRead failed, code: ${e.code}, message: ${e.message}`);
    }
  5. Write data through the serial port.

    try {
      if (!this.port) {
        console.error(`${TAG} No serial port found, please call getSerialPortList first`);
        return;
      }
      const data = new Uint8Array([0x48, 0x65, 0x6C, 0x6C, 0x6F]);
      const writeLen = await this.port.write(data);
      console.info(`${TAG} write success, length: ${writeLen}`);
    } catch (err) {
      const e = err as BusinessError;
      console.error(`${TAG} write failed, code: ${e.code}, message: ${e.message}`);
    }
  6. Refresh the buffer and wait until the sending is complete.

    try {
      if (!this.port) {
        console.error(`${TAG} No serial port found, please call getSerialPortList first`);
        return;
      }
      await this.port.flush();
      console.info(`${TAG} flush success`);
    } catch (err) {
      const e = err as BusinessError;
      console.error(`${TAG} flush failed, code: ${e.code}, message: ${e.message}`);
    }
  7. Hardware signal control.

    • Set the RTS signal to high level.

      try {
        if (!this.port) {
          console.error(`${TAG} No serial port found, please call getSerialPortList first`);
          return;
        }
        await this.port.setRts(true);
        console.info(`${TAG} setRts(true) success`);
      } catch (err) {
        const e = err as BusinessError;
        console.error(`${TAG} setRts failed, code: ${e.code}, message: ${e.message}`);
      }
    • Obtain the CTS signal status.

      try {
        if (!this.port) {
          console.error(`${TAG} No serial port found, please call getSerialPortList first`);
          return;
        }
        const ctsStatus = await this.port.getCts();
        console.info(`${TAG} getCts success, CTS: ${ctsStatus}`);
      } catch (err) {
        const e = err as BusinessError;
        console.error(`${TAG} getCts failed, code: ${e.code}, message: ${e.message}`);
      }
    • Send the break signal.

      try {
        if (!this.port) {
          console.error(`${TAG} No serial port found, please call getSerialPortList first`);
          return;
        }
        await this.port.sendBrk();
        console.info(`${TAG} sendBrk success`);
      } catch (err) {
        const e = err as BusinessError;
        console.error(`${TAG} sendBrk failed, code: ${e.code}, message: ${e.message}`);
      }
  8. Deregister the callback for receiving data and close the serial port device.

    try {
      if (!this.port) {
        console.error(`${TAG} No serial port found, please call getSerialPortList first`);
        return;
      }
      await this.port.close();
      console.info(`${TAG} close success`);
      this.port = null;
    } catch (err) {
      const e = err as BusinessError;
      console.error(`${TAG} close failed, code: ${e.code}, message: ${e.message}`);
    }

[h2]Debugging and Verification

  1. Prepare a serial cable and connect the serial port of the HarmonyOS device to the serial port of the target device.
  2. Run the preceding sample code on the HarmonyOS device.
  3. If the success log is returned, the related API is successfully called and the serial port communication capability of the device is normal. If the failed or error log is returned, the API fails to be called. In this case, check the hardware connection and parameter settings.
  4. You can perform a loopback test (short-circuit the TX and RX of the serial port) to check whether the self-sending and self-receiving function of the data is normal.