HCM111Z QuecOpen(SDK) 外设接口开发指导

简介

移远通信 HCM111Z 模块支持 QuecOpen® 解决方案。QuecOpen® 是基于 RTOS 系统的嵌入式开发平台。它旨在简化物联网应用的开发和设计。有关 QuecOpen® 的详细信息,请参考 *文档 [1]*。

本文档适用于基于 SDK 构建环境的 QuecOpen® 解决方案。本文档主要介绍在 QuecOpen® 方案下,如何使用模块所支持的 GPIO、PMU GPIO、UART、ADC、PWM、SPI 和 I2C API 进行对应外设接口开发。


GPIO

GPIO API

头文件

ql_gpio.h,GPIO API 的头文件,在 components/quectel_api/ql_include 目录中。除非另有说明,本文档中提到的所有头文件都在此目录中。

API 概述

函数 描述
ql_gpio_set_port_mux() 设置 GPIO 复用功能。
ql_gpio_init() 初始化 GPIO。
ql_gpio_set_level() 设置指定 GPIO 的引脚电平。
ql_gpio_get_level() 获取指定 GPIO 的引脚电平。
ql_gpio_int_init() 初始化和使能 GPIO 中断。
ql_gpio_int_disable() 关闭配置的 GPIO 中断。
ql_gpio_set_port_pull() 设置 GPIO 作为输入端口时的上拉模式。

API 描述

ql_gpio_set_port_mux

此函数用于设置 GPIO 复用功能。

原型:

ql_gpio_errcode_e ql_gpio_set_port_mux(ql_gpio_num_e pin, uint8_t func)

参数:

  • pin: [In] GPIO 引脚编号。有关详细信息,请参见 ql_gpio_num_e
  • func: [In] GPIO 复用功能。

返回值:

函数执行结果码,请参见 ql_gpio_errcode_e


ql_gpio_init

此函数用于初始化 GPIO。

原型:

ql_gpio_errcode_e ql_gpio_init(ql_gpio_num_e pin, ql_gpio_mode_e mode)

参数:

  • pin: [In] GPIO 引脚编号。有关详细信息,请参见 ql_gpio_num_e
  • mode: [In] GPIO 模式。有关详细信息,请参见 ql_gpio_mode_e

返回值:

函数执行结果码,请参见 ql_gpio_errcode_e

ql_gpio_num_e

GPIO 编号信息的枚举:

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;
成员 描述
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

GPIO 模式的枚举:

typedef enum {
  QL_GMODE_INPUT_PULLDOWN = 1,
  QL_GMODE_INPUT_PULLUP,
  QL_GMODE_OUTPUT=0,
} ql_gpio_mode_e;
成员 描述
QL_GMODE_INPUT_PULLDOWN 下拉输入(暂不支持)
QL_GMODE_OUTPUT 推挽输出
QL_GMODE_INPUT_PULLUP 上拉输入
ql_gpio_errcode_e

GPIO API 相关结果码枚举:

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;
成员 描述
QL_GPIO_SUCCESS 执行成功
QL_GPIO_EXECUTE_ERR 执行失败
QL_GPIO_INVALID_PARAM_ERR 无效参数
QL_GPIO_EXTI_LINE_CLASH_ERR GPIO 中断线设置冲突

ql_gpio_set_level

此函数用于设置指定 GPIO 的引脚电平,仅对已经配置为输出模式的引脚有效。

原型:

ql_gpio_errcode_e ql_gpio_set_level(ql_gpio_num_e pin, ql_gpio_output_level_e output_level)

参数:

  • pin: [In] GPIO 引脚编号。有关详细信息,请参见 ql_gpio_num_e
  • output_level: [In] 引脚电平设置,只针对输出引脚。有关详细信息,请参见 ql_gpio_output_level_e

返回值:

函数执行结果码,请参见 ql_gpio_errcode_e

ql_gpio_output_level_e

GPIO 输出电平的枚举:

typedef enum {
  QL_GPIO_OUTPUT_LOW,
  QL_GPIO_OUTPUT_HIGH,
} ql_gpio_output_level_e;
成员 描述
QL_GPIO_OUTPUT_LOW 低电平
QL_GPIO_OUTPUT_HIGH 高电平

ql_gpio_get_level

此函数用于获取指定 GPIO 的引脚电平。

原型:

ql_gpio_errcode_e ql_gpio_get_level(ql_gpio_num_e pin, uint32_t *input_level)

参数:

  • pin: [In] GPIO 编号。有关详细信息,请参见 ql_gpio_num_e
  • input_level: [Out] GPIO 引脚电平。

返回值:

函数执行结果码,请参见 ql_gpio_errcode_e


ql_gpio_int_init

此函数用于初始化和使能 GPIO 中断。

原型:

ql_gpio_errcode_e ql_gpio_int_init(ql_gpio_num_e pin, ql_gpio_irq_trigger_e trigger, ql_gpio_irq_callback callback)

