Peripheral Interface Development Guide

Introduction

Quectel FCM242D and FGM842D series modules support QuecOpen® solution. QuecOpen® is an embedded development platform based on RTOS system. It is intended to simplify the design and development of IoT applications. For more information on QuecOpen®, see Quick_Start_Guide.

This document is applicable to QuecOpen® solution based on SDK build environment. It outlines how to use GPIO, UART, SPI, ADC, PWM and I2C APIs supported by the modules to develop corresponding peripheral interfaces.

GPIO API

Header File

ql_gpio.h, the header file of GPIO API, is in the ql_components\api\ directory. Unless otherwise specified, all GPIO header files mentioned in this document are in this directory.

API Description

ql_gpio_init

This function initializes a GPIO pin.

  • Prototype
ql_gpio_errcode_e ql_gpio_init(ql_gpio_num_e gpio_num, ql_gpio_mode_e mode, ql_gpio_level_e level);
  • Parameters
    • gpio_num: [In] GPIO pin number. See ql_gpio_num_e for details.
    • mode: [In] GPIO mode. See ql_gpio_mode_e for details.
    • level: [In] GPIO output level. It is valid only when mode is QL_GMODE_OUTPUT. See ql_gpio_level_e for details.
  • Return Value
    Result code. See ql_gpio_errcode_e for details.

ql_gpio_num_e

The enumeration of GPIO pin numbers:

typedef enum {
    QL_GPIO0 = 0,
    QL_GPIO1,
    QL_GPIO6 = 6,
    QL_GPIO7,
    QL_GPIO8,
    QL_GPIO9,
    QL_GPIO10,
    QL_GPIO11,
    QL_GPIO14 = 14,
    QL_GPIO15,
    QL_GPIO16,
    QL_GPIO17,
    QL_GPIO20 = 20,
    QL_GPIO21,
    QL_GPIO22,
    QL_GPIO23,
    QL_GPIO24,
    QL_GPIO26 = 26,
    QL_GPIO28 = 28,   
} ql_gpio_num_e
Member Description
QL_GPIO0 GPIO0
QL_GPIO1 GPIO1
QL_GPIO6 GPIO6
QL_GPIO7 GPIO7
QL_GPIO8 GPIO8
QL_GPIO9 GPIO9
QL_GPIO10 GPIO10
QL_GPIO11 GPIO11
QL_GPIO14 GPIO14
QL_GPIO15 GPIO15
QL_GPIO16 GPIO16
QL_GPIO17 GPIO17
QL_GPIO20 GPIO20
QL_GPIO21 GPIO21
QL_GPIO22 GPIO22
QL_GPIO23 GPIO23
QL_GPIO24 GPIO24
QL_GPIO26 GPIO26
QL_GPIO28 GPIO28
ql_gpio_mode_e

The enumeration of GPIO modes:

Member Description
QL_GMODE_HIGH_IMPEDANCE High impedance
QL_GMODE_INPUT Input is configured as floating
QL_GMODE_IN_PD Input is configured with pull-down
QL_GMODE_IN_PU Input is configured with pull-up
QL_GMODE_OUTPUT Output
ql_gpio_errcode_e

The enumeration of GPIO API result codes:

typedef enum {
    QL_GPIO_SUCCESS = 0,
    QL_GPIO_EXECUTE_ERR,
    QL_GPIO_INVALID_PARAM_ERR,
} ql_gpio_errcode_e;
  • Members
Member Description
QL_GPIO_SUCCESS Successful execution
QL_GPIO_EXECUTE_ERR Failed execution
QL_GPIO_INVALID_PARAM_ERR Invalid parameter

ql_gpio_deinit

This function deinitializes the GPIO.

  • Prototype
ql_gpio_errcode_e ql_gpio_deinit(ql_gpio_num_e gpio_num);

ql_gpio_set_level

This function sets the level of the specified GPIO pin. It is valid only for output pins.

  • Prototype
ql_gpio_errcode_e ql_gpio_set_level(ql_gpio_num_e gpio_num, ql_gpio_level_e level);
ql_gpio_level_e

The enumeration of GPIO output levels:

typedef enum {
    QL_GPIO_LEVEL_LOW = 0,
    QL_GPIO_LEVEL_HIGH,
} ql_gpio_level_e;
  • Members
Member Description
QL_GPIO_LEVEL_LOW Low level
QL_GPIO_LEVEL_HIGH High level

ql_gpio_set_level_reverse

This function reverses the GPIO output level. It is valid only for output pins.

  • Prototype
ql_gpio_errcode_e ql_gpio_set_level_reverse(ql_gpio_num_e gpio_num);

ql_gpio_get_level

This function gets the level of the specified GPIO pin. It is valid only for input pins.

  • Prototype
ql_gpio_errcode_e ql_gpio_get_level(ql_gpio_num_e gpio_num, uint32 *input_level);
  • Parameters
    • gpio_num: [In] GPIO pin number. See ql_gpio_num_e for details.
    • input_level: [Out] GPIO pin level.
  • Return Value
    Result code. See ql_gpio_errcode_e for details.

ql_gpio_int_init

This function initializes and enables the GPIO interrupt.

  • Prototype
ql_gpio_errcode_e ql_gpio_int_init(ql_gpio_num_e gpio_num, ql_gpio_irq_trigger_e irq_trigger, ql_gpio_irq_callback cb);

ql_gpio_irq_trigger_e

