GPIO Latch

该示例使用 ENHTIM 实现外部信号变化时锁存计数器的功能。

将 P2_4 引脚配置为 GPIO 输出引脚,模拟外部信号变化,电平持续翻转。将 P2_2 配置为 ENHTIM 的输入引脚,用于检测外部信号变化。

将 P2_2 引脚和 P2_4 引脚连接,当 P2_2 检测到信号的上升沿变化时,ENHTIM 会触发一次计数。在累计触发计数三次后,会触发 ENHTIM_INT_LATCH_CNT_FIFO_THD 中断,在中断函数内执行用户应用程序。

这里应该是 enhtim_latch_gpio_diagram

Latch gpio 框图

用户可以通过不同的宏配置来修改引脚信息,定时时间等。具体宏配置详见 配置选项

环境需求

该示例的环境需求,可参考 环境需求

硬件连线

连接 P2_4 和 P2_2。

配置选项

  1. 可配置如下宏修改 GPIO 的输出引脚。

    #define OUTPUT_PIN          P2_4
    #define GPIO_PIN            GPIO_GetPin(OUTPUT_PIN)
    #define GPIO_PORT           GPIO_GetPort(OUTPUT_PIN)
    
  2. 可配置如下宏修改 ENHTIM 的计数触发引脚。

    #define INPUT_PIN           P2_2
    

编译和下载

该示例的编译和下载流程,可参考 编译和下载

测试验证

  1. 当 EVB 启动后,在 Debug Analyzer 工具内观察如下 log。

    Start latch_gpio test!
    
  2. 初始化完成后,P2_4 持续翻转电平,P2_2 每检测到一次上升沿变化会记录当前计数器值。当 P2_2 累计检测到三次上升沿后,会触发 ENHTIM_INT_LATCH_CNT_FIFO_THD 中断,在中断函数内获取并打印 GPIO 三次触发锁存时的计数器数值。

    ENH_TIM0 ENHTIM_INT_LATCH_CNT2_FIFO_THD
    ENH_TIM0 fifo length = 3
    ENH_TIM0 data[0] = xxx
    ENH_TIM0 data[1] = xxx
    ENH_TIM0 data[2] = xxx
    ENH_TIM0 ENHTIM_INT_LATCH_CNT2_FIFO_THD
    ...
    
  3. 由于 P2_4 持续翻转,ENHTIM_INT_LATCH_CNT_FIFO_THD 中断会持续触发,持续打印 log。

代码介绍

该章节主要介绍示例中的初始化和相应功能实现的代码和流程说明

源码路径

工程文件和源码路径如下:

  • 工程路径: sdk\samples\peripheral\enhtimer\latch_gpio\proj

  • 源码路径: sdk\samples\peripheral\enhtimer\latch_gpio\src

初始化

外设的初始化流程可参考 General Introduction 中的 初始化流程 部分。

  1. 调用 Pad_Config()Pinmux_Config(),配置对应引脚的 PAD 和 PINMUX 。

    void board_gpio_init(void)
    {
        Pad_Config(OUTPUT_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_HIGH);
    
        Pinmux_Config(OUTPUT_PIN, DWGPIO);
    }
    
  2. 调用 RCC_PeriphClockCmd() ,开启 GPIO 时钟。

  3. 对 GPIO 外设进行初始化:

    1. 定义 GPIO_InitTypeDef 类型 GPIO_InitStruct ,调用 GPIO_StructInit()GPIO_InitStruct 预填默认值。

    2. 根据需求修改 GPIO_InitStruct 参数,GPIO 的初始化参数配置如下表。调用 GPIO_Init(),初始化 GPIO 外设。

GPIO 初始化参数

GPIO Hardware Parameters

Setting in the GPIO_InitStruct

GPIO

GPIO pin

GPIO_InitTypeDef::GPIO_Pin

GPIO_PIN_OUTPUT

GPIO direction

GPIO_InitTypeDef::GPIO_Dir

GPIO_DIR_OUT

  1. 调用 RCC_PeriphClockCmd() ,开启 ENHTIM 时钟。

  2. 对 ENHTIM 外设进行初始化:

    1. 定义 ENHTIM_InitTypeDef 类型 ENHTIM_InitStruct ,调用 ENHTIM_StructInit()ENHTIM_InitStruct 预填默认值。

    2. 根据需求修改 ENHTIM_InitStruct 参数,ENHTIM 的初始化参数配置如下表。调用 ENHTIM_Init(),初始化 ENHTIM 外设。

ENHTIM 初始化参数

ENHTIM Hardware Parameters

Setting in the ENHTIM_InitStruct

ENHTIM

Counter mode