参数:

  • pin: [In] GPIO 引脚编号。有关详细信息,请参见 ql_gpio_num_e
  • trigger: [In] GPIO 中断触发方式。有关详细信息,请参见 ql_gpio_irq_trigger_e
  • callback: [In] GPIO 中断回调函数。有关详细信息,请参见 ql_gpio_irq_callback

返回值:

函数执行结果码,请参见 ql_gpio_errcode_e

ql_gpio_irq_trigger_e

GPIO 中断触发方式的枚举:

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;
成员 描述
QL_IRQ_TRIGGER_LOW_LEVEL 低电平中断
QL_IRQ_TRIGGER_HIGH_LEVEL 高电平中断
QL_IRQ_TRIGGER_RISING_EDGE 上升沿中断
QL_IRQ_TRIGGER_FALLING_EDGE 下降沿中断
ql_gpio_irq_callback

此函数为 GPIO 中断的回调函数。

typedef void (*ql_gpio_irq_callback)(void *arg, uint8_t line)

参数:

  • arg: [Out] 触发 GPIO 中断的引脚。
  • line: [Out] 触发 GPIO 中断的外部中断线序号。

ql_gpio_int_disable

此函数用于关闭配置的 GPIO 中断。

原型:

ql_gpio_errcode_e ql_gpio_int_disable(ql_gpio_num_e pin)

参数:

  • pin: [In] GPIO 引脚编号。有关详细信息,请参见 ql_gpio_num_e

返回值:

函数执行结果码,请参见 ql_gpio_errcode_e


ql_gpio_set_port_pull

此函数用于设置 GPIO 作为输入端口时的上拉模式。

原型:

ql_gpio_errcode_e ql_gpio_set_port_pull(ql_gpio_num_e pin, uint8_t enable)

参数:

  • pin: [In] GPIO 引脚编号。有关详细信息,请参见 ql_gpio_num_e
  • enable: [In] 上拉模式设置。True 使能上拉模式,False 不设置。

返回值:

函数执行结果码,请参见 ql_gpio_errcode_e


开发过程

本章描述如何在应用程序中使用上述的 GPIO API,并进行基础的调试,示例中默认使用 QL_GPIO_PD4QL_GPIO_PD5QL_GPIO_PD6 进行测试。

操作过程

模块 SDK 中提供了操作 GPIO 的示例。演示在 quectel_demo/ql_gpio_demo/code 目录下的 ql_gpio_demo.c 中。相关函数的描述如下:

  • demo_gpio():初始化 GPIO 和使能 GPIO 中断。
  • ql_gpio_irq_test():中断回调函数,实现了设置 GPIO 引脚电平和关闭 GPIO 中断。
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;
    }
}

函数调试

要调试 GPIO 函数,使用安装了模块的开发板(例如,HCM111Z TE-B),并按照以下步骤操作:

  1. 运行 操作过程 中描述的 GPIO 演示。
  2. 重新编译固件版本,并将其烧录到模块。
  3. 重启模块。
  4. 打开 UART 1 端口以获取日志信息。

串口工具中获取 Log

若调试过程中打印中断信息,则表示触发 GPIO 中断。

GPIO测试 Log

PMU GPIO

PMU GPIO API

头文件

ql_pmu_gpio.h,PMU GPIO API 的头文件,在 components/quectel_api/ql_include 目录中。除非另有说明,本文档中提到的所有头文件都在此目录中。

PMU GPIO 相较于普通 GPIO 的区别是 PMU GPIO 可以让模块在睡眠状态下保持输出电平状态不变。

API 概述

函数 描述
ql_pmu_gpio_init() 初始化 PMU GPIO。
ql_pmu_gpio_set_level() 设置指定 PMU GPIO 的引脚电平。
ql_pmu_gpio_get_level() 获取指定 PMU GPIO 的引脚电平。
ql_pmu_gpio_int_init() 初始化和使能 PMU GPIO 中断。
ql_pmu_gpio_int_disable() 关闭配置的 PMU GPIO 中断。

API 描述

ql_pmu_gpio_init

此函数用于初始化 PMU GPIO。

原型:

ql_gpio_errcode_e ql_pmu_gpio_init(ql_gpio_num_e pin, ql_gpio_mode_e mode)

参数:

  • pin: [In] PMU GPIO 引脚编号。有关详细信息,请参见 ql_gpio_num_e
  • mode: [In] PMU GPIO 模式。有关详细信息,请参见 ql_gpio_mode_e

返回值:

函数执行结果码,请参见 ql_gpio_errcode_e


ql_pmu_gpio_set_level

此函数用于设置指定 PMU GPIO 的引脚电平,仅对已经配置为输出模式的引脚有效。

原型:

ql_gpio_errcode_e ql_pmu_gpio_set_level(ql_gpio_num_e pin, ql_gpio_output_level_e output_level)

参数:

  • pin: [In] PMU GPIO 引脚编号。有关详细信息,请参见 ql_gpio_num_e
  • output_level: [In] 引脚电平设置,只针对输出引脚。有关详细信息,请参见 ql_gpio_output_level_e

返回值:

函数执行结果码,请参见 ql_gpio_errcode_e


ql_pmu_gpio_get_level