The enumeration of GPIO interrupt triggering modes:

typedef enum {
    QL_IRQ_TRIGGER_LOW_LEVEL,
    QL_IRQ_TRIGGER_HIGH_LEVEL,
    QL_IRQ_TRIGGER_RISING_EDGE,
    QL_IRQ_TRIGGER_FALLING_EDGE,
} ql_gpio_irq_trigger_e;
  • Members
Member Description
QL_IRQ_TRIGGER_LOW_LEVEL GPIO interrupt triggered at low level
QL_IRQ_TRIGGER_HIGH_LEVEL GPIO interrupt triggered at high level
QL_IRQ_TRIGGER_RISING_EDGE GPIO interrupt triggered at rising edge
QL_IRQ_TRIGGER_FALLING_EDGE GPIO interrupt triggered at falling edge

ql_gpio_irq_callback

This is the callback function of GPIO interrupt.

  • Prototype
typedef void (*ql_gpio_irq_callback)(void *arg);
  • Parameters
    • arg: [In] Pin for triggering the GPIO interrupt.
  • Return Value
    None.

ql_gpio_int_disable

This function disables the configured GPIO interrupt.

  • Prototype
ql_gpio_errcode_e ql_gpio_int_disable(ql_gpio_num_e gpio_num);

GPIO Development Process

This chapter explains how to use the above GPIO API to configure GPIO and perform basic debugging.

GPIO Operation

The example of how to use the GPIO API is provided in the ql_application/example/gpio_demo/ql_gpio_demo.c file in the module SDK. The descriptions of related functions are as follows:

  • ql_gpio_demo_thread_creat(): This function creates a GPIO task. Call this function to run the demo.
  • ql_gpio_demo_thread(): This function executes the GPIO task. It initializes GPIO pins, configures output levels, and initiates, enables and disables GPIO interrupts.

To run the demo, set the CFG_ENABLE_QUECTEL_GPIO macro definition in ql_application/ql_app_main.c of SDK to 1 (i.e., to enable the macro definition). This will automatically trigger the execution of ql_gpio_demo_thread_creat() to create a test task.

Figure 1: Example: Creating a GPIO Task

Figure 2: Example: Using GPIO API

For details on RTOS functions mentioned in the figures, see RTOS Development Guide.

Function Debugging

To debug the GPIO function, use the development board (e.g., FCM242D TE-B) with the module and follow these steps:

  1. Run the GPIO demo as explained in GPIO Operation.
  2. Recompile the firmware version and flash it to the module.
  3. Reboot the module.
  4. Open UART2 port and obtain log via this port.

Pull up the GPIO22 pin level and verify that the GPIO9 pin level is reversed. This indicates that the GPIO interrupt has been triggered. The log information will be displayed as follows:

Capturing Logs via UART Port Tool


UART API

Header File

ql_uart.h, the header file of UART API, is in the ql_components\api\ directory. Unless otherwise specified, all header files mentioned in this document are in this directory.

API Description

ql_uart_set_dcbconfig

This function sets the UART port properties, which take effect after the UART port is reopened. Please note that the system log port cannot be used as the UART port.

  • Prototype
ql_uart_errcode_e ql_uart_set_dcbconfig(ql_uart_port_number_e port, ql_uart_config_s *dcb);
ql_uart_port_number_e

The enumeration of UART port numbers. Currently only two UART ports are supported.

typedef enum {
    QL_UART_PORT_1,
    QL_UART_PORT_2,
} ql_uart_port_number_e;
  • Members
Member Description
QL_UART_PORT_1 UART 1
QL_UART_PORT_2 UART 2
ql_uart_config_s

The structure of the configuration of UART port properties:

typedef struct {
    ql_uart_baud_e baudrate;
    ql_uart_databit_e data_bit;
    ql_uart_stopbit_e stop_bit;
    ql_uart_paritybit_e parity_bit;
    ql_uart_flowctrl_e flow_ctrl;
} ql_uart_config_s;
  • Members
Type Parameter Description
ql_uart_baud_e baudrate Baud rate. Default: 115200 bps. See ql_uart_baud_e for details.
ql_uart_databit_e data_bit Data bit. Default: 8 bits. See ql_uart_databit_e for details.
ql_uart_stopbit_e stop_bit Stop bit. Default: 1 bit. See ql_uart_stopbit_e for details.
ql_uart_paritybit_e parity_bit Parity bit. Default: No parity bit. See ql_uart_paritybit_e for details.
ql_uart_flowctrl_e flow_ctrl Flow control. Default: Disabled. See ql_uart_flowctrl_e for details.

ql_uart_baud_e

The enumeration of baud rates:

typedef enum {
    QL_UART_BAUD_1200 = 1200,
    QL_UART_BAUD_2400 = 2400,
    QL_UART_BAUD_4800 = 4800,
    QL_UART_BAUD_9600 = 9600,
    QL_UART_BAUD_14400 = 14400,
    QL_UART_BAUD_19200 = 19200,
    QL_UART_BAUD_28800 = 28800,
    QL_UART_BAUD_33600 = 33600,
    QL_UART_BAUD_38400 = 38400,
    QL_UART_BAUD_57600 = 57600,
    QL_UART_BAUD_115200 = 115200,
    QL_UART_BAUD_230400 = 230400,
    QL_UART_BAUD_460800 = 460800,
    QL_UART_BAUD_921600 = 921600,
    QL_UART_BAUD_1000000 = 1000000,
    QL_UART_BAUD_2000000 = 2000000,
} ql_uart_baud_e

  • Members
