HCM111Z QuecOpen(SDK) Peripheral Interface Development Guide

Introduction

Quectel HCM111Z module supports QuecOpen® solution. QuecOpen® is an embedded development platform, which is intended to simplify the design and development of IoT applications.

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


GPIO API

Header File

ql_gpio.h, the header file of GPIO API, is in the components/quectel_api/ql_include directory. Unless otherwise specified, all header files mentioned in this document are in this directory.

API Overview

Function Description
ql_gpio_set_port_mux() Sets the GPIO multiplexing feature.
ql_gpio_init() Initializes a GPIO pin.
ql_gpio_set_level() Sets the level of the specified GPIO pin.
ql_gpio_get_level() Gets the level of the specified GPIO pin.
ql_gpio_int_init() Initializes and enables the GPIO interrupt.
ql_gpio_int_disable() Disables the configured GPIO interrupt.
ql_gpio_set_port_pull() Sets the pull-up mode when GPIO is used as an input port.

API Description

ql_gpio_set_port_mux

This function sets the GPIO multiplexing feature.

Prototype:

ql_gpio_errcode_e ql_gpio_set_port_mux(ql_gpio_num_e pin, uint8_t func)

Parameters:

  • pin: [In] GPIO pin number. See ql_gpio_num_e.
  • func: [In] GPIO multiplexing feature.

Return Value:

Function execution result code. See ql_gpio_errcode_e.


ql_gpio_init

This function initializes a GPIO pin.

Prototype:

ql_gpio_errcode_e ql_gpio_init(ql_gpio_num_e pin, ql_gpio_mode_e mode)

Parameters:

Return Value:

Function execution result code. See ql_gpio_errcode_e.


ql_gpio_num_e

The enumeration of GPIO pin number:

typedef enum {
  QL_GPIO_PA0,
  QL_GPIO_PA1,
  QL_GPIO_PA2,
  QL_GPIO_PA3,
  QL_GPIO_PA4,
  QL_GPIO_PA5,
  QL_GPIO_PA6,
  QL_GPIO_PA7,
  QL_GPIO_PB0,
  QL_GPIO_PB1,
  QL_GPIO_PB2,
  QL_GPIO_PB3,
  QL_GPIO_PB4,
  QL_GPIO_PB5,
  QL_GPIO_PB6,
  QL_GPIO_PB7,
  QL_GPIO_PC0,
  QL_GPIO_PC1,
  QL_GPIO_PC2,
  QL_GPIO_PC3,
  QL_GPIO_PC4,
  QL_GPIO_PC5,
  QL_GPIO_PC6,
  QL_GPIO_PC7,
  QL_GPIO_PD0,
  QL_GPIO_PD1,
  QL_GPIO_PD2,
  QL_GPIO_PD3,
  QL_GPIO_PD4,
  QL_GPIO_PD5,
  QL_GPIO_PD6,
  QL_GPIO_PD7,
} ql_gpio_num_e

Member:

Member Description
QL_GPIO_PA0 GPIOA0
QL_GPIO_PA1 GPIOA1
QL_GPIO_PA2 GPIOA2
QL_GPIO_PA3 GPIOA3
QL_GPIO_PA4 GPIOA4
QL_GPIO_PA5 GPIOA5
QL_GPIO_PA6 GPIOA6
QL_GPIO_PA7 GPIOA7
QL_GPIO_PB0 GPIOB0
QL_GPIO_PB1 GPIOB1
QL_GPIO_PB2 GPIOB2
QL_GPIO_PB3 GPIOB3
QL_GPIO_PB4 GPIOB4
QL_GPIO_PB5 GPIOB5
QL_GPIO_PB6 GPIOB6
QL_GPIO_PB7 GPIOB7
QL_GPIO_PC0 GPIOC0
QL_GPIO_PC1 GPIOC1
QL_GPIO_PC2 GPIOC2
QL_GPIO_PC3 GPIOC3
QL_GPIO_PC4 GPIOC4
QL_GPIO_PC5 GPIOC5
QL_GPIO_PC6 GPIOC6
QL_GPIO_PC7 GPIOC7
QL_GPIO_PD0 GPIOD0
QL_GPIO_PD1 GPIOD1
QL_GPIO_PD2 GPIOD2
QL_GPIO_PD3 GPIOD3
QL_GPIO_PD4 GPIOD4
QL_GPIO_PD5 GPIOD5
QL_GPIO_PD6 GPIOD6
QL_GPIO_PD7 GPIOD7

ql_gpio_mode_e

The enumeration of GPIO pin modes:

typedef enum {
  QL_GMODE_INPUT_PULLDOWN = 1,
  QL_GMODE_INPUT_PULLUP,
  QL_GMODE_OUTPUT = 0,
} ql_gpio_mode_e

Member:

Member Description
QL_GMODE_INPUT_PULLDOWN Input is configured for pull-down
QL_GMODE_INPUT_PULLUP Input is configured for pull-up
QL_GMODE_OUTPUT Push-pull output

ql_gpio_errcode_e

The enumeration of GPIO result codes:

typedef enum {
  QL_GPIO_SUCCESS = 0,
  QL_GPIO_EXECUTE_ERR,
  QL_GPIO_INVALID_PARAM_ERR,
  QL_GPIO_EXTI_LINE_CLASH_ERR,
} ql_gpio_errcode_e

Member:

Member Description
QL_GPIO_SUCCESS Successful execution
QL_GPIO_EXECUTE_ERR Failed execution
QL_GPIO_INVALID_PARAM_ERR Invalid parameter
QL_GPIO_EXTI_LINE_CLASH_ERR GPIO interrupt line configuration conflict

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 pin, ql_gpio_output_level_e output_level)

Parameters:

Return Value:

Function execution result code. See ql_gpio_errcode_e.


ql_gpio_output_level_e

The enumeration of the GPIO output levels:

typedef enum {
  QL_GPIO_OUTPUT_LOW,
  QL_GPIO_OUTPUT_HIGH,
} ql_gpio_output_level_e

Member:

Member Description
QL_GPIO_OUTPUT_LOW Low level
QL_GPIO_OUTPUT_HIGH High level

ql_gpio_get_level

This function gets the level of the specified GPIO pin.

Prototype:

ql_gpio_errcode_e ql_gpio_get_level(ql_gpio_num_e pin, uint32_t *input_level)

Parameters:

  • pin: [In] GPIO pin number. See ql_gpio_num_e.
  • input_level: [Out] GPIO pin level.

Return Value:

Function execution result code. See ql_gpio_errcode_e.


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 pin, ql_gpio_irq_trigger_e trigger, ql_gpio_irq_callback callback)

Parameters:

Return Value:

Function execution result code. See ql_gpio_errcode_e.


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

Member:

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, uint8_t line)

Parameters:

  • arg: [In] Pin for triggering the GPIO interrupt.
  • line: [Out] Serial number of the external interrupt line that triggers the GPIO interrupt.

ql_gpio_int_disable

This function disables the configured GPIO interrupt.

Prototype:

ql_gpio_errcode_e ql_gpio_int_disable(ql_gpio_num_e pin)

Parameters:

Return Value:

Function execution result code. See ql_gpio_errcode_e.


ql_gpio_set_port_pull

This function sets the pull-up mode when GPIO is used as an input port.

Prototype:

ql_gpio_errcode_e ql_gpio_set_port_pull(ql_gpio_num_e pin, uint8_t enable)

Parameters:

  • pin: [In] GPIO pin number. See ql_gpio_num_e.
  • enable: [In] Set the pull-up mode.

True Enable the pull-up mode
False No setting

Return Value:

Function execution result code. See ql_gpio_errcode_e.


GPIO Development Process

This chapter describes how to use the above GPIO API to configure GPIO pins and perform basic debugging. QL_GPIO_PD4, QL_GPIO_PD5 and QL_GPIO_PD6 are used in the following examples by default.

GPIO Operation

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

  • demo_gpio(): Initializes a GPIO pin and enables the GPIO interrupt
  • ql_gpio_irq_test(): This is the interrupt callback function. It can implement functionalities such as setting the GPIO pin level and disabling GPIO interrupts.

The example of using the GPIO API is as follows:

void demo_gpio(void)
{
    ql_debug("digital gpio demo\\r\\n");
    //digital gpio output
    ql_gpio_set_port_mux(QL_GPIO_PD4 , QL_PORTD4_FUNC_D4);
    ql_gpio_set_port_mux(QL_GPIO_PD5 , QL_PORTD5_FUNC_D5);
    ql_gpio_set_port_mux(QL_GPIO_PD6 , QL_PORTD6_FUNC_D6);
    ql_gpio_init(QL_GPIO_PD4,QL_GMODE_OUTPUT);
    ql_gpio_init(QL_GPIO_PD5,QL_GMODE_INPUT_PULLDOWN);
    ql_gpio_set_level(QL_GPIO_PD4,QL_GPIO_OUTPUT_HIGH);
    ql_gpio_init(QL_GPIO_PD6 , QL_GMODE_INPUT_PULLDOWN);
    ql_gpio_int_init(QL_GPIO_PD6, QL_IRQ_TRIGGER_RISING_EDGE , ql_gpio_irq_test);
}
void ql_gpio_irq_test (void *arg,uint8_t line)
{
    static int cnt = 0;
    uint32_t input_level = 0;
    ql_gpio_get_level(QL_GPIO_PD5,&input_level);
    ql_debug("exit_line=%d\\r\\n",line);
    ql_debug(" gpio5 read=%d\\r\\n",input_level);
    if(input_level == 0){
        ql_gpio_set_level(QL_GPIO_PD4,QL_GPIO_OUTPUT_LOW);
    }else{
        ql_gpio_set_level(QL_GPIO_PD4,QL_GPIO_OUTPUT_HIGH);
    }
    cnt++;
    ql_debug(" int cnt=%d\\r\\n",cnt);
    if(cnt >= 10){
        ql_gpio_int_disable(QL_GPIO_PD6);
        cnt = 0;
    }
}

Function Debugging

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

  1. Recompile the firmware version and flash it to the module.
  2. Reboot the module.
  3. Open UART port 1 to obtain the debugging logs. The log information will be displayed as follows:

Log Obtained via a Serial Port Tool

If the following information is printed during the debugging, it indicates that the GPIO interrupt has been triggered.

GPIO Test Log

PMU GPIO API

Header File

ql_pmu_gpio.h, the header file of PMU GPIO API, is in the components/quectel_api/ql_include directory. Unless otherwise specified, all header files mentioned in this document are in this directory.

The functional difference between GPIO and PMU GPIO pins is that the PMU GPIO pins can keep the output level unchanged when the module is in sleep state.

API Overview

Function Description
ql_pmu_gpio_init() Initializes a PMU GPIO pin.
ql_pmu_gpio_set_level() Sets the level of the specified PMU GPIO pin.
ql_pmu_gpio_get_level() Gets the level of the specified PMU GPIO pin.
ql_pmu_gpio_int_init() Initializes and enables the PMU GPIO interrupt.
ql_pmu_gpio_int_disable() Disables the configured PMU GPIO interrupt.

API Description

ql_pmu_gpio_init

This function initializes a PMU GPIO pin.

Prototype:

ql_gpio_errcode_e ql_pmu_gpio_init(ql_gpio_num_e pin, ql_gpio_mode_e mode)

Parameters:

Return Value:

Function execution result code. See ql_gpio_errcode_e.


ql_pmu_gpio_set_level

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

Prototype:

ql_gpio_errcode_e ql_pmu_gpio_set_level(ql_gpio_num_e pin, ql_gpio_output_level_e output_level)

Parameters:

Return Value:

Function execution result code. See ql_gpio_errcode_e.


ql_pmu_gpio_get_level

This function gets the level of the specified PMU GPIO pin.

Prototype:

ql_gpio_errcode_e ql_pmu_gpio_get_level(ql_gpio_num_e pin, uint32_t *input_level)

Parameters:

  • pin: [In] PMU GPIO pin number. See ql_gpio_num_e.
  • input_level: [Out] PMU GPIO pin level.

Return Value:

Function execution result code. See ql_gpio_errcode_e.


ql_pmu_gpio_int_init

This function initializes and enables the PMU GPIO interrupt.

Prototype:

ql_gpio_errcode_e ql_pmu_gpio_int_init(ql_gpio_num_e pin, ql_gpio_irq_trigger_e trigger, ql_pmu_gpio_irq_callback callback)

Parameters:

Return Value:

Function execution result code. See ql_gpio_errcode_e.


ql_pmu_gpio_irq_callback

This is the callback function of PMU GPIO interrupt.

Prototype:

typedef void (*ql_pmu_gpio_irq_callback)(void *arg)

Parameters:

  • arg: [Out] Reserved.

ql_pmu_gpio_int_disable

This function disables the configured PMU GPIO interrupt.

Prototype:

ql_gpio_errcode_e ql_pmu_gpio_int_disable(ql_gpio_num_e pin)

Parameters:

Return Value:

Function execution result code. See ql_gpio_errcode_e.


PMU GPIO Development Process

This chapter describes how to use the above PMU GPIO API to configure PMU GPIO pins and perform basic debugging. QL_GPIO_PD4, QL_GPIO_PD5 and QL_GPIO_PD6 are used in the following examples by default.

PMU GPIO Operation

The example of how to use the PMU GPIO API is provided in the quectel_demo/ql_pmu_gpio_demo/code/ql_pmu_gpio_demo.c file in the module SDK. The related functions are described as follows:

  • demo_pmu_gpio(): Initializes PMU GPIO and enables the PMU GPIO interrupt
  • ql_gpio_pmu_irq_test(): This is the interrupt callback function. It can implement the functionalities such as getting the pin level of PMU GPIO, setting the level of PMU GPIO pin and disabling the PMU GPIO interrupt.