此函数用于获取指定 PMU GPIO 的引脚电平。

原型:

ql_gpio_errcode_e ql_pmu_gpio_get_level(ql_gpio_num_e pin, uint32_t *input_level)

参数:

  • pin: [In] PMU GPIO 引脚编号。有关详细信息,请参见 ql_gpio_num_e
  • input_level: [Out] PMU GPIO 引脚电平值。

返回值:

函数执行结果码,请参见 ql_gpio_errcode_e


ql_pmu_gpio_int_init

此函数用于初始化和使能 PMU GPIO 中断。

原型:

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)

参数:

返回值:

函数执行结果码,请参见 ql_gpio_errcode_e

ql_pmu_gpio_irq_callback

此函数为 PMU GPIO 中断的回调函数。

typedef void (*ql_pmu_gpio_irq_callback)(void *arg)

参数:

  • arg: [Out] 预留。

ql_pmu_gpio_int_disable

此函数用于关闭配置的 PMU GPIO 中断。

原型:

ql_gpio_errcode_e ql_pmu_gpio_int_disable(ql_gpio_num_e pin)

参数:

  • pin: [In] PMU GPIO 引脚编号。有关详细信息,请参见 ql_gpio_num_e

返回值:

函数执行结果码,请参见 ql_gpio_errcode_e


开发过程

本章描述如何在应用程序中使用上述的 PMU GPIO API,并进行基础的调试,示例中默认使用 QL_GPIO_PD4QL_GPIO_PD5QL_GPIO_PD6 进行测试。

操作过程

模块 SDK 中提供了操作 PMU GPIO 的示例。演示在 quectel_demo/ql_pmu_gpio_demo/code 目录下的 ql_pmu_gpio_demo.c 中。相关函数的描述如下:

  • demo_pmu_gpio():初始化 PMU GPIO 和使能 PMU GPIO 中断。
  • ql_gpio_pmu_irq_test():中断回调函数,实现了获取和设置 PMU GPIO 的引脚电平,以及关闭 PMU GPIO 中断的功能。
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;
    }
}

函数调试

要调试 PMU GPIO 函数,使用安装了模块的开发板(例如,HCM111Z TE-B),并按照以下步骤操作:

  1. 运行 操作过程 中描述的 PMU GPIO 演示。
  2. 重新编译固件版本,并将其烧录到模块。
  3. 重启模块。
  4. 打开 UART 1 端口以获取日志信息。

串口工具中获取 Log

若调试过程中打印如下信息,则表示触发 PMU GPIO 中断。

PMU GPIO测试 Log

UART

UART API

头文件

ql_uart.h,UART API 的头文件,在 components/quectel_api/ql_include 目录中。除非另有说明,本文档中提到的所有头文件都在此目录中。

API 概述

函数 描述
ql_uart_set_dcbconfig() 设置串口属性。
ql_uart_get_dcbconfig() 获取串口属性配置。
ql_uart_open() 打开串口。
ql_uart_close() 关闭串口。
ql_uart_write() 通过串口向模块写入数据。
ql_uart_read() 通过串口读取模块的数据。
ql_uart_set_rx_cb() 注册串口接收数据中断事件的回调函数。

API 描述

ql_uart_set_dcbconfig

此函数用于设置串口属性,设置后重新打开串口才能生效。

原型:

ql_uart_errcode_e ql_uart_set_dcbconfig(ql_uart_port_number_e port, ql_uart_config_s *dcb)

参数:

返回值:

函数执行结果码,请参见 ql_uart_errcode_e

ql_uart_port_number_e

串口编号信息枚举:

typedef enum {
  QL_UART_PORT_1,
  QL_UART_PORT_2,
} ql_uart_port_number_e;
成员 描述
QL_UART_PORT_1 串口1
QL_UART_PORT_2 串口2
ql_uart_config_s

串口属性配置信息结构体:

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;
类型 参数 功能描述
uint8_t is_debug_port 1 打印log
0 收发数据
ql_uart_baud_e baudrate 波特率,默认为115200 bps,详见 ql_uart_baud_e
ql_uart_databit_e data_bit 数据位,默认为8位,详见 ql_uart_databit_e
ql_uart_stopbit_e stop_bit 停止位,默认为1位,详见 ql_uart_stopbit_e
ql_uart_parityit_e parity_bit 校验位,默认无校验,详见 ql_uart_parityit_e
ql_uart_baud_e

串口波特率枚举:

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;
成员 描述
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_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

串口数据位的枚举:

typedef enum {
  QL_UART_DATABIT_5,
  QL_UART_DATABIT_6,
  QL_UART_DATABIT_7,
  QL_UART_DATABIT_8,
} ql_uart_databit_e;
成员 描述
QL_UART_DATABIT_5 5位
QL_UART_DATABIT_6 6位
QL_UART_DATABIT_7 7位
QL_UART_DATABIT_8 8位
ql_uart_stopbit_e

串口停止位枚举:

typedef enum {
  QL_UART_STOP_1,
  QL_UART_STOP_2,
} ql_uart_stopbit_e;
成员 描述
QL_UART_STOP_1 1位
QL_UART_STOP_2 2位
ql_uart_parityit_e