Member Description
QL_UART_BAUD_1200 1200 bps
QL_UART_BAUD_2400 2400 bps
QL_UART_BAUD_4800 4800 bps
QL_UART_BAUD_9600 9600 bps
QL_UART_BAUD_14400 14400 bps
QL_UART_BAUD_19200 19200 bps
QL_UART_BAUD_28800 28800 bps
QL_UART_BAUD_33600 33600 bps
QL_UART_BAUD_38400 38400 bps
QL_UART_BAUD_57600 57600 bps
QL_UART_BAUD_115200 115200 bps
QL_UART_BAUD_230400 230400 bps
QL_UART_BAUD_460800 460800 bps
QL_UART_BAUD_921600 921600 bps
QL_UART_BAUD_1000000 1000000 bps
QL_UART_BAUD_2000000 2000000 bps
ql_uart_databit_e

The enumeration of data bits:

typedef enum {
    QL_UART_DATABIT_5,
    QL_UART_DATABIT_6,
    QL_UART_DATABIT_7,
    QL_UART_DATABIT_8,
} ql_uart_databit_e;
  • Members
Member Description
QL_UART_DATABIT_5 5 bits
QL_UART_DATABIT_6 6 bits
QL_UART_DATABIT_7 7 bits
QL_UART_DATABIT_8 8 bits
ql_uart_stopbit_e

The enumeration of stop bits:

typedef enum {
    QL_UART_STOP_1 = 0,
    QL_UART_STOP_2,
} ql_uart_stopbit_e;
  • Members
Member Description
QL_UART_STOP_1 1 bit
QL_UART_STOP_2 2 bits
ql_uart_paritybit_e

The enumeration of parity bits:

typedef enum {
    QL_UART_PARITY_NONE,
    QL_UART_PARITY_ODD,
    QL_UART_PARITY_EVEN,
} ql_uart_paritybit_e;
  • Members
Member Description
QL_UART_PARITY_NONE No parity
QL_UART_PARITY_ODD Odd parity
QL_UART_PARITY_EVEN Even parity
ql_uart_flowctrl_e

The enumeration of flow control:

typedef enum {
    QL_FC_NONE = 0,
    QL_FC_HW_CTS,
    QL_FC_HW_RTS,
    QL_FC_HW_RTS_CTS,
} ql_uart_flowctrl_e;
  • Members
Member Description
QL_FC_NONE No flow control
QL_FC_HW_CTS Hardware CTS
QL_FC_HW_RTS Hardware RTS
QL_FC_HW_RTS_CTS Hardware CTS and RTS
ql_uart_errcode_e

The enumeration of UART API result codes:

typedef enum {
    QL_UART_SUCCESS = 0,
    QL_UART_EXECUTE_ERR,
    QL_UART_MEM_ADDR_NULL_ERR,
    QL_UART_INVALID_PARAM_ERR,
    QL_UART_NOT_OPEN_ERR,
} ql_uart_errcode_e;
  • Members
Member Description
QL_UART_SUCCESS Successful execution
QL_UART_EXECUTE_ERR Failed execution
QL_UART_MEM_ADDR_NULL_ERR Parameter address: Null
QL_UART_INVALID_PARAM_ERR Invalid parameter
QL_UART_NOT_OPEN_ERR UART port is not open

ql_uart_get_dcbconfig

This function gets the configuration of UART port properties.

  • Prototype
ql_uart_errcode_e ql_uart_get_dcbconfig(ql_uart_port_number_e port, ql_uart_config_s *dcb);

ql_uart_open

This function opens the UART port.

  • Prototype
ql_uart_errcode_e ql_uart_open(ql_uart_port_number_e port);

ql_uart_close

This function closes the UART port.

  • Prototype
ql_uart_errcode_e ql_uart_close(ql_uart_port_number_e port);

ql_uart_write_ready

This function assesses if the data can currently be written to module through the specified UART port.

  • Prototype
bool ql_uart_write_ready(ql_uart_port_number_e port);
  • Parameters
    • port: [In] UART port number. See *Chapter 3.2.1.1* for details.
  • Return Value
    • 0: Data cannot currently be written to module through the specified UART port.
    • 1: Data can currently be written to module through the specified UART port.

ql_uart_write

This function writes data to the module through the specified UART port.

  • Prototype
ql_uart_errcode_e ql_uart_write(ql_uart_port_number_e port, uint8 *data, uint32 data_len);
  • Parameters
    • port: [In] UART port number. See ql_uart_port_number_e for details.
    • data: [In] Written data.
    • data_len: [In] Length of written data. Unit: byte.
  • Return Value
    Result code. See ql_uart_errcode_e for details.

ql_uart_read

This function reads the data from the UART buffer via the specified UART port. If the length of the data in the UART buffer is less than the length of the data to be read, it fails to read the data, and you can call ql_uart_read_prefetch() to read the available data in the UART buffer.

  • Prototype
ql_uart_errcode_e ql_uart_read(ql_uart_port_number_e port, uint8 *data, uint32 data_len);
  • Parameters
    • port: [In] UART port number. See ql_uart_port_number_e for details.
    • data: [Out] Read data.
    • data_len: [In] Length of read data. Unit: byte.
  • Return Value
    Result code. See ql_uart_errcode_e for details.

