这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » 国产MCU » 【CH32F207】使用定时器的捕获功能读取编码器数据

共1条 1/1 1 跳转至

【CH32F207】使用定时器的捕获功能读取编码器数据

高工
2026-04-20 13:54:00     打赏

一:CH32通用定时器知识如下:

这是数量最多、功能最灵活的一类定时器,适用于大部分常见的定时、计数、PWM和输入捕获应用。可用于自动化控制、电源等领域。

包含的定时器: TIM2, TIM3, TIM4,  TIM5,

注意: 通用定时器又可以细分为完全功能的通用定时器和简化功能的通用定时器。

通用定时器类型: (TIM2, TIM3, TIM4,TIM5, )

这些是功能最全的通用定时器。

主要特性:

16位(仅TIM2和TIM5) 自动重装载计数器和预分频器。

支持向上、向下、向上/向下(中心对齐) 三种计数模式。

拥有4个独立的输入捕获/输出比较通道,可以产生4路PWM或进行4路输入捕获。

支持编码器接口,可以直接连接正交编码器。

支持外部时钟模式。

支持定时器同步与链接(一个定时器可以启动另一个定时器)。

每个通道都可以用于:

  输出比较:产生PWM波形、单脉冲输出等。

  输入捕获:测量脉冲宽度、频率等。

  互补输出(部分定时器支持,带有死区控制)。

二:CH32定时器的编码器模式

    编码器模式是定时器的一个典型应用,可以用来接入编码器的双相输出,核心计数器的计数方向和编码器的转轴方向同步,编码器每输出一个脉冲就会使核心计数器加一或减一。使用编码器的步骤为:将 SMS 域置为 001b(只在 TI2 边沿计数)、010b(只在 T11 边沿计数)或者 011b(在T11和TI2双边沿计数),将编码器接到比较捕获通道 1、2 的输入端,设一个重装值计数器的值,这个值可以设的大一点。在编码器模式时,定时器内部的比较捕获寄存器,预分频器,重复计数寄存器等都正常工作。下表表明了计数方向和编码器信号的关系。

下图为:定时器编码器模式的计数方向和编码器信号之间的关系

18-1.png

三:编码器知识分享:

3.1 使用的模块资料

    EC11编码器模块是增量式(正交)编码器,两相正交输出,带按键,旋转 360°可发 20 个周期脉冲,用来测量位置、速度或旋转方向

3.2 参数特性:

旋转 360°输出脉冲数:20个脉冲

最大额定电压:DC5V

最大额定电流:各相导线AB相:0.5mA,公共导线C相:10mA工作

温度范围:-10℃to70℃

3.3 使用说明:

下图为EC11编码器实物图片

18-3.png

实物的原理图如下所示

A:A相脉冲输出端,默认上拉输出高电平

B:B相脉冲输出端,默认上拉输出高电平

C:公共导线,默认接地

S1、S2:编码器按键,S1 引出 SW引脚,默认上拉,按键按下时,导通 S1和 S2 接地输出低电平

编码器旋扭转轴时,A 相和 B 相会输出相位相差 90°的方波,顺时针方向旋转时,A 相先产生脉冲,然后 B相产生脉冲,A 相超前 B相 90°,逆时针方向旋转时,B相先产生脉冲,然后 A 相产生脉冲,B相超前 A 相 90°


18-2.png

3.4 软件编写流程:

    对于编码器旋转产生的正交信号脉冲可以是使用外部中断读取或者使用定时器 TIM 的编码器接口读取实现

    使用外部中断方法会频繁进入中断,消耗掉过多的 MCU资源,建议通过定时器的编码器接口来实现自动计次,可以节约软件资源编码器接口可接收增量式(正交)编码器旋转产生的正交信号脉冲,自动控制CNT自增或自减,从而指示编码器的转过圈数、旋转方向和旋转速度

    用任意单片机选定有编码器接口模式的定时器(基本定时器没有编码器接口模式),AB 相分别使用通道1和通道2(通道3和通道4没有接到编码器接口),编码器按键选取任意 GPIO 脚做普通输入脚

1.选定好使用的定时器 TIM,定时器通道对应的 GPIO 脚与编码器模块 A、B 脚相连

2.选定好 GPO 脚做编码器的按键,该脚与编码器模块 SW 脚相连

3.初始化定时器通道 GPIO 脚和编码器按键 GPIO 脚,都配置为上拉输入模式

4.初始化定时器 TIM,配置 TIM 使用编码器接口模式

5.获取 CNT寄存器的值,判断编码器的转过圈数、旋转方向和旋转速度

6.输出调试信息到串口工具

四:软件代码如下:

4.1 定时器初始化:

void TIM3_Encoder_Init()
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_ICInitTypeDef TIM_ICInitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
    TIM_TimeBaseStructure.TIM_Prescaler = 0x0;
    TIM_TimeBaseStructure.TIM_Period = 80;
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

    TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);

    TIM_ICStructInit(&TIM_ICInitStructure);
    TIM_ICInitStructure.TIM_ICFilter = 10;
    TIM_ICInit(TIM3, &TIM_ICInitStructure);

    NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

    NVIC_Init(&NVIC_InitStructure);

    TIM_ClearFlag(TIM3, TIM_FLAG_Update);
    TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
    TIM_SetCounter(TIM3, 0);
    TIM_Cmd(TIM3, ENABLE);
}

4.2 定时器处理过程:

void TIM3_IRQHandler()
{
    volatile uint16_t tempcnt = TIM3->CNT, temparr = TIM3->ATRLR;
    if (TIM_GetITStatus(TIM3, TIM_IT_Update))
    {
        if (tempcnt < temparr / 2)
        {
            circle += 1;
        }
        else
        {
            circle -= 1;
        }
    }
    TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
}

4.3 通过串口输出当前的编码器采集数据:

        if (precircle != circle || (precnt != TIM3->CNT && TIM3->CNT % 4 == 0))
        {
            printf(" 编码器位置 position= %d circle %d step\r\n", circle, TIM3->CNT);
            if (time != 0)
                printf("编码器 speed= %f\r\n", -(float)(precircle * 80 + precnt - (circle * 80 + TIM3->CNT)) / (float)time * 1000.0/(float)SpeedSampleTimeMs / 80.0);
            else
                printf("编码器 speed null!!\r\n");
            time = 0;
            precircle = circle;
            precnt = TIM3->CNT;
        }
        time++;
        Delay_Ms(SpeedSampleTimeMs);

五:软件接收如图

18-4.png




关键词: 捕获     定时器    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]