串口校验位枚举:

typedef enum {
  QL_UART_PARITY_NONE,
  QL_UART_PARITY_ODD,
  QL_UART_PARITY_EVEN,
} ql_uart_parityit_e;
成员 描述
QL_UART_PARITY_NONE 无校验
QL_UART_PARITY_ODD 奇校验
QL_UART_PARITY_EVEN 偶校验
ql_uart_errcode_e

UART API 结果码枚举:

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;
成员 描述
QL_UART_SUCCESS 执行成功
QL_UART_EXECUTE_ERR 执行失败
QL_UART_MEM_ADDR_NULL_ERR 参数地址为空
QL_UART_INVALID_PARAM_ERR 无效参数
QL_UART_NOT_OPEN_ERR 串口未打开

ql_uart_get_dcbconfig

此函数用于获取串口属性配置。

原型:

ql_uart_errcode_e ql_uart_get_dcbconfig(ql_uart_port_number_e port, ql_uart_config_s *dcb)

参数:

返回值:

函数执行结果码,请参见 ql_uart_errcode_e


ql_uart_open

此函数用于打开串口。

原型:

ql_uart_errcode_e ql_uart_open(ql_uart_port_number_e port)

参数:

返回值:

函数执行结果码,请参见 ql_uart_errcode_e


ql_uart_close

此函数用于关闭串口。

原型:

ql_uart_errcode_e ql_uart_close(ql_uart_port_number_e port)

参数:

返回值:

函数执行结果码,请参见 ql_uart_errcode_e


ql_uart_write

此函数用于通过串口向模块写入数据。

原型:

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

参数:

  • port: [In] 串口编号。有关详细信息,请参见 ql_uart_port_number_e
  • data: [In] 写入的数据。
  • data_len: [In] 写入的数据长度。

返回值:

函数执行结果码,请参见 ql_uart_errcode_e


ql_uart_read

此函数用于通过串口读取模块的数据。

原型:

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

参数:

  • port: [In] 串口编号。有关详细信息,请参见 ql_uart_port_number_e
  • data: [Out] 读取的数据。
  • data_len: [In] 读取的数据长度。

返回值:

函数执行结果码,请参见 ql_uart_errcode_e


ql_uart_set_rx_cb

此函数用于注册串口接收数据中断事件的回调函数。

原型:

ql_uart_errcode_e ql_uart_set_rx_cb(ql_uart_port_number_e port, ql_uart_callback uart_cb)

参数:

返回值:

函数执行结果码,请参见 ql_uart_errcode_e

ql_uart_callback

此函数为串口中断的回调函数。

typedef void (*ql_uart_callback)(char value)

参数:

  • value: [In] 通过串口接收的数据。

开发过程

本章描述如何在应用程序中使用上述的串口函数,并进行基础的调试,示例中默认使用串口 0 进行测试。

操作过程

模块 SDK 中提供了操作 UART 的示例。演示在 quectel_demo/ql_uart_demo/code 目录下的 ql_uart_demo.c 中。相关函数的描述如下:

  • demo_uart():初始化串口,注册中断回调函数。
  • ql_uart_cb_test():中断回调函数,可通过串口接收数据。
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);
}

函数调试

要调试 UART 函数,使用安装了模块的开发板(例如,HCM111Z TE-B),并按照以下步骤操作:

  1. 运行 操作过程 中描述的 UART 演示。
  2. 重新编译固件版本,并将其烧录到模块。
  3. 重启模块。
  4. 打开 UART 1 端口以获取日志信息。

串口工具中获取 Log


ADC

ADC API

头文件

ql_adc.h,ADC API 的头文件,在 components/quectel_api/ql_include 目录中。除非另有说明,本文档中提到的所有头文件都在此目录中。

API 概述

函数 描述
ql_adc_channel_init() 配置 ADC 通道参数。
ql_adc_channel_start() 使能 ADC 检测。
ql_adc_channel_stop() 停止 ADC 检测。

API 描述

ql_adc_channel_init

此函数用于配置 ADC 通道参数。

原型:

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)

参数:

  • handle: [In] ADC 通道信息。有关详细信息,请参见 ql_adc_obj_s
  • cb: [In] 通道检测完成的回调函数。有关详细信息,请参见 ql_adc_obj_callback
  • channel: [In] ADC 通道编号。有关详细信息,请参见 ql_adc_channel_e
  • user_data: [In] 用户数据。

返回值:

函数执行结果码,请参见 ql_adc_errcode_e

ql_adc_obj_s

ADC 通道信息结构体:

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;
类型 参数 描述
void * user_data 用户数据
ql_adc_channel_e channel ADC 通道编号
ql_adc_obj_callback cb 通道检测完成的回调函数
struct adc_obj_ * next 链表下一个节点的地址
ql_adc_obj_callback

此函数为 ADC 通道检测完成回调函数。

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