ql_uart_read_prefetch

This function reads the data from the UART buffer via the specified UART port. If the length of the data in the UART buffer is less than the length of the data to be read, the function reads the available data in the buffer.

  • Prototype
int ql_uart_read_prefetch(ql_uart_port_number_e port, uint8 *data, uint32 data_len);
  • Parameters
    • port: [In] UART port number. See ql_uart_port_number_e for details.
    • data: [Out] Read data.
    • data_len: [In] Length of read data. Unit: byte.
  • Return Value
    Length of actually read data.

ql_uart_get_rx_count

This function reads the length of data in the specified UART buffer.

  • Prototype
int ql_uart_get_rx_count(ql_uart_port_number_e port);
  • Parameters
  • Return Value
    Length of data read from the UART buffer. Unit: byte.

ql_uart_set_rx_cb

This function registers the callback function that is called when data is received via the UART port and interrupt is triggered.

  • Prototype
ql_uart_errcode_e ql_uart_set_rx_cb(ql_uart_port_number_e port, ql_uart_callback uart_cb, void *param);
  • Parameters
    • port: [In] UART port number. See ql_uart_port_number_e for details.
    • uart_cb: [In] Callback function that handles the UART interrupt.
    • param: [In] Parameter of callback function that handles the UART interrupt.
  • Return Value
    Result code. See ql_uart_errcode_e for details.

ql_uart_set_tx_cb

This function registers the callback function that is called when data is sent via the UART port and the interrupt is triggered.

  • Prototype
ql_uart_errcode_e ql_uart_set_tx_cb(ql_uart_port_number_e port, ql_uart_callback uart_cb, void *param);
  • Parameters
    • port: [In] UART port number. See ql_uart_port_number_e for details.
    • uart_cb: [In] Callback function that handles the UART interrupt.
    • param: [In] Parameter of callback function that handles the UART interrupt.
  • Return Value
    Result code. See ql_uart_errcode_e for details.

ql_uart_set_tx_int

This function controls the transmit interrupt event for the specified UART port.

  • Prototype
ql_uart_errcode_e ql_uart_set_tx_int(ql_uart_port_number_e port, uint32 set);
  • Parameters
    • port: [In] UART port number. See ql_uart_port_number_e for details.
    • set: [In] Control the transmit interrupt event for the UART port.
      • 1: Enable
      • 2: Disable
  • Return Value
    Result code. See ql_uart_errcode_e for details.

UART Development Process

This chapter explains how to use the above UART API in the application and perform basic debugging.

UART Operation

The example of how to use the UART API is provided in the ql_application/example/uart_demo/ql_uart_demo.c file in the module SDK. The descriptions of related functions are as follows.

  • ql_uart_demo_thread_creat(): This function creates a UART task. Call this function to run the demo.
  • ql_uart_demo_thread(): This function executes the UART task. It initializes the UART port, sends, and receives data.

To run the demo, enable CFG_ENABLE_QUECTEL_UART macro definition. This will automatically trigger the execution of ql_uart_demo_thread_creat() to create a task.

Example: Creating a UART Task

Example: Using UART API (I)

Example: Using UART API (II)

Function Debugging

To debug the UART function, use the development board (e.g., FCM242D TE-B) with the module and follow these steps:

  1. Run the UART demo as explained in UART Operation.
  2. Recompile the firmware version and flash it to the module.
  3. Reboot the module.
  4. Open UART1 to start the test. Send the data of 20 bytes from UART1 to UART2, which will receive and echo the data, as shown below:

Test Data Sent via UART port 1

Test Data Received on UART2

Log After Test Completion

It can be confirmed that the UART function has been tested successfully by comparing the sent data in *Figure 7* with the received data in *Figure 8*.


SPI API

Header File

ql_spi.h, the header file of SPI API, is in the ql_components\api\ directory. Unless otherwise specified, all header files mentioned in this document are in this directory.

API Description

ql_spi_init

This function initializes SPI.

  • Prototype
ql_spi_errcode_e ql_spi_init(ql_spi_id_e spi_id, ql_spi_config_s *spi_cfg);
ql_spi_id_e

The enumeration of SPI IDs:

typedef enum
{
    QL_SPI_ID0 = 0,
    QL_SPI_ID_MAX
} ql_spi_id_e;

  • Member
Member Description
QL_SPI_ID0 SPI0
QL_SPI_ID_MAX Maximum number of SPI IDs
ql_spi_config_s

The structure of SPI configuration:

typedef struct
{
    uint32 clk;
    ql_spi_role_e role;
    ql_spi_bit_order_e bit_order;
} ql_spi_config_s;
  • Parameter
Type Parameter Description
uint32 clk SPI clock frequency. In master mode, the maximum value is 30 MHz. In slave mode, the maximum value is 20 MHz.
ql_spi_role_e*` role SPI master or slave selection. See ql_spi_role_e for details.
ql_spi_pol_pha_mode_e pol_pha_mode SPI clock phase and SPI clock polarity. See ql_spi_pol_pha_mode_e for details.
ql_spi_bit_order_e*` bit_order* SPI transmitting mode. See ql_spi_bit_order_e for details.
ql_spi_role_e

The enumeration of SPI master or slave selection:

typedef enum {
    QL_SPI_ROLE_SLAVE = 0,
    QL_SPI_ROLE_MASTER
} ql_spi_role_e;
  • Member