ENHTIM_InitTypeDef::ENHTIM_Mode

ENHTIM_MODE_FreeRun

Latch count function

ENHTIM_InitTypeDef::ENHTIM_LatchCountEn [0]

ENABLE

Counter latch trigger mode

ENHTIM_InitTypeDef::ENHTIM_LatchCountTrigger [0]

ENHTIM_LATCH_TRIGGER_RISING_EDGE

Latch counter fifo threshold

ENHTIM_InitTypeDef::ENHTIM_LatchCountThd

3

Latch trigger pin

ENHTIM_InitTypeDef::ENHTIM_LatchTriggerPad

INPUT_PIN

  1. 调用 NVIC_Init() ,配置 NVIC。NVIC 相关配置可参考 中断配置

  2. 调用 ENHTIM_ClearINTPendingBit()ENHTIM_INTConfig() ,清除 ENHTIM 中断,使能 ENHTIM 中断。

    ENHTIM_ClearINTPendingBit(ENHTIMER_NUM, ENHTIM_INT_LATCH_CNT_FIFO_FULL);
    ENHTIM_INTConfig(ENHTIMER_NUM, ENHTIM_INT_LATCH_CNT_FIFO_FULL, ENABLE);
    
    ENHTIM_ClearINTPendingBit(ENHTIMER_NUM, ENHTIM_INT_LATCH_CNT_FIFO_THD);
    ENHTIM_INTConfig(ENHTIMER_NUM, ENHTIM_INT_LATCH_CNT_FIFO_THD, ENABLE);
    
  3. 调用 ENHTIM_Cmd() 使能 ENHTIM 外设。

功能实现

ENHTIM Latch 功能的流程如图所示:

这里应该是 enhtim_latch_count_flow

ENHTIM Latch 流程图

当 ENHTIM 配置的触发引脚,检测到上升沿触发次数达到 FIFO 设定阈值,触发 ENHTIM 的 ENHTIM_INT_LATCH_CNT_FIFO_THD 中断,进入中断处理函数 Enhanced_Timer0_Handler 。 如果设定阈值过大,FIFO 中的数据来不及被搬走,就会触发 ENHTIM_INT_LATCH_CNT_FIFO_FULL 中断。

  1. 触发 FIFO 阈值中断

    1. 判断中断状态位是否为 ENHTIM_INT_LATCH_CNT_FIFO_THD,失能中断。

    2. 调用 ENHTIM_GetLatchCountFIFOLength(),获取 FIFO 内数据个数。

    3. 调用 ENHTIM_ReadLatchCountFIFO(),获取计数值并打印。

    4. 清除中断标志位,重新使能中断。

  2. 触发 FIFO 满中断

    1. 判断中断状态位是否为 ENHTIM_INT_LATCH_CNT_FIFO_FULL

    2. 清除中断标志位。

void Enhanced_Timer0_Handler()
{
    ...
    if (ENHTIM_GetINTStatus(ENH_TIM0, ENHTIM_INT_LATCH_CNT_FIFO_FULL))
    {
        APP_PRINT_INFO0("ENH_TIM0 ENHTIM_INT_LATCH_CNT2_FIFO_FULL\r\n");
        ENHTIM_ClearINTPendingBit(ENH_TIM0, ENHTIM_INT_LATCH_CNT_FIFO_FULL);
    }
    if (ENHTIM_GetINTStatus(ENH_TIM0, ENHTIM_INT_LATCH_CNT_FIFO_THD))
    {
        APP_PRINT_INFO0("ENH_TIM0 ENHTIM_INT_LATCH_CNT2_FIFO_THD\r\n");
        ENHTIM_INTConfig(ENHTIMER_NUM, ENHTIM_INT_LATCH_CNT_FIFO_THD, DISABLE);
        uint8_t length = ENHTIM_GetLatchCountFIFOLength(ENH_TIM0);
        uint32_t data[4] = {0};
        ENHTIM_ReadLatchCountFIFO(ENH_TIM0, data, length);
        /* Only for debugging, removed in actual application. */
        APP_PRINT_INFO1("ENH_TIM0 fifo length = %d\r\n", length);
        for (uint8_t i = 0; i < length; i++)
        {
            /* Only for debugging, removed in actual application. */
            APP_PRINT_INFO2("ENH_TIM0 data[%d] = 0x%x\r\n", i, data[i]);
        }

        ENHTIM_ClearINTPendingBit(ENH_TIM0, ENHTIM_INT_LATCH_CNT_FIFO_THD);
        ENHTIM_INTConfig(ENH_TIM0, ENHTIM_INT_LATCH_CNT_FIFO_THD, ENABLE);
    }
}