参数:

  • channel: [Out] ADC 通道编号。有关详细信息,请参见 ql_adc_channel_e
  • value: [Out] ADC 通道电压采样结果。范围:0~1023。ADC 参考电压为 3.3 V,当采样结果为 1023 时表示该通道电压大于或等于 3.3 V。
  • user_data: [Out] 用户数据。
ql_adc_channel_e

ADC 通道编号枚举:

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;
成员 描述
QL_ADC_CHANNEL_0 通道0,检测 QL_GPIO_PD4 引脚电压
QL_ADC_CHANNEL_1 通道1,检测 QL_GPIO_PD5 引脚电压
QL_ADC_CHANNEL_2 通道2,检测 QL_GPIO_PD6 引脚电压
QL_ADC_CHANNEL_3 通道3,检测 QL_GPIO_PD7 引脚电压
ql_adc_errcode_e

ADC API 结果码枚举:

typedef enum {
  QL_ADC_SUCCESS = 0,
  QL_ADC_EXECUTE_ERR,
  QL_ADC_INVALID_PARAM_ERR,
} ql_adc_errcode_e;
成员 描述
QL_ADC_SUCCESS 函数执行成功
QL_ADC_EXECUTE_ERR 函数执行失败
QL_ADC_INVALID_PARAM_ERR 参数无效

ql_adc_channel_start

此函数用于使能 ADC 检测。

原型:

ql_adc_errcode_e ql_adc_channel_start(ql_adc_obj_s *handle)

参数:

  • handle: [In] ADC 通道信息。有关详细信息,请参见 ql_adc_obj_s

返回值:

函数执行结果码,请参见 ql_adc_errcode_e


ql_adc_channel_stop

此函数用于停止 ADC 检测。

原型:

ql_adc_errcode_e ql_adc_channel_stop(ql_adc_obj_s *handle)

参数:

  • handle: [In] ADC 通道信息。有关详细信息,请参见 ql_adc_obj_s

返回值:

函数执行结果码,请参见 ql_adc_errcode_e


开发过程

本章描述如何在应用程序中使用上述的 API,并进行基础的调试,示例中默认使用通道 0 进行测试。

操作过程

模块 SDK 中提供了操作 ADC 的示例。演示在 quectel_demo/ql_adc_demo/code 目录下的 ql_adc_demo.c 中。相关函数的描述如下:

  • demo_adc():重映射 ADC 通道,初始化 ADC。
  • adc_tim_fn():定时器回调函数,实现了每隔一秒检测 ADC 通道。
  • ql_adc_detect_callback():打印 ADC 通道检测结果。
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);
}

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);
}

函数调试

要调试 ADC 函数,使用安装了模块的开发板(例如,HCM111Z TE-B),并按照以下步骤操作:

  1. 运行 操作过程 中描述的 ADC 演示。
  2. 重新编译固件版本,并将其烧录到模块。
  3. 重启模块。
  4. 打开 UART 1 端口以获取日志信息。改变引脚输入电压,检测值随之改变。

串口工具中获取 Log


PWM

PWM API

头文件

ql_pwm.h,PWM API 的头文件,在 components/quectel_api/ql_include 目录中。除非另有说明,本文档中提到的所有头文件都在此目录中。

API 概述

函数 描述
ql_pwm_init() 初始化 PWM。
ql_pwm_update_param() 更新 PWM 配置参数。
ql_pwm_enable() 使能 PWM 输出。
ql_pwm_disable() 停止 PWM 输出。

API 描述

ql_pwm_init

此函数用于初始化 PWM。

原型:

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

参数:

  • channel: [In] PWM 通道。有关详细信息,请参见 ql_pwm_channel_e
  • frequency: [In] PWM 频率。
  • high_duty: [In] PWM 占空比值。

返回值:

函数执行结果码,请参见 ql_pwm_errcode_e

ql_pwm_channel_e

PWM 通道枚举:

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;
成员 描述
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

PWM API 结果码枚举:

typedef enum {
  QL_PWM_SUCCESS = 0,
  QL_PWM_EXECUTE_ERR,
  QL_PWM_INVALID_PARAM_ERR,
} ql_pwm_errcode_e;
成员 描述
QL_PWM_SUCCESS 执行成功
QL_PWM_EXECUTE_ERR 执行失败
QL_PWM_INVALID_PARAM_ERR 无效参数

ql_pwm_update_param

此函数用于更新 PWM 配置参数,更新后在下一个 PWM 周期生效。

原型:

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

参数:

  • channel: [In] PWM 通道。有关详细信息,请参见 ql_pwm_channel_e
  • frequency: [In] PWM 频率。
  • high_duty: [In] PWM 占空比值。

返回值:

函数执行结果码,请参见 ql_pwm_errcode_e


ql_pwm_enable

此函数用于使能 PWM 输出。

原型:

ql_pwm_errcode_e ql_pwm_enable(ql_pwm_channel_e channel)

参数:

返回值:

函数执行结果码,请参见 ql_pwm_errcode_e


ql_pwm_disable

此函数用于停止 PWM 输出。

原型:

ql_pwm_errcode_e ql_pwm_disable(ql_pwm_channel_e channel)

参数:

返回值:

函数执行结果码,请参见 ql_pwm_errcode_e


开发过程

本章描述如何在应用程序中使用上述的 PWM API,并进行基础的调试,示例中默认使用 QL_PWM_4QL_PWM_5 进行测试。

操作过程

模块 SDK 中提供了操作 PWM 的示例。演示在 quectel_demo/ql_pwm_demo/code 目录下的 ql_pwm_demo.c 中。相关函数的描述如下:

  • demo_pwm():初始化 PWM、使能 PWM 输出和关闭 PWM 输出。
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);
}

函数调试

要调试 PWM 函数,使用安装了模块的开发板(例如,HCM111Z TE-B),并按照以下步骤操作:

  1. 运行 操作过程 中描述的 PWM 演示。
  2. 重新编译固件版本,并将其烧录到模块。
  3. 重启模块。
  4. 打开 UART 1 端口以获取日志信息。

串口工具中获取 Log

逻辑分析仪获取 PWM 波形


SPI

SPI API

头文件

ql_spi.h,SPI API 的头文件,在 components/quectel_api/ql_include 目录中。除非另有说明,本文档中提到的所有头文件都在此目录中。

API 概述

函数 描述
ql_spi_init() 初始化 SPI。
ql_spi_transfer() 发送或接收 SPI 数据。

API 描述

ql_spi_init

此函数用于初始化 SPI。

原型:

ql_spi_errcode_e ql_spi_init(ql_spi_config_s spi_cfg)

参数:

  • spi_cfg: [In] SPI 配置。有关详细信息,请参见 ql_spi_config_s

返回值:

函数执行结果码,请参见 ql_spi_errcode_e

ql_spi_config_s

SPI 配置信息结构体:

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;
类型 参数 描述
uint32_t spiclk SPI 时钟频率;最大 24 MHz。
ql_spi_cpol_pol_e cpol SPI 时钟极性,详见 ql_spi_cpol_pol_e
ql_spi_cpha_pol_e cpha SPI 时钟相位,详见 ql_spi_cpha_pol_e
ql_spi_master_slave_mode_e masterorslave SPI 主从机选择,详见 ql_spi_master_slave_mode_e
void (*spi_cs_ctrl)(uint8_t) spi_cs_ctrl 函数指针,指向控制 CS 引脚的函数,具体可参考下方举例的ql_spi_cs_ctrl()
ql_spi_cpol_pol_e

SPI 时钟极性枚举:

typedef enum {
  QL_SPI_CPOL_LOW = 0,
  QL_SPI_CPOL_HIGH,
} ql_spi_cpol_pol_e;
成员 描述
QL_SPI_CPOL_LOW SCK 在空闲状态处于低电平
QL_SPI_CPOL_HIGH SCK 在空闲状态处于高电平
ql_spi_cpha_pol_e

SPI 时钟相位枚举:

typedef enum {
  QL_SPI_CPHA_1Edge,
  QL_SPI_CPHA_2Edge,
} ql_spi_cpha_pol_e;
成员 描述
QL_SPI_CPHA_1Edge 在 SCK 周期的第一个边沿采样数据。
QL_SPI_CPHA_2Edge 在 SCK 周期的第二个边沿采样数据。
ql_spi_master_slave_mode_e

SPI 主从机选择枚举:

typedef enum {
  QL_SPI_MASTER = 0,
  QL_SPI_SLAVE,
} ql_spi_master_slave_mode_e;
成员 描述
QL_SPI_MASTER SPI 为主机
QL_SPI_SLAVE SPI 为从机(暂不支持)
ql_spi_errcode_e

SPI API 结果码枚举:

typedef enum {
  QL_SPI_SUCCESS = 0,
  QL_SPI_EXECUTE_ERR,
  QL_SPI_INVALID_PARAM_ERR,
} ql_spi_errcode_e;
成员 描述
QL_SPI_SUCCESS 执行成功
QL_SPI_EXECUTE_ERR 执行失败
QL_SPI_INVALID_PARAM_ERR 无效参数

ql_spi_transfer

此函数用于发送或接收 SPI 数据。

原型:

ql_errcode_spi_e ql_spi_transfer(ql_spi_message_s *spi_msg)

参数:

  • spi_msg: [In] SPI 发送或接收的数据。有关详细信息,请参见 ql_spi_message_s

返回值:

函数执行结果码,请参见 ql_spi_errcode_e

ql_spi_message_s

SPI 发送或接收的数据结构体:

typedef struct {
  UINT8 *send_buf;
  UINT32 send_len;
  UINT8 *recv_buf;
  UINT32 recv_len;
} ql_spi_message_s;
类型 参数 描述
UINT8 * send_buf 发送数据
UINT32 send_len 发送的数据的长度
UINT8 * recv_buf 接收数据
UINT32 recv_len 接收的数据的长度

开发过程

本章描述如何在应用程序中使用上述的 SPI API,并进行基础的调试。

操作过程