Member Description
QL_SPI_ROLE_SLAVE SPI is configured as the slave.
QL_SPI_ROLE_MASTER SPI is configured as the master.
ql_spi_pol_pha_mode_e

The enumeration of SPI clock polarities and SPI clock phases:

typedef enum {
    QL_SPI_POL_PHA_MODE0 = 0,
    QL_SPI_POL_PHA_MODE1,
    QL_SPI_POL_PHA_MODE2,
    QL_SPI_POL_PHA_MODE3
} ql_spi_pol_pha_mode_e;
  • Member
Member Description
QL_SPI_POL_PHA_MODE0 SCK is at a low level during idle state. Sample data on the edge of the first period of SCK.
QL_SPI_POL_PHA_MODE1 SCK is at a low level during idle state. Sample data on the edge of the second period of SCK.
QL_SPI_POL_PHA_MODE2 SCK is at a high level during idle state. Sample data on the edge of the first period of SCK.
QL_SPI_POL_PHA_MODE3 SCK is at a high level during idle state. Sample data on the edge of the second period of SCK.
ql_spi_bit_order_e

The enumeration of SPI transmitting modes:

typedef enum {
    QL_SPI_MSB_FIRST = 0,
    QL_SPI_LSB_FIRST
} ql_spi_bit_order_e;
  • Member
Member Description
QL_SPI_MSB_FIRST MSB is sent first
QL_SPI_LSB_FIRST LSB is sent first
ql_spi_errcode_e

The enumeration of SPI API result codes:

typedef enum
{
    QL_SPI_SUCCESS = 0,
    QL_SPI_EXECUTE_ERR,
    QL_SPI_INVALID_PARAM_ERR,
    QL_SPI_NOT_INIT_ERR
} ql_spi_errcode_e;
  • Member
Member Description
QL_SPI_SUCCESS Successful execution
QL_SPI_EXECUTE_ERR Failed execution
QL_SPI_INVALID_PARAM_ERR Invalid parameter
QL_SPI_NOT_INIT_ERR SPI is not initialized

ql_spi_deinit

This function deinitializes the specified SPI.

  • Prototype
ql_spi_errcode_e ql_spi_deinit(ql_spi_id_e spi_id);

ql_spi_write_bytes

This function sends the SPI data.

  • Prototype
ql_spi_errcode_e ql_spi_write_bytes(ql_spi_id_e spi_id, void *data, uint32 size);
  • Parameters
    • spi_id: [In] SPI ID. See ql_spi_id_e for details.
    • data: [In] Sent SPI data.
    • size: [In] Length of sent SPI data. Unit: byte.
  • Return Value
    Result code. See ql_spi_errcode_e for details.

ql_spi_read_bytes

This function reads the SPI data.

  • Prototype
ql_spi_errcode_e ql_spi_read_bytes(ql_spi_id_e spi_id, void *data, uint32 size);
  • Parameters
    • spi_id: [In] SPI ID. See ql_spi_id_e for details.
    • data: [Out] Buffer for reading SPI data.
    • size: [In] Length of read data. Unit: byte.
  • Return Value
    Result code. See ql_spi_errcode_e for details.

ql_spi_transfer

This function sends and receives SPI data.

  • Prototype
ql_spi_errcode_e ql_spi_transfer(ql_spi_id_e spi_id, ql_spi_message_s *spi_msg);
ql_spi_message_s

The structure of the sent or received SPI data:

typedef struct {
    const void *send_buf;
    uint32 send_len;
    void *recv_buf;
    uint32 recv_len;
} ql_spi_message_s;
  • Parameter
Type Parameter Description
const void send_buf Sent data.
uint32 send_len Length of sent data. Unit: byte.
void recv_buf Received data.
uint32 recv_len Length of received data. Unit: byte.

SPI Development Process

This chapter explains how to use the above SPI API in applications, and perform basic debugging, and test data transmission from both the master and the slave.

SPI Operation

The example of how to use the SPI API is provided in the ql_application/examplespi_demoql_spi_demo.c file in the module SDK. The descriptions of related functions are as follows:

  • ql_spi_demo_thread_creat(): This function creates an SPI task. Call this function to run the SPI demo.
  • ql_spi_demo_thread(): This function executes the SPI task. It initializes SPI and sends SPI data.

To run this example, enable CFG_ENABLE_QUECTEL_SPI macro definition. This will automatically trigger the execution of ql_spi_demo_thread_creat() to create a test task.

Example: Creating an SPI Task

Example: Using SPI API

Function Debugging

To debug the SPI function, use the development board (e.g., FCM242D TE-B) with the module and follow these steps:

  1. Run the SPI demo as explained in SPI Operation.
  2. Recompile the firmware version and flash it to the module.
  3. Reboot the module.
  4. Capture SPI waveforms through the logic analyzer.
  5. Open UART2 to obtain the debugging logs. The log information will be displayed as follows.

Capturing Logs via UART Port Tool

Capturing SPI Waveforms Through Logic Analyzer


ADC API

Header File

ql_adc.h, the header file of ADC API, is in the ql_components\api\ directory. Unless otherwise specified, all header files mentioned in this document are in this directory.

API Description

ql_adc_init

This function initializes ADC.

  • Prototype
ql_adc_errcode_e ql_adc_init(void);
ql_adc_errcode_e

The enumeration of ADC API result codes:

typedef enum
{
    QL_ADC_SUCCESS = 0,
    QL_ADC_EXECUTE_ERR,
    QL_ADC_INVALID_PARAM_ERR
} ql_adc_errcode_e;
  • Member
Member Description
QL_ADC_SUCCESS Successful execution
QL_ADC_EXECUTE_ERR Failed execution
QL_ADC_INVALID_PARAM_ERR Invalid parameter

ql_adc_deinit

This function deinitializes ADC and releases the used resource.

ql_adc_errcode_e ql_adc_deinit(void);

ql_adc_start

This function starts ADC channel detection.

ql_adc_errcode_e ql_adc_start(ql_adc_channel_e chan);
ql_adc_channel_e

The enumeration of ADC channel numbers.

typedef enum
{
    QL_ADC_CHANNEL_1 = 1,
    QL_ADC_CHANNEL_2,
    QL_ADC_CHANNEL_3,
    QL_ADC_CHANNEL_4,
    QL_ADC_CHANNEL_5,
    QL_ADC_CHANNEL_6
} ql_adc_channel_e;
  • Member
Member Description
QL_ADC_CHANNEL_1 ADC1
QL_ADC_CHANNEL_2 ADC2
QL_ADC_CHANNEL_3 ADC3
QL_ADC_CHANNEL_4 ADC4
QL_ADC_CHANNEL_5 ADC5
QL_ADC_CHANNEL_6 ADC6

Since ADC5 and ADC6 channels occupy the UART interface pins in hardware, it is not recommended to use these two channels. See documents Hardware Design for details.

ql_adc_stop

This function stops ADC channel detection.

  • Prototype
ql_adc_errcode_e ql_adc_stop(ql_adc_channel_e chan);

ql_adc_read

This function reads the sample data from the specified ADC channel.

  • Prototype
ql_adc_errcode_e ql_adc_read(ql_adc_channel_e chan, uint16 *data, uint32 timeout);
  • Parameters
    • chan: [In] ADC channel number. See ql_adc_channel_e for details.
    • data: [Out] Read sample data.
    • timeout: [In] Timeout for data reading.
  • Return Value
    Result code. See ql_adc_errcode_e for details.

ADC Development Process

This chapter explains how to use the above ADC API in applications, and perform basic debugging. In the following subsections, ADC channels 3 and 4 are used as examples.

ADC Operation

The example of how to use the ADC API is provided in the ql_application/example/adc_demo/ql_adc_demo.c file in the module SDK directory. The descriptions of related functions are as follows:

  • ql_adc_demo_thread_creat(): This function creates an ADC task. Call the function to run the ADC demo.
  • ql_adc_demo_thread(): This function executes the ADC task. It initializes ADC and detects voltage.

To run the demo, enable CFG_ENABLE_QUECTEL_ADC macro definition. This will automatically trigger the execution of ql_adc_demo_thread_creat() and ql_adc_demo_thread()to create a test task, as shown below.

Example: Creating an ADC Task

Example: Using ADC API

Function Debugging

To debug the ADC function, use the development board (e.g., FCM242D TE-B) with the module and follow these steps:

  1. Run the ADC demo as explained in ADC Operation.
  2. Recompile the firmware version and flash it to the module.
  3. Reboot the module.
  4. Open UART port 2 to capture the debugging logs. Change the input voltage of the pin and the detection value changes accordingly. The log information will be displayed as follows:

Capturing Logs via UART Port Tool


PWM API

Header File

ql_pwm.h, the header file of PWM API, is in the ql_components\api\ directory. Unless otherwise specified, all header files mentioned in this document are in this directory.

API Description

ql_pwm_init

This function initializes PWM.

  • Prototype
ql_pwm_errcode_e ql_pwm_init(ql_pwm_channel_e chan, uint32 period, uint32 duty);
  • Parameters
    • chan: [In] PWM channel. See ql_pwm_channel_e for details.
    • period: [In] PWM period. Actual output frequency: F = 26 MHz / period.
    • duty: [In] PWM duty cycle. It is less than the period value.
  • Return Value
    Result code. See ql_pwm_errcode_e for details.

ql_pwm_channel_e

The enumeration of PWM channels.

typedef enum {
    QL_PWM_0 = 0,
    QL_PWM_1,
    QL_PWM_2,
    QL_PWM_3,
    QL_PWM_4,
    QL_PWM_5
} ql_pwm_channel_e;
  • Member
Member Description
QL_PWM_0 PWM 0
QL_PWM_1 PWM 1
QL_PWM_2 PWM 2
QL_PWM_3 PWM 3
QL_PWM_4 PWM 4
QL_PWM_5 PWM 5
ql_pwm_errcode_e

The enumeration of PWM API result codes:

typedef enum {
    QL_PWM_SUCCESS = 0,
    QL_PWM_EXECUTE_ERR,
    QL_PWM_INVALID_PARAM_ERR
} ql_pwm_errcode_e;
  • Member
Member Description
QL_PWM_SUCCESS Successful execution
QL_PWM_EXECUTE_ERR Failed execution
QL_PWM_INVALID_PARAM_ERR Invalid parameter

ql_pwm_deinit

This function deinitializes PWM.

ql_pwm_errcode_e ql_pwm_deinit(ql_pwm_channel_e pwm_channel);

ql_pwm_enable

This function enables PWM output.

  • Prototype
ql_pwm_errcode_e ql_pwm_enable(ql_pwm_channel_e pwm_channel);