The example of using the PMU GPIO API is as follows:

void demo_pmu_gpio(void)
{
    ql_debug("pmu gpio demo\\r\\n");
    ql_pmu_gpio_init(QL_GPIO_PD4,QL_GMODE_OUTPUT);
    ql_pmu_gpio_init(QL_GPIO_PD5,QL_GMODE_INPUT_PULLDOWN);
    ql_pmu_gpio_set_level(QL_GPIO_PD4,QL_GPIO_OUTPUT_HIGH);
    ql_pmu_gpio_int_init(QL_GPIO_PD6, QL_IRQ_TRIGGER_FALLING_EDGE, ql_gpio_pmu_irq_test);//wakeup pin
}

void ql_gpio_pmu_irq_test (void *arg)
{
    static int cnt = 0;
    uint32_t input_level = 0;
    ql_pmu_gpio_get_level(QL_GPIO_PD5,&input_level);
    ql_debug(" gpio5 read=%d\\r\\n",input_level);
    if(input_level == 0){
        ql_pmu_gpio_set_level(QL_GPIO_PD4,QL_GPIO_OUTPUT_LOW);
    }else{
        ql_pmu_gpio_set_level(QL_GPIO_PD4,QL_GPIO_OUTPUT_HIGH);
    }
    cnt++;
    ql_debug(" int cnt=%d\\r\\n",cnt);
    if(cnt >= 10){
        ql_pmu_gpio_int_disable(QL_GPIO_PD6);
        cnt = 0;
    }
}

Function Debugging

To debug the PMU GPIO function, use the development board (HCM111Z TE-B) with the module and follow these steps:

  1. Recompile the firmware version and flash it to the module.
  2. Reboot the module.
  3. Open UART port 1 to obtain the debugging logs. The log information will be displayed as follows:

Capturing Logs via Serial Port Tool

If the following information is printed during the debugging, it indicates that the PMU GPIO interrupt has been triggered.

PMU GPIO Test Log

UART API

Header File

ql_uart.h, the header file of UART API, is in the components/quectel_api/ql_include directory. Unless otherwise specified, all header files mentioned in this document are in this directory.

API Overview

Function Description
ql_uart_set_dcbconfig() Sets the UART port properties.
ql_uart_get_dcbconfig() Gets the configuration of UART port properties.
ql_uart_open() Opens the UART port.
ql_uart_close() Closes the UART port.
ql_uart_write() Writes data to the module through the UART port.
ql_uart_read() Reads the data from the module through the UART port.
ql_uart_set_rx_cb() Registers the callback function for UART data interrupt.

API Description

ql_uart_set_dcbconfig

This function sets the UART port properties, which take effect after the UART port is re-opened.

Prototype:

ql_uart_errcode_e ql_uart_set_dcbconfig(ql_uart_port_number_e port, ql_uart_config_s *dcb)

Parameters:

Return Value:

Function execution result code. See ql_uart_errcode_e.


ql_uart_port_number_e

The enumeration of the UART port number is defined below. The module currently supports two UART ports.

typedef enum {
  QL_UART_PORT_1,
  QL_UART_PORT_2,
} ql_uart_port_number_e

Member:

Member Description
QL_UART_PORT_1 UART port 1
QL_UART_PORT_2 UART port 2

ql_uart_config_s

The structure of the configuration of UART port properties:

typedef struct {
  uint8_t is_debug_port;
  ql_uart_baud_e baudrate;
  ql_uart_databit_e data_bit;
  ql_uart_stopbit_e stop_bit;
  ql_uart_parityit_e parity_bit;
} ql_uart_config_s

Parameter:

Type Parameter Description
uint8_t is_debug_port Print log (0: Receive and send data)
ql_uart_baud_e baudrate Baud rate. Default: 115200 bps.See ql_uart_baud_e
ql_uart_databit_e data_bit Data bit. Default: 8 bits.See ql_uart_databit_e
ql_uart_stopbit_e stop_bit Stop bit. Default: 1 bit.See ql_uart_stopbit_e
ql_uart_parityit_e parity_bit Parity bit. Default: No parity bit.See ql_uart_parityit_e

ql_uart_baud_e

The enumeration of baud rates:

typedef enum {
  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_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_e

Member:

Member Description
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_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_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

Member:

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,
  QL_UART_STOP_2,
} ql_uart_stopbit_e

Member:

Member Description
QL_UART_STOP_1 1 bit
QL_UART_STOP_2 2 bits

ql_uart_parityit_e

The enumeration of parity bits:

typedef enum {
  QL_UART_PARITY_NONE,
  QL_UART_PARITY_ODD,
  QL_UART_PARITY_EVEN,
} ql_uart_parityit_e

Member:

Member Description
QL_UART_PARITY_NONE No parity
QL_UART_PARITY_ODD Odd parity
QL_UART_PARITY_EVEN Even parity

ql_uart_errcode_e

The enumeration of UART 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

Member:

Member Description
QL_UART_SUCCESS Successful execution
QL_UART_EXECUTE_ERR Failed execution
QL_UART_MEM_ADDR_NULL_ERR Parameter address is 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)

Parameters:

Return Value:

Function execution result code. See ql_uart_errcode_e.


ql_uart_open

This function opens the UART port.

Prototype:

ql_uart_errcode_e ql_uart_open(ql_uart_port_number_e port)

Parameters:

Return Value:

Function execution result code. See ql_uart_errcode_e.


ql_uart_close

This function closes the UART port.

Prototype:

ql_uart_errcode_e ql_uart_close(ql_uart_port_number_e port)

Parameters:

Return Value:

Function execution result code. See ql_uart_errcode_e.


ql_uart_write

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

Prototype:

int ql_uart_write(ql_uart_port_number_e port, unsigned char *data, unsigned int data_len)

Parameters:

  • port: [In] UART port number. See ql_uart_port_number_e.
  • data: [In] Written data.
  • data_len: [In] Length of written data.

Return Value:

Function execution result code. See ql_uart_errcode_e.


ql_uart_read

This function reads the data from the module through the UART port.

Prototype:

int ql_uart_read(ql_uart_port_number_e port, unsigned char *data, unsigned int data_len)

Parameters:

  • port: [In] UART port number. See ql_uart_port_number_e.
  • data: [Out] Read data.
  • data_len: [In] Length of read data.

Return Value:

Function execution result code. See ql_uart_errcode_e.


ql_uart_set_rx_cb

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

Prototype:

ql_uart_errcode_e ql_uart_set_rx_cb(ql_uart_port_number_e port, ql_uart_callback uart_cb)

Parameters:

Return Value:

Function execution result code. See ql_uart_errcode_e.


ql_uart_callback

This is the callback function that handles the UART interrupt.

Prototype:

typedef void (*ql_uart_callback)(char value)

Parameters:

  • value: [In] Data received via the UART port.

Return Value:

None


UART Development Process

This chapter describes how to use the above UART API in the application and perform basic debugging. UART 0 is used in the following example by default.

UART Operation

The example of how to use the UART API is provided in the quectel_demo/ql_uart_demo/code/ql_uart_demo.c file in the module SDK. The related functions are described as follows:

  • demo_uart(): Initializes the UART port and registers the interrupt callback function.
  • ql_uart_cb_test(): Interrupt callback function that handles the data received through the UART port.

The example of using the UART API is as follows:

void demo_uart(void)
{
    ql_uart_config_s cfg = {
        .is_debug_port = 0, //0 | 1
        .baudrate = QL_UART_BAUD_115200,
        .data_bit = QL_UART_DATABIT_8,
        .stop_bit = QL_UART_STOP_1,
        .parity_bit = QL_UART_PARITY_NONE,
    };
    ql_debug("uart demo\\r\\n");
    ql_gpio_set_port_mux(QL_GPIO_PD4,QL_PORTD4_FUNC_UART0_RXD);
    ql_gpio_set_port_mux(QL_GPIO_PD5,QL_PORTD5_FUNC_UART0_TXD);
    ql_gpio_set_port_pull(QL_GPIO_PD4, true);
    ql_uart_set_dcbconfig(QL_UART_PORT_0,&cfg);
    ql_uart_set_rx_cb(QL_UART_PORT_0,ql_uart_cb_test);
    ql_uart_open(QL_UART_PORT_0);
}

void ql_uart_cb_test(char value)
{
    char data = value;
    ql_debug("recv %0x\\r\\n",data);
    ql_uart_write(QL_UART_PORT_0,(unsigned char*)&data,1);
}

Function Debugging

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

  1. Recompile the firmware version and flash it to the module.
  2. Reboot the module.
  3. Open UART port 1 to obtain the debugging logs. The log information will be displayed as follows:

Capturing Logs via Serial Port Tool


ADC API

Header File

ql_adc.h, the header file of ADC API, is in the components/quectel_api/ql_include directory. Unless otherwise specified, all header files mentioned in this document are in this directory.

API Overview

Function Description
ql_adc_channel_init() Configures ADC channel parameters.
ql_adc_channel_start() Enables ADC channel detection.
ql_adc_channel_stop() Disables ADC channel detection.

API Description

ql_adc_channel_init

This function configures ADC channel parameters.

Prototype:

ql_adc_errcode_e ql_adc_channel_init(ql_adc_obj_s *handle, ql_adc_obj_callback cb, ql_adc_channel_e channel, void *user_data)

Parameters:

Return Value:

Function execution result code. See ql_adc_errcode_e.


ql_adc_obj_s

The structure of ADC channels:

typedef struct adc_obj_ {
  void *user_data;
  ql_adc_channel_e channel;
  ql_adc_obj_callback cb;
  struct adc_obj_ *next;
} ql_adc_obj_s

Parameter:

Type Parameter Description
void user_data User data.
ql_adc_channel_e channel ADC channel number.
ql_adc_obj_callback cb Callback function for channel detection.
struct adc_obj_ next Address of the next node in the Linked List.

ql_adc_obj_callback

This function is the callback function for ADC channel detection.

Prototype:

typedef void (*ql_adc_obj_callback)(ql_adc_channel_e channel, int value, void *user_data)

Parameters:

  • channel: [Out] ADC channel number. See ql_adc_channel_e.
  • value: [In] ADC channel voltage sampling result. Range: 0--1023. Reference voltage: 3.3 V. When the sampling result is 1023, it means that the channel voltage is greater than or equal to 3.3 V.
  • user_data: [In] User data.

Return Value:

None


ql_adc_channel_e

The enumeration of ADC channel number.

typedef enum {
  QL_ADC_CHANNEL_0 = 0x01,
  QL_ADC_CHANNEL_1 = 0x02,
  QL_ADC_CHANNEL_2 = 0x04,
  QL_ADC_CHANNEL_3 = 0x08,
} ql_adc_channel_e

Parameter:

Parameter Description
QL_ADC_CHANNEL_0 Channel 0, detecting voltage for QL_GPIO_PD4.
QL_ADC_CHANNEL_1 Channel 1, detecting voltage for QL_GPIO_PD5.
QL_ADC_CHANNEL_2 Channel 2, detecting voltage for QL_GPIO_PD6.
QL_ADC_CHANNEL_3 Channel 3, detecting voltage for QL_GPIO_PD7.

ql_adc_errcode_e

The enumeration of ADC result codes:

typedef enum {
  QL_ADC_SUCCESS = 0,
  QL_ADC_EXECUTE_ERR,
  QL_ADC_INVALID_PARAM_ERR,
} ql_adc_errcode_e

Parameter:

Parameter Description
QL_ADC_SUCCESS Successful execution
QL_ADC_EXECUTE_ERR Failed execution
QL_ADC_INVALID_PARAM_ERR Invalid parameter

ql_adc_channel_start

This function enables ADC channel detection.

Prototype:

ql_adc_errcode_e ql_adc_channel_start(ql_adc_obj_s *handle)

Parameters:

Return Value:

Function execution result code. See ql_adc_errcode_e.


ql_adc_channel_stop

This function disables ADC channel detection.

Prototype:

ql_adc_errcode_e ql_adc_channel_stop(ql_adc_obj_s *handle)

Parameters:

Return Value:

Function execution result code. See ql_adc_errcode_e.


ADC Development Process

This chapter describes how to use the above ADC API in the application, and perform basic debugging. In the example, channel 0 is used for test by default.

ADC Operation

The example of how to use the ADC API is provided in the quectel_demo/ql_adc_demo/code/ql_adc_demo.c file the module SDK. The related functions are described as follows:

  • demo_adc(): Configure and initialize ADC channels.
  • adc_tim_fn(): The timer callback function, which implements ADC channel detection every 1 s.

The example of using ADC API is as follows:

void demo_adc(void)
{
    ql_debug("adc demo\\r\\n");
    ql_gpio_set_port_mux(QL_GPIO_PD4,QL_PORTD4_FUNC_ADC0);
    ql_soft_timer_init(&adc_timer , adc_tim_fn , NULL);
    ql_soft_timer_start(&adc_timer,1000,1);
}
void adc_tim_fn(void *arg)
{
    ql_adc_channel_init(&ql_test_adc , ql_adc_detect_callback , QL_ADC_CHANNEL_0 , NULL);
    ql_adc_channel_start(&ql_test_adc);
    ql_adc_channel_stop(&ql_test_adc);
}

You can print the result of ADC channel detection through ql_adc_detect_callback() as follows:

static void ql_adc_detect_callback(ql_adc_channel_e channel, int value , void *user_data)
{
    ql_debug("adc channel %d , value %d \\r\\n" , channel , value);
}

Function Debugging

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

  1. Recompile the firmware version and flash it to the module.
  2. Reboot the module.
  3. Open UART port 1 to obtain 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 Serial Port Tool