模块 SDK 中提供了操作 SPI 的示例。演示在 quectel_demo/ql_spi_demo/code 目录下的 ql_spi_demo.c 中。相关函数的描述如下:

  • demo_spi_master():初始化 SPI,发送并接收数据。
  • ql_spi_cs_ctrl():控制 CS 引脚。
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_CPHA_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);
}

函数调试

要调试 SPI 函数,使用安装了模块的开发板(例如,HCM111Z TE-B),并按照以下步骤操作:

  1. 运行 操作过程 中描述的 SPI 演示。
  2. 重新编译固件版本,并将其烧录到模块。
  3. 重启模块。
  4. 打开 UART 1 端口以获取日志信息。

串口工具中获取 Log

逻辑分析仪抓取 SPI 波形


I2C

I2C API

头文件

ql_i2c.h,I2C API 的头文件,在 components/quectel_api/ql_include 目录中。除非另有说明,本文档中提到的所有头文件都在此目录中。

API 概述

函数 描述
ql_i2c_init() 初始化 I2C 总线。
ql_i2c_write() 向 I2C 总线中写入数据。
ql_i2c_read() 从 I2C 总线中读取数据。
ql_i2c_master_init() 初始化 I2C 主机。
ql_i2c_master_transmit() I2C 主机向从机传输数据。
ql_i2c_master_receive() I2C 主机读取从机传输的数据。
ql_i2c_slave_init() 初始化 I2C 从机。
ql_i2c_slave_transmit() I2C 从机向主机传输数据。
ql_i2c_slave_receive() I2C 从机读取主机传输的数据。

API 描述

ql_i2c_init

此函数用于初始化 I2C 总线。

原型:

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

参数:

  • i2c_hdl: [Out] 获取的 I2C 句柄。
  • mode: [In] I2C 的工作模式。有关详细信息,请参见 ql_i2c_mode_e
  • channel: [In] I2C 通道。有关详细信息,请参见 ql_i2c_channel_e

返回值:

函数执行结果码,请参见 ql_errcode_i2c_e

ql_i2c_mode_e

I2C 工作模式枚举:

typedef enum {
  QL_STANDARD_MODE = 0,
  QL_FAST_MODE,
  QL_FAST_PLUS_MODE
} ql_i2c_mode;
成员 描述
QL_STANDARD_MODE 标准模式,速率:100 kbps
QL_FAST_MODE 快速模式,速率:400 kbps
QL_FAST_PLUS_MODE 高速模式,速率:1000 kbps
ql_i2c_channel_e

I2C 通道枚举:

typedef enum {
  QL_I2C_CHANNEL_0 = 0,
  QL_I2C_CHANNEL_1,
} ql_i2c_channel_e;
成员 描述
QL_I2C_CHANNEL_0 I2C 通道0
QL_I2C_CHANNEL_1 I2C 通道1
ql_errcode_i2c_e

I2C API 结果码枚举:

typedef enum {
  QL_I2C_SUCCESS = 0,
  QL_I2C_INIT_ERR,
  QL_I2C_WRITE_ERR,
  QL_I2C_READ_ERR,
} ql_errcode_i2c_e;
成员 描述
QL_I2C_SUCCESS 执行成功
QL_I2C_INIT_ERR I2C 初始化失败
QL_I2C_WRITE_ERR 向 I2C 总线中写入数据失败
QL_I2C_READ_ERR 从 I2C 总线中读取数据失败

ql_i2c_write

此函数用于向 I2C 总线中写入数据。

原型:

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)

参数:

  • i2c_hdl: [In] I2C 句柄。
  • slave_addr: [In] I2C 从机设备地址。
  • reg_addr: [In] I2C 从机寄存器地址。
  • data: [In] 写入的数据。
  • len: [In] 写入数据的长度。

返回值:

函数执行结果码,请参见 ql_errcode_i2c_e


ql_i2c_read

此函数用于从 I2C 总线中读取数据。

原型:

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)

参数:

  • i2c_hdl: [In] I2C 句柄。
  • slave_addr: [In] I2C 从机设备地址。
  • reg_addr: [In] I2C 从机寄存器地址。
  • data: [Out] 读取的数据。
  • len: [In] 读取数据的长度。

返回值:

函数执行结果码,请参见 ql_errcode_i2c_e


ql_i2c_master_init

此函数用于初始化 I2C 主机。

原型:

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)

参数:

  • i2c_channel: [In] I2C 通道,仅支持 QL_I2C_CHANNEL_1
  • i2c_mode: [In] I2C 的工作模式。
  • pin_mux: [In] I2C 的 SCL 和 SDA 的复用 GPIO 组合。有关详细信息,请参见 ql_i2c_pin_mux_e

返回值:

函数执行结果码,请参见 ql_errcode_i2c_e

ql_i2c_pin_mux_e