ql_pwm_disable

This function disables PWM output.

  • Prototype
ql_pwm_errcode_e ql_pwm_disable(ql_pwm_channel_e pwm_channel);

ql_pwm_update_param

This function updates the parameters of PWM configuration. The configuration takes effect in the next PWM period.

  • Prototype
ql_pwm_errcode_e ql_pwm_update_param(ql_pwm_channel_e pwm_channel, uint32 period, uint32 duty_cycle);
  • Parameters
    • pwm_channel: [In] PWM channel. See ql_pwm_channel_e for details.
    • period: [In] PWM period. Actual output frequency: F = 26 MHz / period.
    • duty_cycle: [In] PWM duty cycle. It is less than the period value.
  • Return Value
    Result code. See ql_pwm_errcode_e for details.

PWM Development Process

This chapter explains how to use the above PWM API in applications and perform basic debugging. In the following subsections, GPIO6 pin corresponding to PWM0 is used as an example.

PWM Operation

The example of how to use the PWM API is provided in the ql_application/example/pwm_demo/ql_pwm_demo.c file in the module SDK. The descriptions of related functions are as follows:

  • ql_pwm_demo_thread_creat(): This function creates a PWM task. Call the function to run PWM demo.

To run the demo, enable CFG_ENABLE_QUECTEL_PWM macro definition. This will automatically trigger the execution of ql_pwm_demo_thread_creat() to create a test task.

Example: Creating a PWM Task

Example: Using PWM API

Function Debugging

To debug the PWM function, use the development board (e.g., FCM242D TE-B) with the module and follow these steps:

  1. Run the PWM demo as explained in PWM Operation.
  2. Recompile the firmware version and flash it to the module.
  3. Reboot the module.
  4. Capture the pin waveforms of PWM0 through the logic analyzer.
  5. Open UART2 to obtain the debugging logs. The log information will be displayed as follows:

Capturing Logs via UART Port Tool

Capturing PWM Waveforms Through Logic Analyzer


I2C API

Header File

ql_i2c.h, the header file of I2C API, is in the ql_components\api\ directory. Unless otherwise specified, all header files mentioned in this document are in this directory.

API Description

ql_i2c_init

This function initializes the I2C bus.

  • Prototype
ql_i2c_errcode_e ql_i2c_init(ql_i2c_id_e iic_id, ql_i2c_speed_mode_e speed_mode, ql_i2c_addr_mode_e addr_mode, uint16 slave_addr);
  • Parameters
    • iic_id: [In] I2C bus ID. See ql_i2c_id_e for details. Currently, only I2C2 is supported.
    • speed_mode: [In] I2C clock frequency. See ql_i2c_speed_mode_e for details.
    • addr_mode: [In] Length of slave device address. See ql_i2c_addr_mode_e for details.
    • slave_addr: [In] Address used for communication when the module acts as either a master device or a slave device.
  • Return Value
    Result code. See ql_i2c_errcode_e for details.

ql_i2c_id_e

The enumeration of I2C bus ID:

typedef enum {
    QL_I2C2 = 0
} ql_i2c_id_e;
  • Member
Member Description
QL_I2C2 I2C2
ql_i2c_speed_mode_e

The enumeration of I2C clock frequencies:

typedef enum {
    QL_I2C_SPEED_STANDARD = 0,
    QL_I2C_SPEED_FAST
} ql_i2c_speed_mode_e;
  • Member
Member Description
QL_I2C_SPEED_STANDARD Standard mode (Clock frequency is 100 kHz)
QL_I2C_SPEED_FAST Fast mode (Clock frequency is 400 kHz)
ql_i2c_addr_mode_e

The enumeration of slave device address lengths:

typedef enum {
    QL_I2C_ADDR_SIZE_7BIT = 0,
    QL_I2C_ADDR_SIZE_10BIT
} ql_i2c_addr_mode_e;
  • Member
Member Description
QL_I2C_ADDR_SIZE_7BIT Slave device address length is 7 bits.
QL_I2C_ADDR_SIZE_10BIT Slave device address length is 10 bits (Not supported currently).

ql_i2c_errcode_e

The enumeration of I2C API result codes:

typedef enum {
    QL_I2C_SUCCESS = 0,
    QL_I2C_INIT_ERR,
    QL_I2C_ID_INIT_ERR,
    QL_I2C_SM_BUS_ERR,
    QL_I2C_ACK_TIMEOUT_ERR,
    QL_I2C_WRITE_ERR,
    QL_I2C_READ_ERR
} ql_i2c_errcode_e;
  • Member
Member Description
QL_I2C_SUCCESS Successful execution
QL_I2C_INIT_ERR Failed I2C initialization
QL_I2C_ID_INIT_ERR I2C bus ID error
QL_I2C_SM_BUS_ERR I2C bus error
QL_I2C_ACK_TIMEOUT_ERR Timeout for getting ACK
QL_I2C_WRITE_ERR Failed to write data to I2C bus
QL_I2C_READ_ERR Failed to read data from I2C bus

ql_i2c_deinit

This function releases I2C resource.

  • Prototype
ql_i2c_errcode_e ql_i2c_deinit(ql_i2c_id_e iic_id);
  • Parameters
    • iic_id: [In] I2C bus ID. See ql_i2c_id_e for details. Currently, only I2C2 is supported.
  • Return Value
    Result code. See ql_i2c_errcode_e for details.