PWM API

Header File

ql_pwm.h, the header file of PWM API, is in the components/quectel_api/ql_include directory. Unless otherwise specified, all header files mentioned in this document are in this directory.

API Overview

Function Description
ql_pwm_init() Initializes PWM.
ql_pwm_update_param() Updates the PWM parameters.
ql_pwm_enable() Enables PWM output.
ql_pwm_disable() Disables PWM output.

API Description

ql_pwm_init

This function initializes PWM.

Prototype:

ql_pwm_errcode_e ql_pwm_init(ql_pwm_channel_e channel, uint32_t frequency, uint32_t high_duty)

Parameters:

  • channel: [In] PWM channel. See ql_pwm_channel_e.
  • frequency: [In] PWM frequency.
  • high_duty: [In] PWM duty cycle.

Return Value:

Function execution result code. See ql_pwm_errcode_e.


ql_pwm_channel_e

The enumeration of PWM channels. There are 6 PWM channels in total.

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 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_update_param

This function updates the PWM parameters. The updated parameters take effect in next PWM period.

Prototype:

ql_pwm_errcode_e ql_pwm_update_param(ql_pwm_channel_e channel, uint32_t frequency, uint32_t high_duty)

Parameters:

  • channel: [In] PWM channel. See ql_pwm_channel_e.
  • frequency: [In] PWM frequency.
  • high_duty: [In] PWM duty cycle.

Return Value:

Function execution result code. See ql_pwm_errcode_e.


ql_pwm_enable

This function enables PWM output.

Prototype:

ql_pwm_errcode_e ql_pwm_enable(ql_pwm_channel_e channel)

Parameters:

Return Value:

Function execution result code. See ql_pwm_errcode_e.


ql_pwm_disable

This function disables PWM output.

Prototype:

ql_pwm_errcode_e ql_pwm_disable(ql_pwm_channel_e channel)

Parameters:

Return Value:

Function execution result code. See ql_pwm_errcode_e.


PWM Development Process

This chapter describes how to use the above PWM API in the application, and perform simple debugging. In the example, QL_PWM_4 and QL_PWM_5 are used for test by default.

PWM Operation

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

  • demo_pwm(): Initializes PWM, enables PWM output and disables PWM output.

The example of using PWM API is as follows:

void demo_pwm(void)
{
    ql_debug("digital_pwm demo\\r\\n");
    ql_gpio_set_port_mux(QL_GPIO_PD4,QL_PORTD4_FUNC_PWM4);
    ql_gpio_set_port_mux(QL_GPIO_PD5,QL_PORTD5_FUNC_PWM5);
    ql_pwm_init(QL_PWM_4,1000,50);
    ql_pwm_init(QL_PWM_5,1000,80);
    ql_pwm_enable(QL_PWM_4);
    ql_pwm_enable(QL_PWM_5);
    ql_sys_delay_100us(20000); //1 kHz for 2 s
    ql_pwm_update_param(QL_PWM_4,10000,80);
    ql_pwm_update_param(QL_PWM_5,10000,50);
    ql_sys_delay_100us(10000); //10K Hz for 1 s
    ql_pwm_disable(QL_PWM_4);
    ql_pwm_disable(QL_PWM_5);
    ql_sys_delay_100us(20000); //Stop for 2 s
    ql_pwm_enable(QL_PWM_4);
    ql_pwm_enable(QL_PWM_5);
    ql_sys_delay_100us(10000); //Restart PWM with 10 kHz for 1 s
    ql_pwm_disable(QL_PWM_4);
    ql_pwm_disable(QL_PWM_5);
}

Function Debugging

To debug the PWM function use the development board (HCM111Z TE-B) with the module and follow these steps:

  1. Recompile the firmware version and flash it to the module.
  2. Reboot the module.
  3. Open UART port 1 to obtain the debugging logs. The log information will be displayed as follows:

Capturing Logs via Serial Port Tool

Capturing PWM Waveforms with Logic Analyzer


SPI API

Header File

ql_spi.h, the header file of SPI API, is in the components/quectel_api/ql_include directory. Unless otherwise specified, all header files mentioned in this document are in this directory.

API Overview

Function Description
ql_spi_init() Initializes SPI.
ql_spi_transfer() Sends or receives SPI data.

API Description

ql_spi_init

This function initializes SPI.

Prototype:

ql_spi_errcode_e ql_spi_init(ql_spi_config_s spi_cfg)

Parameters:

Return Value:

Function execution result code. See ql_spi_errcode_e.


ql_spi_config_s

The structure of SPI configuration:

typedef struct {
  uint32_t spiclk;
  ql_spi_cpol_pol_e cpol;
  ql_spi_cpha_pol_e cpha;
  ql_spi_master_slave_mode_e masterorslave;
  void (*spi_cs_ctrl)(uint8_t);
} ql_spi_config_s

Parameter:

Type Parameter Description
uint32_t spiclk SPI clock frequency. Maximum value: 24 MHz.
ql_spi_cpol_pol_e cpol SPI clock polarity.See ql_spi_cpol_pol_e.
ql_spi_cpha_pol_e cpha SPI clock phase.See ql_spi_cpha_pol_e.
ql_spi_master_slave_mode_e masterorslave SPI master or slave selection.See ql_spi_master_slave_mode_e.
void (*spi_cs_ctrl)(uint8_t) spi_cs_ctrl Function pointer for controlling CS pin.See ql_spi_cs_ctrl() in SPI Operation.

ql_spi_cpol_pol_e

The enumeration of SPI clock polarities:

typedef enum {
  QL_SPI_CPOL_LOW = 0,
  QL_SPI_CPOL_HIGH,
} ql_spi_cpol_pol_e

Member:

Member Description
QL_SPI_CPOL_LOW SCK is at a low level during the idle state.
QL_SPI_CPOL_HIGH SCK is at a high level during the idle state.

ql_spi_cpha_pol_e

The enumeration of SPI clock phases:

typedef enum {
  QL_SPI_CPHA_1Edge,
  QL_SPI_CPHA_2Edge,
} ql_spi_cpha_pol_e

Member:

Member Description
QL_SPI_CPHA_1Edge Sample data on the edge of the first period of SCK.
QL_SPI_CPHA_2Edge Sample data on the edge of the second period of SCK.

ql_spi_master_slave_mode_e

The enumeration of SPI master or slave selections:

typedef enum {
  QL_SPI_MASTER = 0,
  QL_SPI_SLAVE,
} ql_spi_master_slave_mode_e

Member:

Member Description
QL_SPI_MASTER SPI serves as the master.
QL_SPI_SLAVE SPI serves as the slave (Currently not supported).

ql_spi_errcode_e

The enumeration of SPI result codes:

typedef enum {
  QL_SPI_SUCCESS = 0,
  QL_SPI_EXECUTE_ERR,
  QL_SPI_INVALID_PARAM_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_transfer

This function sends or receives SPI data.

Prototype:

ql_errcode_spi_e ql_spi_transfer(ql_spi_messag_s *spi_msg)

Parameters:

Return Value:

Function execution result code. See ql_spi_errcode_e.


ql_spi_messag_s

The structure of data sent or received via SPI:

typedef struct {
  UINT8 *send_buf;
  UINT32 send_len;
  UINT8 *recv_buf;
  UINT32 recv_len;
} ql_spi_message_s

Parameter:

Type Parameter Description
UINT8 send_buf Sent data
UINT32 send_len Length of the sent data
UINT8 recv_buf Received data
UINT32 recv_len Length of the received data

SPI Development Process

This chapter describes how to use the above SPI API in the application, and perform basic debugging.

SPI Operation

The example of how to use the SPI API is provided in the quectel_demo/ql_spi_demo/code/ql_spi_demo.c file in the module SDK. The related functions are described as follows:

  • demo_spi_master(): Initializes SPI, sends and receives data.
  • ql_spi_cs_ctrl(): Controls CS pin.

The example of using SPI API is as follows:

void demo_spi_master(void)
{
    ql_debug("spi master demo\\r\\n");
    uint8_t send_buff[128] = {0};
    uint8_t recv_buff[128] = {0};
    int i = 0;
    for(i=0;i<128;i++)
        send_buff[i] = i;
    ql_spi_config_s cfg = {
        .spiclk = 3000000,
        .cpol = QL_SPI_CPOL_LOW,
        .cpha = QL_SPI_CHPA_1EDGE,
        .masterorslave = QL_SPI_MASTER,
        .spi_cs_ctrl = ql_spi_cs_ctrl,
    };
    ql_spi_message_s msg = {
        .send_buf = send_buff,
        .send_len = 128,
        .recv_buf = recv_buff,
        .recv_len = 128,
    };
    ql_gpio_set_port_mux(QL_GPIO_PD4, QL_PORTD4_FUNC_SSP0_CLK);
    //ql_gpio_set_port_mux(QL_GPIO_PD5, QL_PORTD5_FUNC_SSP0_CSN);
    ql_gpio_set_port_mux(QL_GPIO_PD5, QL_PORTD5_FUNC_D5);
    ql_gpio_init(QL_GPIO_PD5,QL_GMODE_OUTPUT);
    ql_gpio_set_port_mux(QL_GPIO_PD6, QL_PORTD6_FUNC_SSP0_DOUT);
    ql_gpio_set_port_mux(QL_GPIO_PD7, QL_PORTD7_FUNC_SSP0_DIN);
    ql_spi_init(cfg);
    ql_spi_transfer(&msg);
    ql_debug("spi master demo over\\r\\n");
}

void ql_spi_cs_ctrl(uint8_t enable)
{
    ql_gpio_set_level(QL_GPIO_PD5,enable);
}

Function Debugging

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

  1. Recompile the firmware version and flash it to the module.
  2. Reboot the module.
  3. Open UART port 1 to obtain the debugging logs. The log information will be displayed as follows:

Capturing Logs via Serial Port Tool

Capturing SPI Waveforms Through Logic Analyzer


I2C API

Header File

ql_i2c.h, the header file of I2C API, is in the components/quectel_api/ql_include directory. Unless otherwise specified, all I2C header files mentioned in this document are in this directory.

API Overview

Function Description
ql_i2c_init() Initializes the I2C bus.
ql_i2c_write() Writes data to the I2C bus.
ql_i2c_read() Reads data from the I2C bus.
ql_i2c_master_init() Initializes the I2C master.
ql_i2c_master_transmit() Transmits data from I2C master to the slave.
ql_i2c_master_receive() Reads the data transmitted from I2C slave by I2C master.
ql_i2c_slave_init() Initializes the I2C slave.
ql_i2c_slave_transmit() Transmits data from I2C slave to I2C master.
ql_i2c_slave_receive() Reads the data transmitted from I2C master by I2C slave.

API Description

ql_i2c_init

This function initializes the I2C bus.

Prototype:

ql_errcode_i2c_e ql_i2c_init(QL_DD_HANDLE *i2c_hdl, ql_i2c_mode mode, ql_i2c_channel_e channel)

Parameters:

Return Value:

Function execution result code. See ql_errcode_i2c_e.


ql_i2c_mode_e

The enumeration of I2C bus operating modes:

typedef enum {
  STANDARD_MODE = 0,
  FAST_MODE = 1,
} ql_i2c_mode_e

Member:

Member Description
QL_STANDARD_MODE Standard mode
FAST_MODE Fast mode

ql_i2c_channel_e

The enumeration of I2C channels:

typedef enum {
  QL_I2C_CHANNEL_0 = 0,
  QL_I2C_CHANNEL_1,
} ql_i2c_channel_e

Member:

Member Description
QL_I2C_CHANNEL_0 I2C channel 0
QL_I2C_CHANNEL_1 I2C channel 1

ql_errcode_i2c_e

The enumeration of the I2C result codes:

typedef enum {
  QL_I2C_SUCCESS = 0,
  QL_I2C_INIT_ERR,
  QL_I2C_WRITE_ERR,
  QL_I2C_READ_ERR,
} ql_errcode_i2c_e

Member:

Member Description
QL_I2C_SUCCESS Successful execution
QL_I2C_INIT_ERR Failed I2C initialization
QL_I2C_WRITE_ERR Failed to write data to I2C
QL_I2C_READ_ERR Failed to read data from I2C

ql_i2c_write

This function writes data to the I2C bus.

Prototype:

ql_errcode_i2c_e ql_i2c_write(QL_DD_HANDLE *i2c_hdl, uint8_t slave_addr, uint8_t reg_addr, char *data, uint32_t len)

Parameters:

  • i2c_hdl: [In] I2C handle.
  • slave_addr: [In] I2C slave device address.
  • reg_addr: [In] I2C slave register address.
  • data: [In] Data to be written to the I2C bus.
  • len: [In] Data length to be written to the I2C bus.

Return Value:

Function execution result code. See ql_errcode_i2c_e.


ql_i2c_read

This function reads data from the I2C bus.

Prototype:

ql_errcode_i2c_e ql_i2c_read(QL_DD_HANDLE *i2c_hdl, uint8_t slave_addr, uint8_t reg_addr, char *data, uint32_t len)

Parameters:

  • i2c_hdl: [In] I2C handle.
  • slave_addr: [In] I2C slave device address.
  • reg_addr: [In] I2C slave register address.
  • data: [Out] Data read from the I2C bus.
  • len: [In] Data length read from the I2C bus.

Return Value:

Function execution result code. See ql_errcode_i2c_e.


ql_i2c_master_init

This function initializes the I2C master.

Prototype:

ql_errcode_i2c_e ql_i2c_master_init(ql_i2c_channel_e i2c_channel, ql_i2c_mode i2c_mode, ql_i2c_pin_mux_e pin_mux)

Parameters:

  • i2c_channel: [In] I2C channel. Only QL_I2C_CHANNEL_1 is supported.
  • i2c_mode: [In] Working mode of I2C.
  • pin_mux: [In] Multiplexed GPIO combination of I2C's SCL and SDA. See ql_i2c_pin_mux_e.

Return Value:

Function execution result code. See ql_errcode_i2c_e.


ql_i2c_pin_mux_e

The enumeration of multiplexed GPIO combination of I2C's SCL and SDA:

typedef enum {
  // I2C1_CLK I2C1_DAT
  QL_PIN_MUX_0, // PORTA2 PORTA3
  QL_PIN_MUX_1, // PORTA6 PORTA7
  QL_PIN_MUX_2, // PORTB2 PORTB3
  QL_PIN_MUX_3, // PORTB6 PORTB7
  QL_PIN_MUX_4, // PORTC2 PORTC3
  QL_PIN_MUX_5, // PORTC6 PORTC7
  QL_PIN_MUX_6, // PORTD2 PORTD3
  QL_PIN_MUX_7  // PORTD6 PORTD7
} ql_i2c_pin_mux_e;

Member:

Member Description
QL_PIN_MUX_0 PA2 is used as SCL and PA3 is used as SDA.
QL_PIN_MUX_1 PA6 is used as SCL and PA7 is used as SDA.
QL_PIN_MUX_2 PB2 is used as SCL and PB3 is used as SDA.
QL_PIN_MUX_3 PB6 is used as SCL and PB7 is used as SDA.
QL_PIN_MUX_4 PC2 is used as SCL and PC3 is used as SDA.
QL_PIN_MUX_5 PC6 is used as SCL and PC7 is used as SDA.
QL_PIN_MUX_6 PD2 is used as SCL and PD3 is used as SDA.
QL_PIN_MUX_7 PD6 is used as SCL and PD7 is used as SDA.

ql_i2c_master_transmit

This function transmits data from I2C master to the slave.

Prototype:

ql_errcode_i2c_e ql_i2c_master_transmit(ql_i2c_channel_e i2c_channel, uint8_t slave_addr, uint8_t *data, uint16_t data_len)

Parameters:

  • i2c_channel: [In] I2C channel. Only QL_I2C_CHANNEL_1 is supported.
  • slave_addr: [In] I2C slave device address with no offset.
  • data: [In] The transmitted data.
  • data_len: [In] Length of the transmitted data.

Return Value:

Function execution result code. See ql_errcode_i2c_e.


ql_i2c_master_receive

This function reads the data transmitted from I2C slave by I2C master.

Prototype:

ql_errcode_i2c_e ql_i2c_master_receive(ql_i2c_channel_e i2c_channel, uint8_t slave_addr, uint8_t *data, uint16_t *data_len)

Parameters:

  • i2c_channel: [In] I2C channel. Only QL_I2C_CHANNEL_1 is supported.
  • slave_addr: [In] I2C slave device address with no offset.
  • data: [Out] The read data.
  • data_len: [Out] Length of the read data.

Return Value:

Function execution result code. See ql_errcode_i2c_e.


ql_i2c_slave_init

This function initializes the I2C slave.

Prototype:

ql_errcode_i2c_e ql_i2c_slave_init(ql_i2c_channel_e i2c_channel, ql_i2c_mode i2c_mode, ql_i2c_pin_mux_e pin_mux, uint16_t slave_addr)

Parameters:

  • i2c_channel: [In] I2C channel. Only QL_I2C_CHANNEL_1 is supported.
  • i2c_mode: [In] Working mode of I2C.
  • pin_mux: [In] Multiplexed GPIO combination of I2C's SCL and SDA. See ql_i2c_pin_mux_e.
  • slave_addr: [In] Initialization address of the slave.

Return Value:

Function execution result code. See ql_errcode_i2c_e.


ql_i2c_slave_transmit

This function transmits data from I2C slave to I2C master.

Prototype:

ql_errcode_i2c_e ql_i2c_slave_transmit(ql_i2c_channel_e i2c_channel, uint8_t *data, uint16_t data_len)

Parameters:

  • i2c_channel: [In] I2C channel. Only QL_I2C_CHANNEL_1 is supported.
  • data: [In] The transmitted data.
  • data_len: [In] Length of the transmitted data.

Return Value:

Function execution result code. See ql_errcode_i2c_e.


ql_i2c_slave_receive

This function reads the data transmitted from I2C master by I2C slave.

Prototype:

ql_errcode_i2c_e ql_i2c_slave_receive(ql_i2c_channel_e i2c_channel, uint8_t *data, uint16_t *data_len)

Parameters:

  • i2c_channel: [In] I2C channel. Only QL_I2C_CHANNEL_1 is supported.
  • data: [Out] The read data.
  • data_len: [Out] Length of the read data.

Return Value:

Function execution result code. See ql_errcode_i2c_e.


I2C Development Process

This chapter describes how to use the above I2C API in the application, and perform basic debugging. QL_I2C_CHANNEL_1 is used for test by default.

I2C Operation

The example of how to use the I2C API is provided in the quectel_demo/ql_i2c_demo/code/ql_i2c_demo.c file in the module SDK. In this example, the module operates as the I2C master device for communicating with the chip. The related functions are described as follows:

  • demo_i2c(): Initializes I2C channel 1.

The example of using I2C API is as follows:

void demo_i2c(void)
{
    uint8_t i2c_test_no = 0;
    char data = 0;
    uint8_t buff1[6];
    uint8_t buff2[6];
    ql_debug("IIC demo\\r\\n");
    ql_gpio_set_port_mux(QL_GPIO_PD6, QL_PORTD6_FUNC_I2C1_CLK);//PD6
    ql_gpio_set_port_mux(QL_GPIO_PD7, QL_PORTD7_FUNC_I2C1_DAT);//PD7
    ql_gpio_set_port_pull(QL_GPIO_PD6,1);
    ql_gpio_set_port_pull(QL_GPIO_PD7,1);
    //IIC1, 1 MHz. slave addr: 0xd6
    ql_i2c_init(&i2c_hdl ,QL_STANDARD_MODE,QL_I2C_CHANNEL_1);
    // iic_init(IIC_CHANNEL_1,1000,LSM6DS33_ADDR);
    data = 0;
    ql_i2c_write(&i2c_hdl ,LSM6DS33_ADDR ,0x15,&data,1);
    ql_i2c_write(&i2c_hdl ,LSM6DS33_ADDR ,0x16,&data,1);
    data = 0x80;
    ql_i2c_write(&i2c_hdl ,LSM6DS33_ADDR ,0x10,&data,1);
    ql_i2c_write(&i2c_hdl ,LSM6DS33_ADDR ,0x11,&data,1);
    data = 0x04;
    ql_i2c_write(&i2c_hdl ,LSM6DS33_ADDR ,0x12,&data,1);
    while(1)
    {
        for(uint8_t i=0; i<6; i++)
        {
            ql_i2c_read(&i2c_hdl ,LSM6DS33_ADDR ,0x28+i,(char*)&buff1[i],1);
            ql_i2c_read(&i2c_hdl ,LSM6DS33_ADDR ,0x22+i,(char*)&buff2[i],1);
        }
        ql_debug("X:%d |Y:%d |Z:%d\\r\\n",*(uint16_t *)buff1,*(uint16_t *)(buff1+2),*(uint16_t *)(buff1+4));
        ql_debug("AccX:%d|Acc_Y:%d|Acc_Z:%d\\r\\n",*(uint16_t *)buff2,*(uint16_t *)(buff2+2),*(uint16_t *)(buff2+4));
        i2c_test_no++;
        if(i2c_test_no>3)
            break;
    }
}

Function Debugging

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

  1. Recompile the firmware version and flash it to the module.
  2. Reboot the module.
  3. Capture the I2C waveforms with a logic analyzer as shown below:

Capturing I2C Waveforms of PWM with Logic Analyzer

I2C Master and Slave Mode Debugging

The SDK code of the module provides examples of operating the I2C master and slave modes, which are located in the files ql_i2c_master.c and ql_i2c_slave.c in the directory quectel_demo/ql_i2c_demo/code. In this example, one module communicates via I2C as the master and the other as the slave. The following explains the related functions:

I2C Slave Operation
  • ql_i2c_demo_slave_init()*`: Initializes I2C slave channel 1, with PA6 serving as SCL, PA7 as SDA, and PA0 indicating that data is ready.

The I2C slave initialization example is as follows:

void ql_i2c_demo_slave_init(void)
{
    ql_debug("I2C SLAVE DEMO RUNNING\\r\\n");

    /* Configure I/O port to check whether data is ready on the slave */
    ql_gpio_set_port_mux(QL_GPIO_PA0, QL_PORTA0_FUNC_A0);
    ql_gpio_set_dir(QL_GPIO_PA0, QL_GMODE_OUTPUT);	
    ql_gpio_set_level(QL_GPIO_PA0 , QL_GPIO_OUTPUT_HIGH);

    /* Prepare the data to be sent */
    for(uint32_t i = 0; i < sizeof(slave_send_data); i++)
    {
        slave_send_data[i] = i + 10;
    }

    /* Initialization I2C slave */
    if(QL_I2C_SUCCRSS != ql_i2c_slave_init(QL_I2C_CHANNEL_1, QL_FAST_PLUS_MODE, QL_PIN_MUX_1, IIC_SLVAE_ADDRESS))
    {
        ql_debug("I2C SLAVE INIT FAIL!\\r\\n");
    }

    while(1)
    {
        ql_i2c_slave_receive(QL_I2C_CHANNEL_1, ql_slave_recv_data, &ql_slave_recv_len);
        if(ql_slave_recv_len > 0)
        {
            ql_debug("SLAVE -> RECV DATA FROM MASTER, DATA LENGTH:%d\\r\\n", ql_slave_recv_len);
            for (uint32_t i = 0; i < ql_slave_recv_len; i++)
            {
                ql_debug("%02X ", ql_slave_recv_data[i]);
            }
            ql_debug("\\r\\n"); 

            ql_gpio_set_level(QL_GPIO_PA0 , QL_GPIO_OUTPUT_HIGH);

            slave_send_data[0] = ql_slave_send_cnt++;
            if(ql_slave_send_cnt > 255) ql_slave_send_cnt = 0;

            ql_i2c_slave_transmit(QL_I2C_CHANNEL_1, slave_send_data, sizeof(slave_send_data));

            /* Notification master */
            ql_gpio_set_level(QL_GPIO_PA0 , QL_GPIO_OUTPUT_LOW);
        }
    }
}
I2C Master Operation
  • ql_i2c_demo_master_init(): Initializes I2C master channel 1, with PA6 serving as SCL, PA7 as SDA, and PA0 indicating that data is ready.

The I2C master initialization example is as follows:

void ql_i2c_demo_master_init(void)
{
    ql_debug("I2C MASTER DEMO RUNNING\\r\\n");

    /* Configure I/O port to check whether data is ready on the slave */
    ql_gpio_set_port_pull(QL_GPIO_PA0,1);
    ql_gpio_set_port_mux(QL_GPIO_PA0, QL_PORTA0_FUNC_A0);
    ql_gpio_set_dir(QL_GPIO_PA0, QL_GMODE_INPUT_PULLUP);

    /* Prepare the data to be sent */
    for (uint32_t i = 1; i < sizeof(master_send_data); i++)
    {
        master_send_data[i] = i;
    }

    /* Initialization I2C master */
    if(QL_I2C_SUCCRSS != ql_i2c_master_init(QL_I2C_CHANNEL_1, QL_FAST_MODE, QL_PIN_MUX_1))
    {
        ql_debug("I2C MASTER INIT FAIL!\\r\\n");
    }

    while (1)
    {   
        /* Master send data counter */
        master_send_data[0] = ql_master_send_cnt++;
        if(ql_master_send_cnt > 255) ql_master_send_cnt = 0;

        /* Master transmit data to slave via i2c port */
        ql_i2c_master_transmit(QL_I2C_CHANNEL_1, IIC_SLVAE_ADDRESS, master_send_data, sizeof(master_send_data));

        /* Master wait for the slave to prepare data */
        while(gpio_get_pin_value(GPIO_PORT_A, GPIO_BIT_0));

        /* Master receive data from slave via i2c port */
        ql_i2c_master_receive(QL_I2C_CHANNEL_1, IIC_SLVAE_ADDRESS, ql_master_recv_data, &ql_master_recv_len);

        ql_debug("MASTER -> RECV DATA FROM SLAVE, DATA LENGTH:%d\\r\\n", ql_master_recv_len);
        for (uint32_t i = 0; i < ql_master_recv_len; i++)
        {
            ql_debug("%02X ", ql_master_recv_data[i]);
        }
        ql_debug("\\r\\n");   

        ql_sys_delay_100us(10000);
    }  
}

Connect the PA6, PA7, and PA0 pins of the two modules to each other, with PA0 serving as the pin indicating the slave data is ready. The I2C slave will print out the data received from the master and transmit the data back to the master.

I2C Master-Slave Communication Debugging


Terms and Abbreviations

Abbreviation Description
ADC Analog-to-Digital Converter
API Application Programming Interface
CLK Clock
CPHA Clock Phase
CPOL Clock Polarity
CS Chip Select
EVB Evaluation Board
GPIO General-Purpose Input/Output
I2C Inter-Integrated Circuit
IoT Internet of Things
PMU Power Management Unit
PWM Pulse Width Modulation
RTOS Real-Time Operating System
SCL Serial Clock Line
SDA Serial Data Line
SDK Software Development Kit
SPI Serial Peripheral Interface
UART Universal Asynchronous Receiver/Transmitter

HCM111Z QuecOpen(SDK) Peripheral Interface Development Guide

Introduction

Quectel HCM111Z module supports QuecOpen® solution. QuecOpen® is an embedded development platform, which is intended to simplify the design and development of IoT applications.

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


GPIO API

Header File

ql_gpio.h, the header file of GPIO API, is in the components/quectel_api/ql_include directory. Unless otherwise specified, all header files mentioned in this document are in this directory.

API Overview

Function Description
ql_gpio_set_port_mux() Sets the GPIO multiplexing feature.
ql_gpio_init() Initializes a GPIO pin.
ql_gpio_set_level() Sets the level of the specified GPIO pin.
ql_gpio_get_level() Gets the level of the specified GPIO pin.
ql_gpio_int_init() Initializes and enables the GPIO interrupt.
ql_gpio_int_disable() Disables the configured GPIO interrupt.
ql_gpio_set_port_pull() Sets the pull-up mode when GPIO is used as an input port.

API Description

ql_gpio_set_port_mux

This function sets the GPIO multiplexing feature.

Prototype:

ql_gpio_errcode_e ql_gpio_set_port_mux(ql_gpio_num_e pin, uint8_t func)

Parameters:

  • pin: [In] GPIO pin number. See ql_gpio_num_e.
  • func: [In] GPIO multiplexing feature.

Return Value:

Function execution result code. See ql_gpio_errcode_e.


ql_gpio_init

This function initializes a GPIO pin.

Prototype:

ql_gpio_errcode_e ql_gpio_init(ql_gpio_num_e pin, ql_gpio_mode_e mode)

Parameters:

Return Value:

Function execution result code. See ql_gpio_errcode_e.


ql_gpio_num_e

The enumeration of GPIO pin number:

typedef enum {
  QL_GPIO_PA0,
  QL_GPIO_PA1,
  QL_GPIO_PA2,
  QL_GPIO_PA3,
  QL_GPIO_PA4,
  QL_GPIO_PA5,
  QL_GPIO_PA6,
  QL_GPIO_PA7,
  QL_GPIO_PB0,
  QL_GPIO_PB1,
  QL_GPIO_PB2,
  QL_GPIO_PB3,
  QL_GPIO_PB4,
  QL_GPIO_PB5,
  QL_GPIO_PB6,
  QL_GPIO_PB7,
  QL_GPIO_PC0,
  QL_GPIO_PC1,
  QL_GPIO_PC2,
  QL_GPIO_PC3,
  QL_GPIO_PC4,
  QL_GPIO_PC5,
  QL_GPIO_PC6,
  QL_GPIO_PC7,
  QL_GPIO_PD0,
  QL_GPIO_PD1,
  QL_GPIO_PD2,
  QL_GPIO_PD3,
  QL_GPIO_PD4,
  QL_GPIO_PD5,
  QL_GPIO_PD6,
  QL_GPIO_PD7,
} ql_gpio_num_e

Member:

Member Description
QL_GPIO_PA0 GPIOA0
QL_GPIO_PA1 GPIOA1
QL_GPIO_PA2 GPIOA2
QL_GPIO_PA3 GPIOA3
QL_GPIO_PA4 GPIOA4
QL_GPIO_PA5 GPIOA5
QL_GPIO_PA6 GPIOA6
QL_GPIO_PA7 GPIOA7
QL_GPIO_PB0 GPIOB0
QL_GPIO_PB1 GPIOB1
QL_GPIO_PB2 GPIOB2
QL_GPIO_PB3 GPIOB3
QL_GPIO_PB4 GPIOB4
QL_GPIO_PB5 GPIOB5
QL_GPIO_PB6 GPIOB6
QL_GPIO_PB7 GPIOB7
QL_GPIO_PC0 GPIOC0
QL_GPIO_PC1 GPIOC1
QL_GPIO_PC2 GPIOC2
QL_GPIO_PC3 GPIOC3
QL_GPIO_PC4 GPIOC4
QL_GPIO_PC5 GPIOC5
QL_GPIO_PC6 GPIOC6
QL_GPIO_PC7 GPIOC7
QL_GPIO_PD0 GPIOD0
QL_GPIO_PD1 GPIOD1
QL_GPIO_PD2 GPIOD2
QL_GPIO_PD3 GPIOD3
QL_GPIO_PD4 GPIOD4
QL_GPIO_PD5 GPIOD5
QL_GPIO_PD6 GPIOD6
QL_GPIO_PD7 GPIOD7

ql_gpio_mode_e

The enumeration of GPIO pin modes:

typedef enum {
  QL_GMODE_INPUT_PULLDOWN = 1,
  QL_GMODE_INPUT_PULLUP,
  QL_GMODE_OUTPUT = 0,
} ql_gpio_mode_e

Member:

Member Description
QL_GMODE_INPUT_PULLDOWN Input is configured for pull-down
QL_GMODE_INPUT_PULLUP Input is configured for pull-up
QL_GMODE_OUTPUT Push-pull output

ql_gpio_errcode_e

The enumeration of GPIO result codes:

typedef enum {
  QL_GPIO_SUCCESS = 0,
  QL_GPIO_EXECUTE_ERR,
  QL_GPIO_INVALID_PARAM_ERR,
  QL_GPIO_EXTI_LINE_CLASH_ERR,
} ql_gpio_errcode_e

Member:

Member Description
QL_GPIO_SUCCESS Successful execution
QL_GPIO_EXECUTE_ERR Failed execution
QL_GPIO_INVALID_PARAM_ERR Invalid parameter
QL_GPIO_EXTI_LINE_CLASH_ERR GPIO interrupt line configuration conflict

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 pin, ql_gpio_output_level_e output_level)

Parameters:

Return Value:

Function execution result code. See ql_gpio_errcode_e.


ql_gpio_output_level_e

The enumeration of the GPIO output levels:

typedef enum {
  QL_GPIO_OUTPUT_LOW,
  QL_GPIO_OUTPUT_HIGH,
} ql_gpio_output_level_e

Member:

Member Description
QL_GPIO_OUTPUT_LOW Low level
QL_GPIO_OUTPUT_HIGH High level

ql_gpio_get_level

This function gets the level of the specified GPIO pin.

Prototype:

ql_gpio_errcode_e ql_gpio_get_level(ql_gpio_num_e pin, uint32_t *input_level)

Parameters:

  • pin: [In] GPIO pin number. See ql_gpio_num_e.
  • input_level: [Out] GPIO pin level.

Return Value:

Function execution result code. See ql_gpio_errcode_e.


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 pin, ql_gpio_irq_trigger_e trigger, ql_gpio_irq_callback callback)

Parameters:

Return Value:

Function execution result code. See ql_gpio_errcode_e.


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

Member:

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, uint8_t line)

Parameters:

  • arg: [In] Pin for triggering the GPIO interrupt.
  • line: [Out] Serial number of the external interrupt line that triggers the GPIO interrupt.

ql_gpio_int_disable

This function disables the configured GPIO interrupt.

Prototype:

ql_gpio_errcode_e ql_gpio_int_disable(ql_gpio_num_e pin)

Parameters:

Return Value:

Function execution result code. See ql_gpio_errcode_e.


ql_gpio_set_port_pull

This function sets the pull-up mode when GPIO is used as an input port.

Prototype:

ql_gpio_errcode_e ql_gpio_set_port_pull(ql_gpio_num_e pin, uint8_t enable)

Parameters:

  • pin: [In] GPIO pin number. See ql_gpio_num_e.
  • enable: [In] Set the pull-up mode.

True Enable the pull-up mode
False No setting

Return Value:

Function execution result code. See ql_gpio_errcode_e.


GPIO Development Process

This chapter describes how to use the above GPIO API to configure GPIO pins and perform basic debugging. QL_GPIO_PD4, QL_GPIO_PD5 and QL_GPIO_PD6 are used in the following examples by default.

GPIO Operation

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

  • demo_gpio(): Initializes a GPIO pin and enables the GPIO interrupt
  • ql_gpio_irq_test(): This is the interrupt callback function. It can implement functionalities such as setting the GPIO pin level and disabling GPIO interrupts.

The example of using the GPIO API is as follows:

void demo_gpio(void)
{
    ql_debug("digital gpio demo\\r\\n");
    //digital gpio output
    ql_gpio_set_port_mux(QL_GPIO_PD4 , QL_PORTD4_FUNC_D4);
    ql_gpio_set_port_mux(QL_GPIO_PD5 , QL_PORTD5_FUNC_D5);
    ql_gpio_set_port_mux(QL_GPIO_PD6 , QL_PORTD6_FUNC_D6);
    ql_gpio_init(QL_GPIO_PD4,QL_GMODE_OUTPUT);
    ql_gpio_init(QL_GPIO_PD5,QL_GMODE_INPUT_PULLDOWN);
    ql_gpio_set_level(QL_GPIO_PD4,QL_GPIO_OUTPUT_HIGH);
    ql_gpio_init(QL_GPIO_PD6 , QL_GMODE_INPUT_PULLDOWN);
    ql_gpio_int_init(QL_GPIO_PD6, QL_IRQ_TRIGGER_RISING_EDGE , ql_gpio_irq_test);
}
void ql_gpio_irq_test (void *arg,uint8_t line)
{
    static int cnt = 0;
    uint32_t input_level = 0;
    ql_gpio_get_level(QL_GPIO_PD5,&input_level);
    ql_debug("exit_line=%d\\r\\n",line);
    ql_debug(" gpio5 read=%d\\r\\n",input_level);
    if(input_level == 0){
        ql_gpio_set_level(QL_GPIO_PD4,QL_GPIO_OUTPUT_LOW);
    }else{
        ql_gpio_set_level(QL_GPIO_PD4,QL_GPIO_OUTPUT_HIGH);
    }
    cnt++;
    ql_debug(" int cnt=%d\\r\\n",cnt);
    if(cnt >= 10){
        ql_gpio_int_disable(QL_GPIO_PD6);
        cnt = 0;
    }
}

Function Debugging

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

  1. Recompile the firmware version and flash it to the module.
  2. Reboot the module.
  3. Open UART port 1 to obtain the debugging logs. The log information will be displayed as follows:

Log Obtained via a Serial Port Tool

If the following information is printed during the debugging, it indicates that the GPIO interrupt has been triggered.

GPIO Test Log


PMU GPIO API

Header File

ql_pmu_gpio.h, the header file of PMU GPIO API, is in the components/quectel_api/ql_include directory. Unless otherwise specified, all header files mentioned in this document are in this directory.

The functional difference between GPIO and PMU GPIO pins is that the PMU GPIO pins can keep the output level unchanged when the module is in sleep state.

API Overview

Function Description
ql_pmu_gpio_init() Initializes a PMU GPIO pin.
ql_pmu_gpio_set_level() Sets the level of the specified PMU GPIO pin.
ql_pmu_gpio_get_level() Gets the level of the specified PMU GPIO pin.
ql_pmu_gpio_int_init() Initializes and enables the PMU GPIO interrupt.
ql_pmu_gpio_int_disable() Disables the configured PMU GPIO interrupt.

API Description

ql_pmu_gpio_init

This function initializes a PMU GPIO pin.

Prototype:

ql_gpio_errcode_e ql_pmu_gpio_init(ql_gpio_num_e pin, ql_gpio_mode_e mode)

Parameters:

Return Value:

Function execution result code. See ql_gpio_errcode_e.


ql_pmu_gpio_set_level

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

Prototype:

ql_gpio_errcode_e ql_pmu_gpio_set_level(ql_gpio_num_e pin, ql_gpio_output_level_e output_level)

Parameters:

Return Value:

Function execution result code. See ql_gpio_errcode_e.


ql_pmu_gpio_get_level

This function gets the level of the specified PMU GPIO pin.

Prototype:

ql_gpio_errcode_e ql_pmu_gpio_get_level(ql_gpio_num_e pin, uint32_t *input_level)

Parameters:

  • pin: [In] PMU GPIO pin number. See ql_gpio_num_e.
  • input_level: [Out] PMU GPIO pin level.

Return Value:

Function execution result code. See ql_gpio_errcode_e.


ql_pmu_gpio_int_init

This function initializes and enables the PMU GPIO interrupt.

Prototype:

ql_gpio_errcode_e ql_pmu_gpio_int_init(ql_gpio_num_e pin, ql_gpio_irq_trigger_e trigger, ql_pmu_gpio_irq_callback callback)

Parameters:

Return Value:

Function execution result code. See ql_gpio_errcode_e.


ql_pmu_gpio_irq_callback

This is the callback function of PMU GPIO interrupt.

Prototype:

typedef void (*ql_pmu_gpio_irq_callback)(void *arg)

Parameters:

  • arg: [Out] Reserved.

ql_pmu_gpio_int_disable

This function disables the configured PMU GPIO interrupt.

Prototype:

ql_gpio_errcode_e ql_pmu_gpio_int_disable(ql_gpio_num_e pin)

Parameters:

Return Value:

Function execution result code. See ql_gpio_errcode_e.


PMU GPIO Development Process

This chapter describes how to use the above PMU GPIO API to configure PMU GPIO pins and perform basic debugging. QL_GPIO_PD4, QL_GPIO_PD5 and QL_GPIO_PD6 are used in the following examples by default.

PMU GPIO Operation

The example of how to use the PMU GPIO API is provided in the quectel_demo/ql_pmu_gpio_demo/code/ql_pmu_gpio_demo.c file in the module SDK. The related functions are described as follows:

  • demo_pmu_gpio(): Initializes PMU GPIO and enables the PMU GPIO interrupt
  • ql_gpio_pmu_irq_test(): This is the interrupt callback function. It can implement the functionalities such as getting the pin level of PMU GPIO, setting the level of PMU GPIO pin and disabling the PMU GPIO interrupt.

The example of using the PMU GPIO API is as follows:

void demo_pmu_gpio(void)
{
    ql_debug("pmu gpio demo\\r\\n");
    ql_pmu_gpio_init(QL_GPIO_PD4,QL_GMODE_OUTPUT);
    ql_pmu_gpio_init(QL_GPIO_PD5,QL_GMODE_INPUT_PULLDOWN);
    ql_pmu_gpio_set_level(QL_GPIO_PD4,QL_GPIO_OUTPUT_HIGH);
    ql_pmu_gpio_int_init(QL_GPIO_PD6, QL_IRQ_TRIGGER_FALLING_EDGE, ql_gpio_pmu_irq_test);//wakeup pin
}

void ql_gpio_pmu_irq_test (void *arg)
{
    static int cnt = 0;
    uint32_t input_level = 0;
    ql_pmu_gpio_get_level(QL_GPIO_PD5,&input_level);
    ql_debug(" gpio5 read=%d\\r\\n",input_level);
    if(input_level == 0){
        ql_pmu_gpio_set_level(QL_GPIO_PD4,QL_GPIO_OUTPUT_LOW);
    }else{
        ql_pmu_gpio_set_level(QL_GPIO_PD4,QL_GPIO_OUTPUT_HIGH);
    }
    cnt++;
    ql_debug(" int cnt=%d\\r\\n",cnt);
    if(cnt >= 10){
        ql_pmu_gpio_int_disable(QL_GPIO_PD6);
        cnt = 0;
    }
}

Function Debugging

To debug the PMU GPIO function, use the development board (HCM111Z TE-B) with the module and follow these steps:

  1. Recompile the firmware version and flash it to the module.
  2. Reboot the module.
  3. Open UART port 1 to obtain the debugging logs. The log information will be displayed as follows:

Capturing Logs via Serial Port Tool

If the following information is printed during the debugging, it indicates that the PMU GPIO interrupt has been triggered.

PMU GPIO Test Log


UART API

Header File

ql_uart.h, the header file of UART API, is in the components/quectel_api/ql_include directory. Unless otherwise specified, all header files mentioned in this document are in this directory.

API Overview

Function Description
ql_uart_set_dcbconfig() Sets the UART port properties.
ql_uart_get_dcbconfig() Gets the configuration of UART port properties.
ql_uart_open() Opens the UART port.
ql_uart_close() Closes the UART port.
ql_uart_write() Writes data to the module through the UART port.
ql_uart_read() Reads the data from the module through the UART port.
ql_uart_set_rx_cb() Registers the callback function for UART data interrupt.

API Description

ql_uart_set_dcbconfig

This function sets the UART port properties, which take effect after the UART port is re-opened.

Prototype:

ql_uart_errcode_e ql_uart_set_dcbconfig(ql_uart_port_number_e port, ql_uart_config_s *dcb)

Parameters:

Return Value:

Function execution result code. See ql_uart_errcode_e.


ql_uart_port_number_e

The enumeration of the UART port number is defined below. The module currently supports two UART ports.

typedef enum {
  QL_UART_PORT_1,
  QL_UART_PORT_2,
} ql_uart_port_number_e

Member:

Member Description
QL_UART_PORT_1 UART port 1
QL_UART_PORT_2 UART port 2

ql_uart_config_s

The structure of the configuration of UART port properties:

typedef struct {
  uint8_t is_debug_port;
  ql_uart_baud_e baudrate;
  ql_uart_databit_e data_bit;
  ql_uart_stopbit_e stop_bit;
  ql_uart_parityit_e parity_bit;
} ql_uart_config_s

Parameter:

Type Parameter Description
uint8_t is_debug_port Print log (0: Receive and send data)
ql_uart_baud_e baudrate Baud rate. Default: 115200 bps.See ql_uart_baud_e
ql_uart_databit_e data_bit Data bit. Default: 8 bits.See ql_uart_databit_e
ql_uart_stopbit_e stop_bit Stop bit. Default: 1 bit.See ql_uart_stopbit_e
ql_uart_parityit_e parity_bit Parity bit. Default: No parity bit.See ql_uart_parityit_e

ql_uart_baud_e

The enumeration of baud rates:

typedef enum {
  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_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_e

Member:

Member Description
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_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_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

Member:

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,
  QL_UART_STOP_2,
} ql_uart_stopbit_e

Member:

Member Description
QL_UART_STOP_1 1 bit
QL_UART_STOP_2 2 bits

ql_uart_parityit_e

The enumeration of parity bits:

typedef enum {
  QL_UART_PARITY_NONE,
  QL_UART_PARITY_ODD,
  QL_UART_PARITY_EVEN,
} ql_uart_parityit_e

Member:

Member Description
QL_UART_PARITY_NONE No parity
QL_UART_PARITY_ODD Odd parity
QL_UART_PARITY_EVEN Even parity

ql_uart_errcode_e

The enumeration of UART 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

Member:

Member Description
QL_UART_SUCCESS Successful execution
QL_UART_EXECUTE_ERR Failed execution
QL_UART_MEM_ADDR_NULL_ERR Parameter address is 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)

Parameters:

Return Value:

Function execution result code. See ql_uart_errcode_e.


ql_uart_open

This function opens the UART port.

Prototype:

ql_uart_errcode_e ql_uart_open(ql_uart_port_number_e port)

Parameters:

Return Value:

Function execution result code. See ql_uart_errcode_e.


ql_uart_close

This function closes the UART port.

Prototype:

ql_uart_errcode_e ql_uart_close(ql_uart_port_number_e port)

Parameters:

Return Value:

Function execution result code. See ql_uart_errcode_e.


ql_uart_write

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

Prototype:

int ql_uart_write(ql_uart_port_number_e port, unsigned char *data, unsigned int data_len)

Parameters:

  • port: [In] UART port number. See ql_uart_port_number_e.
  • data: [In] Written data.
  • data_len: [In] Length of written data.

Return Value:

Function execution result code. See ql_uart_errcode_e.


ql_uart_read

This function reads the data from the module through the UART port.

Prototype:

int ql_uart_read(ql_uart_port_number_e port, unsigned char *data, unsigned int data_len)

Parameters:

  • port: [In] UART port number. See ql_uart_port_number_e.
  • data: [Out] Read data.
  • data_len: [In] Length of read data.

Return Value:

Function execution result code. See ql_uart_errcode_e.


ql_uart_set_rx_cb

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

Prototype:

ql_uart_errcode_e ql_uart_set_rx_cb(ql_uart_port_number_e port, ql_uart_callback uart_cb)

Parameters:

Return Value:

Function execution result code. See ql_uart_errcode_e.


ql_uart_callback

This is the callback function that handles the UART interrupt.

Prototype:

typedef void (*ql_uart_callback)(char value)

Parameters:

  • value: [In] Data received via the UART port.

Return Value:

None


UART Development Process

This chapter describes how to use the above UART API in the application and perform basic debugging. UART 0 is used in the following example by default.

UART Operation

The example of how to use the UART API is provided in the quectel_demo/ql_uart_demo/code/ql_uart_demo.c file in the module SDK. The related functions are described as follows:

  • demo_uart(): Initializes the UART port and registers the interrupt callback function.
  • ql_uart_cb_test(): Interrupt callback function that handles the data received through the UART port.

The example of using the UART API is as follows:

void demo_uart(void)
{
    ql_uart_config_s cfg = {
        .is_debug_port = 0, //0 | 1
        .baudrate = QL_UART_BAUD_115200,
        .data_bit = QL_UART_DATABIT_8,
        .stop_bit = QL_UART_STOP_1,
        .parity_bit = QL_UART_PARITY_NONE,
    };
    ql_debug("uart demo\\r\\n");
    ql_gpio_set_port_mux(QL_GPIO_PD4,QL_PORTD4_FUNC_UART0_RXD);
    ql_gpio_set_port_mux(QL_GPIO_PD5,QL_PORTD5_FUNC_UART0_TXD);
    ql_gpio_set_port_pull(QL_GPIO_PD4, true);
    ql_uart_set_dcbconfig(QL_UART_PORT_0,&cfg);
    ql_uart_set_rx_cb(QL_UART_PORT_0,ql_uart_cb_test);
    ql_uart_open(QL_UART_PORT_0);
}

void ql_uart_cb_test(char value)
{
    char data = value;
    ql_debug("recv %0x\\r\\n",data);
    ql_uart_write(QL_UART_PORT_0,(unsigned char*)&data,1);
}

Function Debugging

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

  1. Recompile the firmware version and flash it to the module.
  2. Reboot the module.
  3. Open UART port 1 to obtain the debugging logs. The log information will be displayed as follows:

Capturing Logs via Serial Port Tool


ADC API

Header File

ql_adc.h, the header file of ADC API, is in the components/quectel_api/ql_include directory. Unless otherwise specified, all header files mentioned in this document are in this directory.

API Overview

Function Description
ql_adc_channel_init() Configures ADC channel parameters.
ql_adc_channel_start() Enables ADC channel detection.
ql_adc_channel_stop() Disables ADC channel detection.

API Description

ql_adc_channel_init

This function configures ADC channel parameters.

Prototype:

ql_adc_errcode_e ql_adc_channel_init(ql_adc_obj_s *handle, ql_adc_obj_callback cb, ql_adc_channel_e channel, void *user_data)

Parameters:

Return Value:

Function execution result code. See ql_adc_errcode_e.


ql_adc_obj_s

The structure of ADC channels:

typedef struct adc_obj_ {
  void *user_data;
  ql_adc_channel_e channel;
  ql_adc_obj_callback cb;
  struct adc_obj_ *next;
} ql_adc_obj_s

Parameter:

Type Parameter Description
void user_data User data.
ql_adc_channel_e channel ADC channel number.
ql_adc_obj_callback cb Callback function for channel detection.
struct adc_obj_ next Address of the next node in the Linked List.

ql_adc_obj_callback

This function is the callback function for ADC channel detection.

Prototype:

typedef void (*ql_adc_obj_callback)(ql_adc_channel_e channel, int value, void *user_data)

Parameters:

  • channel: [Out] ADC channel number. See ql_adc_channel_e.
  • value: [In] ADC channel voltage sampling result. Range: 0--1023. Reference voltage: 3.3 V. When the sampling result is 1023, it means that the channel voltage is greater than or equal to 3.3 V.
  • user_data: [In] User data.

Return Value:

None


ql_adc_channel_e

The enumeration of ADC channel number.

typedef enum {
  QL_ADC_CHANNEL_0 = 0x01,
  QL_ADC_CHANNEL_1 = 0x02,
  QL_ADC_CHANNEL_2 = 0x04,
  QL_ADC_CHANNEL_3 = 0x08,
} ql_adc_channel_e

Parameter:

Parameter Description
QL_ADC_CHANNEL_0 Channel 0, detecting voltage for QL_GPIO_PD4.
QL_ADC_CHANNEL_1 Channel 1, detecting voltage for QL_GPIO_PD5.
QL_ADC_CHANNEL_2 Channel 2, detecting voltage for QL_GPIO_PD6.
QL_ADC_CHANNEL_3 Channel 3, detecting voltage for QL_GPIO_PD7.

ql_adc_errcode_e

The enumeration of ADC result codes:

typedef enum {
  QL_ADC_SUCCESS = 0,
  QL_ADC_EXECUTE_ERR,
  QL_ADC_INVALID_PARAM_ERR,
} ql_adc_errcode_e

Parameter:

Parameter Description
QL_ADC_SUCCESS Successful execution
QL_ADC_EXECUTE_ERR Failed execution
QL_ADC_INVALID_PARAM_ERR Invalid parameter

ql_adc_channel_start

This function enables ADC channel detection.

Prototype:

ql_adc_errcode_e ql_adc_channel_start(ql_adc_obj_s *handle)

Parameters:

Return Value:

Function execution result code. See ql_adc_errcode_e.


ql_adc_channel_stop

This function disables ADC channel detection.

Prototype:

ql_adc_errcode_e ql_adc_channel_stop(ql_adc_obj_s *handle)

Parameters:

Return Value:

Function execution result code. See ql_adc_errcode_e.


ADC Development Process

This chapter describes how to use the above ADC API in the application, and perform basic debugging. In the example, channel 0 is used for test by default.

ADC Operation

The example of how to use the ADC API is provided in the quectel_demo/ql_adc_demo/code/ql_adc_demo.c file the module SDK. The related functions are described as follows:

  • demo_adc(): Configure and initialize ADC channels.
  • adc_tim_fn(): The timer callback function, which implements ADC channel detection every 1 s.

The example of using ADC API is as follows:

void demo_adc(void)
{
    ql_debug("adc demo\\r\\n");
    ql_gpio_set_port_mux(QL_GPIO_PD4,QL_PORTD4_FUNC_ADC0);
    ql_soft_timer_init(&adc_timer , adc_tim_fn , NULL);
    ql_soft_timer_start(&adc_timer,1000,1);
}
void adc_tim_fn(void *arg)
{
    ql_adc_channel_init(&ql_test_adc , ql_adc_detect_callback , QL_ADC_CHANNEL_0 , NULL);
    ql_adc_channel_start(&ql_test_adc);
    ql_adc_channel_stop(&ql_test_adc);
}

You can print the result of ADC channel detection through ql_adc_detect_callback() as follows:

static void ql_adc_detect_callback(ql_adc_channel_e channel, int value , void *user_data)
{
    ql_debug("adc channel %d , value %d \\r\\n" , channel , value);
}

Function Debugging

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

  1. Recompile the firmware version and flash it to the module.
  2. Reboot the module.
  3. Open UART port 1 to obtain 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 Serial Port Tool


PWM API

Header File

ql_pwm.h, the header file of PWM API, is in the components/quectel_api/ql_include directory. Unless otherwise specified, all header files mentioned in this document are in this directory.

API Overview

Function Description
ql_pwm_init() Initializes PWM.
ql_pwm_update_param() Updates the PWM parameters.
ql_pwm_enable() Enables PWM output.
ql_pwm_disable() Disables PWM output.

API Description

ql_pwm_init

This function initializes PWM.

Prototype:

ql_pwm_errcode_e ql_pwm_init(ql_pwm_channel_e channel, uint32_t frequency, uint32_t high_duty)

Parameters:

  • channel: [In] PWM channel. See ql_pwm_channel_e.
  • frequency: [In] PWM frequency.
  • high_duty: [In] PWM duty cycle.

Return Value:

Function execution result code. See ql_pwm_errcode_e.


ql_pwm_channel_e

The enumeration of PWM channels. There are 6 PWM channels in total.

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 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_update_param

This function updates the PWM parameters. The updated parameters take effect in next PWM period.

Prototype:

ql_pwm_errcode_e ql_pwm_update_param(ql_pwm_channel_e channel, uint32_t frequency, uint32_t high_duty)

Parameters:

  • channel: [In] PWM channel. See ql_pwm_channel_e.
  • frequency: [In] PWM frequency.
  • high_duty: [In] PWM duty cycle.

Return Value:

Function execution result code. See ql_pwm_errcode_e.


ql_pwm_enable

This function enables PWM output.

Prototype:

ql_pwm_errcode_e ql_pwm_enable(ql_pwm_channel_e channel)

Parameters:

Return Value:

Function execution result code. See ql_pwm_errcode_e.


ql_pwm_disable

This function disables PWM output.

Prototype:

ql_pwm_errcode_e ql_pwm_disable(ql_pwm_channel_e channel)

Parameters:

Return Value:

Function execution result code. See ql_pwm_errcode_e.


PWM Development Process

This chapter describes how to use the above PWM API in the application, and perform simple debugging. In the example, QL_PWM_4 and QL_PWM_5 are used for test by default.

PWM Operation

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

  • demo_pwm(): Initializes PWM, enables PWM output and disables PWM output.

The example of using PWM API is as follows:

void demo_pwm(void)
{
    ql_debug("digital_pwm demo\\r\\n");
    ql_gpio_set_port_mux(QL_GPIO_PD4,QL_PORTD4_FUNC_PWM4);
    ql_gpio_set_port_mux(QL_GPIO_PD5,QL_PORTD5_FUNC_PWM5);
    ql_pwm_init(QL_PWM_4,1000,50);
    ql_pwm_init(QL_PWM_5,1000,80);
    ql_pwm_enable(QL_PWM_4);
    ql_pwm_enable(QL_PWM_5);
    ql_sys_delay_100us(20000); //1 kHz for 2 s
    ql_pwm_update_param(QL_PWM_4,10000,80);
    ql_pwm_update_param(QL_PWM_5,10000,50);
    ql_sys_delay_100us(10000); //10K Hz for 1 s
    ql_pwm_disable(QL_PWM_4);
    ql_pwm_disable(QL_PWM_5);
    ql_sys_delay_100us(20000); //Stop for 2 s
    ql_pwm_enable(QL_PWM_4);
    ql_pwm_enable(QL_PWM_5);
    ql_sys_delay_100us(10000); //Restart PWM with 10 kHz for 1 s
    ql_pwm_disable(QL_PWM_4);
    ql_pwm_disable(QL_PWM_5);
}

Function Debugging

To debug the PWM function use the development board (HCM111Z TE-B) with the module and follow these steps:

  1. Recompile the firmware version and flash it to the module.
  2. Reboot the module.
  3. Open UART port 1 to obtain the debugging logs. The log information will be displayed as follows:

Capturing Logs via Serial Port Tool

Capturing PWM Waveforms with Logic Analyzer


SPI API

Header File

ql_spi.h, the header file of SPI API, is in the components/quectel_api/ql_include directory. Unless otherwise specified, all header files mentioned in this document are in this directory.

API Overview

Function Description
ql_spi_init() Initializes SPI.
ql_spi_transfer() Sends or receives SPI data.

API Description

ql_spi_init

This function initializes SPI.

Prototype:

ql_spi_errcode_e ql_spi_init(ql_spi_config_s spi_cfg)

Parameters:

Return Value:

Function execution result code. See ql_spi_errcode_e.


ql_spi_config_s

The structure of SPI configuration:

typedef struct {
  uint32_t spiclk;
  ql_spi_cpol_pol_e cpol;
  ql_spi_cpha_pol_e cpha;
  ql_spi_master_slave_mode_e masterorslave;
  void (*spi_cs_ctrl)(uint8_t);
} ql_spi_config_s

Parameter:

Type Parameter Description
uint32_t spiclk SPI clock frequency. Maximum value: 24 MHz.
ql_spi_cpol_pol_e cpol SPI clock polarity.See ql_spi_cpol_pol_e.
ql_spi_cpha_pol_e cpha SPI clock phase.See ql_spi_cpha_pol_e.
ql_spi_master_slave_mode_e masterorslave SPI master or slave selection.See ql_spi_master_slave_mode_e.
void (*spi_cs_ctrl)(uint8_t) spi_cs_ctrl Function pointer for controlling CS pin.See ql_spi_cs_ctrl() in SPI Operation.

ql_spi_cpol_pol_e

The enumeration of SPI clock polarities:

typedef enum {
  QL_SPI_CPOL_LOW = 0,
  QL_SPI_CPOL_HIGH,
} ql_spi_cpol_pol_e

Member:

Member Description
QL_SPI_CPOL_LOW SCK is at a low level during the idle state.
QL_SPI_CPOL_HIGH SCK is at a high level during the idle state.

ql_spi_cpha_pol_e

The enumeration of SPI clock phases:

typedef enum {
  QL_SPI_CPHA_1Edge,
  QL_SPI_CPHA_2Edge,
} ql_spi_cpha_pol_e

Member:

Member Description
QL_SPI_CPHA_1Edge Sample data on the edge of the first period of SCK.
QL_SPI_CPHA_2Edge Sample data on the edge of the second period of SCK.

ql_spi_master_slave_mode_e

The enumeration of SPI master or slave selections:

typedef enum {
  QL_SPI_MASTER = 0,
  QL_SPI_SLAVE,
} ql_spi_master_slave_mode_e

Member:

Member Description
QL_SPI_MASTER SPI serves as the master.
QL_SPI_SLAVE SPI serves as the slave (Currently not supported).

ql_spi_errcode_e

The enumeration of SPI result codes:

typedef enum {
  QL_SPI_SUCCESS = 0,
  QL_SPI_EXECUTE_ERR,
  QL_SPI_INVALID_PARAM_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_transfer

This function sends or receives SPI data.

Prototype:

ql_errcode_spi_e ql_spi_transfer(ql_spi_messag_s *spi_msg)

Parameters:

Return Value:

Function execution result code. See ql_spi_errcode_e.


ql_spi_messag_s

The structure of data sent or received via SPI:

typedef struct {
  UINT8 *send_buf;
  UINT32 send_len;
  UINT8 *recv_buf;
  UINT32 recv_len;
} ql_spi_message_s

Parameter:

Type Parameter Description
UINT8 send_buf Sent data
UINT32 send_len Length of the sent data
UINT8 recv_buf Received data
UINT32 recv_len Length of the received data

SPI Development Process

This chapter describes how to use the above SPI API in the application, and perform basic debugging.

SPI Operation

The example of how to use the SPI API is provided in the quectel_demo/ql_spi_demo/code/ql_spi_demo.c file in the module SDK. The related functions are described as follows:

  • demo_spi_master(): Initializes SPI, sends and receives data.
  • ql_spi_cs_ctrl(): Controls CS pin.

The example of using SPI API is as follows:

void demo_spi_master(void)
{
    ql_debug("spi master demo\\r\\n");
    uint8_t send_buff[128] = {0};
    uint8_t recv_buff[128] = {0};
    int i = 0;
    for(i=0;i<128;i++)
        send_buff[i] = i;
    ql_spi_config_s cfg = {
        .spiclk = 3000000,
        .cpol = QL_SPI_CPOL_LOW,
        .cpha = QL_SPI_CHPA_1EDGE,
        .masterorslave = QL_SPI_MASTER,
        .spi_cs_ctrl = ql_spi_cs_ctrl,
    };
    ql_spi_message_s msg = {
        .send_buf = send_buff,
        .send_len = 128,
        .recv_buf = recv_buff,
        .recv_len = 128,
    };
    ql_gpio_set_port_mux(QL_GPIO_PD4, QL_PORTD4_FUNC_SSP0_CLK);
    //ql_gpio_set_port_mux(QL_GPIO_PD5, QL_PORTD5_FUNC_SSP0_CSN);
    ql_gpio_set_port_mux(QL_GPIO_PD5, QL_PORTD5_FUNC_D5);
    ql_gpio_init(QL_GPIO_PD5,QL_GMODE_OUTPUT);
    ql_gpio_set_port_mux(QL_GPIO_PD6, QL_PORTD6_FUNC_SSP0_DOUT);
    ql_gpio_set_port_mux(QL_GPIO_PD7, QL_PORTD7_FUNC_SSP0_DIN);
    ql_spi_init(cfg);
    ql_spi_transfer(&msg);
    ql_debug("spi master demo over\\r\\n");
}

void ql_spi_cs_ctrl(uint8_t enable)
{
    ql_gpio_set_level(QL_GPIO_PD5,enable);
}

Function Debugging

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

  1. Recompile the firmware version and flash it to the module.
  2. Reboot the module.
  3. Open UART port 1 to obtain the debugging logs. The log information will be displayed as follows:

Capturing Logs via Serial Port Tool

Capturing SPI Waveforms Through Logic Analyzer


I2C API

Header File

ql_i2c.h, the header file of I2C API, is in the components/quectel_api/ql_include directory. Unless otherwise specified, all I2C header files mentioned in this document are in this directory.

API Overview

Function Description
ql_i2c_init() Initializes the I2C bus.
ql_i2c_write() Writes data to the I2C bus.
ql_i2c_read() Reads data from the I2C bus.
ql_i2c_master_init() Initializes the I2C master.
ql_i2c_master_transmit() Transmits data from I2C master to the slave.
ql_i2c_master_receive() Reads the data transmitted from I2C slave by I2C master.
ql_i2c_slave_init() Initializes the I2C slave.
ql_i2c_slave_transmit() Transmits data from I2C slave to I2C master.
ql_i2c_slave_receive() Reads the data transmitted from I2C master by I2C slave.

API Description

ql_i2c_init

This function initializes the I2C bus.

Prototype:

ql_errcode_i2c_e ql_i2c_init(QL_DD_HANDLE *i2c_hdl, ql_i2c_mode mode, ql_i2c_channel_e channel)

Parameters:

Return Value:

Function execution result code. See ql_errcode_i2c_e.


ql_i2c_mode_e

The enumeration of I2C bus operating modes:

typedef enum {
  STANDARD_MODE = 0,
  FAST_MODE = 1,
} ql_i2c_mode_e

Member:

Member Description
QL_STANDARD_MODE Standard mode
FAST_MODE Fast mode

ql_i2c_channel_e

The enumeration of I2C channels:

typedef enum {
  QL_I2C_CHANNEL_0 = 0,
  QL_I2C_CHANNEL_1,
} ql_i2c_channel_e

Member:

Member Description
QL_I2C_CHANNEL_0 I2C channel 0
QL_I2C_CHANNEL_1 I2C channel 1

ql_errcode_i2c_e

The enumeration of the I2C result codes:

typedef enum {
  QL_I2C_SUCCESS = 0,
  QL_I2C_INIT_ERR,
  QL_I2C_WRITE_ERR,
  QL_I2C_READ_ERR,
} ql_errcode_i2c_e

Member:

Member Description
QL_I2C_SUCCESS Successful execution
QL_I2C_INIT_ERR Failed I2C initialization
QL_I2C_WRITE_ERR Failed to write data to I2C
QL_I2C_READ_ERR Failed to read data from I2C

ql_i2c_write

This function writes data to the I2C bus.

Prototype:

ql_errcode_i2c_e ql_i2c_write(QL_DD_HANDLE *i2c_hdl, uint8_t slave_addr, uint8_t reg_addr, char *data, uint32_t len)

Parameters:

  • i2c_hdl: [In] I2C handle.
  • slave_addr: [In] I2C slave device address.
  • reg_addr: [In] I2C slave register address.
  • data: [In] Data to be written to the I2C bus.
  • len: [In] Data length to be written to the I2C bus.

Return Value:

Function execution result code. See ql_errcode_i2c_e.


ql_i2c_read

This function reads data from the I2C bus.

Prototype:

ql_errcode_i2c_e ql_i2c_read(QL_DD_HANDLE *i2c_hdl, uint8_t slave_addr, uint8_t reg_addr, char *data, uint32_t len)

Parameters:

  • i2c_hdl: [In] I2C handle.
  • slave_addr: [In] I2C slave device address.
  • reg_addr: [In] I2C slave register address.
  • data: [Out] Data read from the I2C bus.
  • len: [In] Data length read from the I2C bus.

Return Value:

Function execution result code. See ql_errcode_i2c_e.


ql_i2c_master_init

This function initializes the I2C master.

Prototype:

ql_errcode_i2c_e ql_i2c_master_init(ql_i2c_channel_e i2c_channel, ql_i2c_mode i2c_mode, ql_i2c_pin_mux_e pin_mux)

Parameters:

  • i2c_channel: [In] I2C channel. Only QL_I2C_CHANNEL_1 is supported.
  • i2c_mode: [In] Working mode of I2C.
  • pin_mux: [In] Multiplexed GPIO combination of I2C's SCL and SDA. See ql_i2c_pin_mux_e.

Return Value:

Function execution result code. See ql_errcode_i2c_e.


ql_i2c_pin_mux_e

The enumeration of multiplexed GPIO combination of I2C's SCL and SDA:

typedef enum {
  // I2C1_CLK I2C1_DAT
  QL_PIN_MUX_0, // PORTA2 PORTA3
  QL_PIN_MUX_1, // PORTA6 PORTA7
  QL_PIN_MUX_2, // PORTB2 PORTB3
  QL_PIN_MUX_3, // PORTB6 PORTB7
  QL_PIN_MUX_4, // PORTC2 PORTC3
  QL_PIN_MUX_5, // PORTC6 PORTC7
  QL_PIN_MUX_6, // PORTD2 PORTD3
  QL_PIN_MUX_7  // PORTD6 PORTD7
} ql_i2c_pin_mux_e;

Member:

Member Description
QL_PIN_MUX_0 PA2 is used as SCL and PA3 is used as SDA.
QL_PIN_MUX_1 PA6 is used as SCL and PA7 is used as SDA.
QL_PIN_MUX_2 PB2 is used as SCL and PB3 is used as SDA.
QL_PIN_MUX_3 PB6 is used as SCL and PB7 is used as SDA.
QL_PIN_MUX_4 PC2 is used as SCL and PC3 is used as SDA.
QL_PIN_MUX_5 PC6 is used as SCL and PC7 is used as SDA.
QL_PIN_MUX_6 PD2 is used as SCL and PD3 is used as SDA.
QL_PIN_MUX_7 PD6 is used as SCL and PD7 is used as SDA.

ql_i2c_master_transmit

This function transmits data from I2C master to the slave.

Prototype:

ql_errcode_i2c_e ql_i2c_master_transmit(ql_i2c_channel_e i2c_channel, uint8_t slave_addr, uint8_t *data, uint16_t data_len)

Parameters:

  • i2c_channel: [In] I2C channel. Only QL_I2C_CHANNEL_1 is supported.
  • slave_addr: [In] I2C slave device address with no offset.
  • data: [In] The transmitted data.
  • data_len: [In] Length of the transmitted data.

Return Value:

Function execution result code. See ql_errcode_i2c_e.


ql_i2c_master_receive

This function reads the data transmitted from I2C slave by I2C master.

Prototype:

ql_errcode_i2c_e ql_i2c_master_receive(ql_i2c_channel_e i2c_channel, uint8_t slave_addr, uint8_t *data, uint16_t *data_len)

Parameters:

  • i2c_channel: [In] I2C channel. Only QL_I2C_CHANNEL_1 is supported.
  • slave_addr: [In] I2C slave device address with no offset.
  • data: [Out] The read data.
  • data_len: [Out] Length of the read data.

Return Value:

Function execution result code. See ql_errcode_i2c_e.


ql_i2c_slave_init

This function initializes the I2C slave.

Prototype:

ql_errcode_i2c_e ql_i2c_slave_init(ql_i2c_channel_e i2c_channel, ql_i2c_mode i2c_mode, ql_i2c_pin_mux_e pin_mux, uint16_t slave_addr)

Parameters:

  • i2c_channel: [In] I2C channel. Only QL_I2C_CHANNEL_1 is supported.
  • i2c_mode: [In] Working mode of I2C.
  • pin_mux: [In] Multiplexed GPIO combination of I2C's SCL and SDA. See ql_i2c_pin_mux_e.
  • slave_addr: [In] Initialization address of the slave.

Return Value:

Function execution result code. See ql_errcode_i2c_e.


ql_i2c_slave_transmit

This function transmits data from I2C slave to I2C master.

Prototype:

ql_errcode_i2c_e ql_i2c_slave_transmit(ql_i2c_channel_e i2c_channel, uint8_t *data, uint16_t data_len)

Parameters:

  • i2c_channel: [In] I2C channel. Only QL_I2C_CHANNEL_1 is supported.
  • data: [In] The transmitted data.
  • data_len: [In] Length of the transmitted data.

Return Value:

Function execution result code. See ql_errcode_i2c_e.


ql_i2c_slave_receive

This function reads the data transmitted from I2C master by I2C slave.

Prototype:

ql_errcode_i2c_e ql_i2c_slave_receive(ql_i2c_channel_e i2c_channel, uint8_t *data, uint16_t *data_len)

Parameters:

  • i2c_channel: [In] I2C channel. Only QL_I2C_CHANNEL_1 is supported.
  • data: [Out] The read data.
  • data_len: [Out] Length of the read data.

Return Value:

Function execution result code. See ql_errcode_i2c_e.


I2C Development Process

This chapter describes how to use the above I2C API in the application, and perform basic debugging. QL_I2C_CHANNEL_1 is used for test by default.

I2C Operation

The example of how to use the I2C API is provided in the quectel_demo/ql_i2c_demo/code/ql_i2c_demo.c file in the module SDK. In this example, the module operates as the I2C master device for communicating with the chip. The related functions are described as follows:

  • demo_i2c(): Initializes I2C channel 1.

The example of using I2C API is as follows:

void demo_i2c(void)
{
    uint8_t i2c_test_no = 0;
    char data = 0;
    uint8_t buff1[6];
    uint8_t buff2[6];
    ql_debug("IIC demo\\r\\n");
    ql_gpio_set_port_mux(QL_GPIO_PD6, QL_PORTD6_FUNC_I2C1_CLK);//PD6
    ql_gpio_set_port_mux(QL_GPIO_PD7, QL_PORTD7_FUNC_I2C1_DAT);//PD7
    ql_gpio_set_port_pull(QL_GPIO_PD6,1);
    ql_gpio_set_port_pull(QL_GPIO_PD7,1);
    //IIC1, 1 MHz. slave addr: 0xd6
    ql_i2c_init(&i2c_hdl ,QL_STANDARD_MODE,QL_I2C_CHANNEL_1);
    // iic_init(IIC_CHANNEL_1,1000,LSM6DS33_ADDR);
    data = 0;
    ql_i2c_write(&i2c_hdl ,LSM6DS33_ADDR ,0x15,&data,1);
    ql_i2c_write(&i2c_hdl ,LSM6DS33_ADDR ,0x16,&data,1);
    data = 0x80;
    ql_i2c_write(&i2c_hdl ,LSM6DS33_ADDR ,0x10,&data,1);
    ql_i2c_write(&i2c_hdl ,LSM6DS33_ADDR ,0x11,&data,1);
    data = 0x04;
    ql_i2c_write(&i2c_hdl ,LSM6DS33_ADDR ,0x12,&data,1);
    while(1)
    {
        for(uint8_t i=0; i<6; i++)
        {
            ql_i2c_read(&i2c_hdl ,LSM6DS33_ADDR ,0x28+i,(char*)&buff1[i],1);
            ql_i2c_read(&i2c_hdl ,LSM6DS33_ADDR ,0x22+i,(char*)&buff2[i],1);
        }
        ql_debug("X:%d |Y:%d |Z:%d\\r\\n",*(uint16_t *)buff1,*(uint16_t *)(buff1+2),*(uint16_t *)(buff1+4));
        ql_debug("AccX:%d|Acc_Y:%d|Acc_Z:%d\\r\\n",*(uint16_t *)buff2,*(uint16_t *)(buff2+2),*(uint16_t *)(buff2+4));
        i2c_test_no++;
        if(i2c_test_no>3)
            break;
    }
}

Function Debugging

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

  1. Recompile the firmware version and flash it to the module.
  2. Reboot the module.
  3. Capture the I2C waveforms with a logic analyzer as shown below:

Capturing I2C Waveforms of PWM with Logic Analyzer

I2C Master and Slave Mode Debugging

The SDK code of the module provides examples of operating the I2C master and slave modes, which are located in the files ql_i2c_master.c and ql_i2c_slave.c in the directory quectel_demo/ql_i2c_demo/code. In this example, one module communicates via I2C as the master and the other as the slave. The following explains the related functions:

I2C Slave Operation
  • ql_i2c_demo_slave_init()*`: Initializes I2C slave channel 1, with PA6 serving as SCL, PA7 as SDA, and PA0 indicating that data is ready.

The I2C slave initialization example is as follows:

void ql_i2c_demo_slave_init(void)
{
    ql_debug("I2C SLAVE DEMO RUNNING\\r\\n");

    /* Configure I/O port to check whether data is ready on the slave */
    ql_gpio_set_port_mux(QL_GPIO_PA0, QL_PORTA0_FUNC_A0);
    ql_gpio_set_dir(QL_GPIO_PA0, QL_GMODE_OUTPUT);	
    ql_gpio_set_level(QL_GPIO_PA0 , QL_GPIO_OUTPUT_HIGH);

    /* Prepare the data to be sent */
    for(uint32_t i = 0; i < sizeof(slave_send_data); i++)
    {
        slave_send_data[i] = i + 10;
    }

    /* Initialization I2C slave */
    if(QL_I2C_SUCCRSS != ql_i2c_slave_init(QL_I2C_CHANNEL_1, QL_FAST_PLUS_MODE, QL_PIN_MUX_1, IIC_SLVAE_ADDRESS))
    {
        ql_debug("I2C SLAVE INIT FAIL!\\r\\n");
    }

    while(1)
    {
        ql_i2c_slave_receive(QL_I2C_CHANNEL_1, ql_slave_recv_data, &ql_slave_recv_len);
        if(ql_slave_recv_len > 0)
        {
            ql_debug("SLAVE -> RECV DATA FROM MASTER, DATA LENGTH:%d\\r\\n", ql_slave_recv_len);
            for (uint32_t i = 0; i < ql_slave_recv_len; i++)
            {
                ql_debug("%02X ", ql_slave_recv_data[i]);
            }
            ql_debug("\\r\\n"); 

            ql_gpio_set_level(QL_GPIO_PA0 , QL_GPIO_OUTPUT_HIGH);

            slave_send_data[0] = ql_slave_send_cnt++;
            if(ql_slave_send_cnt > 255) ql_slave_send_cnt = 0;

            ql_i2c_slave_transmit(QL_I2C_CHANNEL_1, slave_send_data, sizeof(slave_send_data));

            /* Notification master */
            ql_gpio_set_level(QL_GPIO_PA0 , QL_GPIO_OUTPUT_LOW);
        }
    }
}
I2C Master Operation
  • ql_i2c_demo_master_init(): Initializes I2C master channel 1, with PA6 serving as SCL, PA7 as SDA, and PA0 indicating that data is ready.

The I2C master initialization example is as follows:

void ql_i2c_demo_master_init(void)
{
    ql_debug("I2C MASTER DEMO RUNNING\\r\\n");

    /* Configure I/O port to check whether data is ready on the slave */
    ql_gpio_set_port_pull(QL_GPIO_PA0,1);
    ql_gpio_set_port_mux(QL_GPIO_PA0, QL_PORTA0_FUNC_A0);
    ql_gpio_set_dir(QL_GPIO_PA0, QL_GMODE_INPUT_PULLUP);

    /* Prepare the data to be sent */
    for (uint32_t i = 1; i < sizeof(master_send_data); i++)
    {
        master_send_data[i] = i;
    }

    /* Initialization I2C master */
    if(QL_I2C_SUCCRSS != ql_i2c_master_init(QL_I2C_CHANNEL_1, QL_FAST_MODE, QL_PIN_MUX_1))
    {
        ql_debug("I2C MASTER INIT FAIL!\\r\\n");
    }

    while (1)
    {   
        /* Master send data counter */
        master_send_data[0] = ql_master_send_cnt++;
        if(ql_master_send_cnt > 255) ql_master_send_cnt = 0;

        /* Master transmit data to slave via i2c port */
        ql_i2c_master_transmit(QL_I2C_CHANNEL_1, IIC_SLVAE_ADDRESS, master_send_data, sizeof(master_send_data));

        /* Master wait for the slave to prepare data */
        while(gpio_get_pin_value(GPIO_PORT_A, GPIO_BIT_0));

        /* Master receive data from slave via i2c port */
        ql_i2c_master_receive(QL_I2C_CHANNEL_1, IIC_SLVAE_ADDRESS, ql_master_recv_data, &ql_master_recv_len);

        ql_debug("MASTER -> RECV DATA FROM SLAVE, DATA LENGTH:%d\\r\\n", ql_master_recv_len);
        for (uint32_t i = 0; i < ql_master_recv_len; i++)
        {
            ql_debug("%02X ", ql_master_recv_data[i]);
        }
        ql_debug("\\r\\n");   

        ql_sys_delay_100us(10000);
    }  
}

Connect the PA6, PA7, and PA0 pins of the two modules to each other, with PA0 serving as the pin indicating the slave data is ready. The I2C slave will print out the data received from the master and transmit the data back to the master.

I2C Master-Slave Communication Debugging


Terms and Abbreviations

Abbreviation Description
ADC Analog-to-Digital Converter
API Application Programming Interface
CLK Clock
CPHA Clock Phase
CPOL Clock Polarity
CS Chip Select
EVB Evaluation Board
GPIO General-Purpose Input/Output
I2C Inter-Integrated Circuit
IoT Internet of Things
PMU Power Management Unit
PWM Pulse Width Modulation
RTOS Real-Time Operating System
SCL Serial Clock Line
SDA Serial Data Line
SDK Software Development Kit
SPI Serial Peripheral Interface
UART Universal Asynchronous Receiver/Transmitter