I2C 的 SCL 和 SDA 的复用 GPIO 组合枚举:

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;
成员 描述
QL_PIN_MUX_0 选择 PA2 作为 SCL,PA3 作为 SDA
QL_PIN_MUX_1 选择 PA6 作为 SCL,PA7 作为 SDA
QL_PIN_MUX_2 选择 PB2 作为 SCL,PB3 作为 SDA
QL_PIN_MUX_3 选择 PB6 作为 SCL,PB7 作为 SDA
QL_PIN_MUX_4 选择 PC2 作为 SCL,PC3 作为 SDA
QL_PIN_MUX_5 选择 PC6 作为 SCL,PC7 作为 SDA
QL_PIN_MUX_6 选择 PD2 作为 SCL,PD3 作为 SDA
QL_PIN_MUX_7 选择 PD6 作为 SCL,PD7 作为 SDA

ql_i2c_master_transmit

此函数用于 I2C 主机向从机传输数据。

原型:

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)

参数:

  • i2c_channel: [In] I2C 通道,仅支持 QL_I2C_CHANNEL_1
  • slave_addr: [In] I2C 从机设备地址,无需进行偏移。
  • data: [In] 传输的数据。
  • data_len: [In] 传输数据的长度。

返回值:

函数执行结果码,请参见 ql_errcode_i2c_e


ql_i2c_master_receive

此函数用于 I2C 主机读取从机传输的数据。

原型:

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)

参数:

  • i2c_channel: [In] I2C 通道,仅支持 QL_I2C_CHANNEL_1
  • slave_addr: [In] I2C 从机设备地址,无需进行偏移。
  • data: [Out] 读取的数据。
  • data_len: [Out] 读取数据的长度。

返回值:

函数执行结果码,请参见 ql_errcode_i2c_e


ql_i2c_slave_init

此函数用于初始化 I2C 从机。

原型:

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)

参数:

  • i2c_channel: [In] I2C 通道,仅支持 QL_I2C_CHANNEL_1
  • i2c_mode: [In] I2C 的工作模式。
  • pin_mux: [In] I2C 的 SCL 和 SDA 的复用 GPIO 组合。有关详细信息,请参见 ql_i2c_pin_mux_e
  • slave_addr: [In] 从机的初始化地址。

返回值:

函数执行结果码,请参见 ql_errcode_i2c_e


ql_i2c_slave_transmit

此函数用于 I2C 从机向主机传输数据。

原型:

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

参数:

  • i2c_channel: [In] I2C 通道,仅支持 QL_I2C_CHANNEL_1
  • data: [In] 传输的数据。
  • data_len: [In] 传输数据的长度。

返回值:

函数执行结果码,请参见 ql_errcode_i2c_e


ql_i2c_slave_receive

此函数用于 I2C 从机读取主机传输的数据。

原型:

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

参数:

  • i2c_channel: [In] I2C 通道,仅支持 QL_I2C_CHANNEL_1
  • data: [Out] 读取的数据。
  • data_len: [Out] 读取的数据长度。

返回值:

函数执行结果码,请参见 ql_errcode_i2c_e


开发过程

本章描述如何在应用程序中使用上述的 I2C API,并进行基础的调试,示例中默认使用 QL_I2C_CHANNEL_1 进行测试。

操作过程

模块 SDK 中提供了操作 I2C 的示例。演示在 quectel_demo/ql_i2c_demo/code 目录下的 ql_i2c_demo.c 中。本示例中,模块作为 I2C 主机与芯片进行通信。相关函数的描述如下:

  • demo_i2c():初始化 I2C 通道 1。
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;
    }
}

函数调试

要调试 I2C 函数,使用安装了模块的开发板(例如,HCM111Z TE-B),并按照以下步骤操作:

  1. 运行 操作过程 中描述的 I2C 演示。
  2. 重新编译固件版本,并将其烧录到模块。
  3. 重启模块。
  4. 使用逻辑分析仪抓取 I2C 波形。

逻辑分析仪抓取 I2C 波形

I2C 主从模式调试

模块 SDK 代码中提供了操作 I2C 的主从模式示例,示例程序在 quectel_demo/ql_i2c_demo/code 目录的 ql_i2c_master.cql_i2c_slave.c 文件中。本示例中,一个模块作为 I2C 主机,一个模块作为从机进行通信。相关函数的描述如下:

  • ql_i2c_demo_slave_init():初始化 I2C 从机通道 1,PA6 作为 SCL,PA7 作为 SDA,PA0 作为数据准备完成的标志引脚。
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 master */
    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);

        }
    }
}

  • ql_i2c_demo_master_init():初始化 I2C 主机通道 1,PA6 作为 SCL,PA7 作为 SDA,PA0 作为数据准备完成的标志引脚。
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);
    }  
}

将两个模块 PA6、PA7、PA0 引脚分别互相连接,其中 PA0 作为从机数据准备的完成的标志引脚。I2C 从机收到主机传输的数据会将收到的数据打印出来并将数据传输回主机,分别烧录主机和从机的代码到模块。串口调试图如下图所示。


术语缩写

缩略语 英文全称 中文全称
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 实时操作系统
SCK Serial Clock 串行时钟
SCL Serial Clock Line 串行时钟线
SDA Serial Data Line 串行数据线
SDK Software Development Kit 软件开发工具包
SPI Serial Peripheral Interface 串行外设接口
UART Universal Asynchronous Receiver/Transmitter 通用异步收发传输器