ql_i2c_master_write

This function sends data in I2C master mode.

  • Prototype
ql_i2c_errcode_e ql_i2c_master_write(ql_i2c_id_e iic_id,uint32 dev_addr,const uint8* data,uint32 size);
  • Parameters
    • iic_id: [In] I2C bus ID. See ql_i2c_id_e for details. Currently, only I2C2 is supported.
    • dev_addr: [In] I2C slave device address.
    • data: [Out] Buffer for sending data.
    • size: [In] Length of sent data. Unit: byte.
  • Return Value
    Result code. See ql_i2c_errcode_e for details.
ql_i2c_master_read

This function receives data in I2C master mode.

  • Prototype
ql_i2c_errcode_e ql_i2c_master_read(ql_i2c_id_e iic_id,uint32 dev_addr,uint8 *data,uint32 size);
  • Parameters
    • iic_id: [In] I2C bus ID. See ql_i2c_id_e for details. Currently, only I2C2 is supported.
    • dev_addr: [In] I2C slave device address.
    • data: [In] Buffer for receiving data.
    • size: [In] Length of received data. Unit: byte.
  • Return Value
    Result code. See ql_i2c_errcode_e for details.
ql_i2c_master_mem_write

This function sends data in I2C master mode and sends the memory address of the slave device.

  • Prototype
ql_i2c_errcode_e ql_i2c_master_mem_write(ql_i2c_id_e iic_id,uint32 dev_addr,uint32 mem_addr,ql_i2c_mem_addr_size_e mem_size,uint8* data,uint32 size);
  • Parameters
    • iic_id: [In] I2C bus ID. See ql_i2c_id_e for details. Currently, only I2C2 is supported.
    • dev_addr: [In] I2C slave device address.
    • mem_addr: [In] Memory address of slave device.
    • mem_size: [In] Size of memory address of slave device. See ql_i2c_mem_addr_size_e for details.
    • data: [Out] Buffer for sending data.
    • size: [In] Length of sent data. Unit: byte.
  • Return Value
    Result code. See ql_i2c_errcode_e for details.
ql_i2c_mem_addr_size_e

The enumeration of memory address sizes:

typedef enum {
    QL_I2C_MEM_ADDR_SIZE_8BIT = 0,
    QL_I2C_MEM_ADDR_SIZE_16BIT
} ql_i2c_mem_addr_size_e;
  • Member
Member Description
QL_I2C_MEM_ADDR_SIZE_8BIT Memory address size is 8 bits
QL_I2C_MEM_ADDR_SIZE_16BIT Memory address size is 16 bits

ql_i2c_master_mem_read

This function receives data in I2C master mode and sends the memory address of the slave device.

  • Prototype
ql_i2c_errcode_e ql_i2c_master_mem_read(ql_i2c_id_e iic_id,uint32 dev_addr,uint32 mem_addr,ql_i2c_mem_addr_size_e mem_size,uint8* data,uint32 size);
  • Parameters
    • iic_id: [In] I2C bus ID. See ql_i2c_id_e for details. Currently, only I2C2 is supported.
    • dev_addr: [In] I2C slave device address.
    • mem_addr: [In] Memory address of slave device.
    • mem_size: [In] Size of memory address of slave device. See ql_i2c_mem_addr_size_e for details.
    • data: [In] Buffer for receiving data.
    • size: [In] Length of received data. Unit: byte.
  • Return Value
    Result code. See ql_i2c_errcode_e for details.

I2C Development Process

This chapter explains how to use the above I2C API in applications and perform basic debugging. I2C requires the use of peripherals for communication. EEPROM chip (model: AT24C02) is applied in this example.

I2C Operation

The example of how to use the I2C API is provided in the ql_application/example/i2c_eeprom_demo/ql_i2c_eeprom_demo.c file in the module SDK. The description of related function is as follows:

  • ql_i2c_demo_thread_creat(): This function creates an I2C task. Call this function to run the demo.

To run this demo, enable CFG_ENABLE_QUECTEL_I2C2 macro definition. This will automatically trigger the execution of ql_i2c_demo_thread_creat() to create a test task.

Example: Creating an I2C Task

Example: Using I2C API

Function Debugging

To debug the I2C function, use the development board (e.g., FCM242D TE-B) with the module and follow these steps:

  1. Run the I2C demo as explained in I2C Operation.
  2. Recompile the firmware version and flash it to the module.
  3. Reboot the module.
  4. Open UART2 to obtain the debugging logs. The log information will be displayed as follows:

Capturing Logs via UART Port Tool

The data can be written and read successfully as shown in the figure above. Therefore, it can be said that the I2C function test has passed.


Appendix References

Terms and Abbreviations

Abbreviation Description
ACK Acknowledgement
ADC Analog-to-Digital Converter
API Application Programming Interface
CLK Clock
FC Flow Control
CTS Clear To Send
EEPROM Electrically Erasable Programmable Read-Only Memory
GPIO General-Purpose Input/Output
HW Hardware
I2C Inter-Integrated Circuit
ID Identifier
IoT Internet of Things
LSB Least Significant Bit
MSB Most Significant Bit
PWM Pulse Width Modulation
RTOS Real-Time Operating System
RTS Request To Send
SCK Serial Clock
SDK Software Development Kit
SPI Serial Peripheral Interface
UART Universal Asynchronous Receiver/Transmitter