Stark_GS · 2022年04月13日

【GD32F310开发板试用】编码器接口的使用

定时器中编码器接口的简介及特点

正交译码器

正交译码器功能使用由 TIMERx_CH0 和 TIMERx_CH1 引脚生成的 CI0 和 CI1 正交信号各自相互作用产生计数值。在每个输入源改变期间,DIR 位被硬件自动改变。输入源可以是只有 CI0,可以只有 CI1,或着可以同时有 TI1 和 TI2,通过设置 SMC=0x01, 0x02 或 0x03 来选择使用哪种模式。计数器计数方向改变的机制如下图. 计数方向与编码器信号之间的关系所示。 正交译码器可以当作一个带有方向选择的外部时钟,这意味着计数器会在 0 和自动加载值之间连续的计数。因此,用户必须在计数器开始计数前配置 TIMERx_CAR 寄存器。

编码器的三种模式,由 TIMERx_SMCFG 寄存器的 SMC[2:0]控制
对应下图,编码器模式0、编码器模式1、编码器模式2

比如 1000 线的编码器
编码器模式0、编码器模式1:编码器旋转一周计数器计数 2000
编码器模式2:编码器旋转一周计数器计数 4000
Snipaste_2022-04-11_22-49-30.png
注意: "-" 意思是"无计数"; "X" 意思是不可能。

在【GD32F310G8-PWM单通道输出】文章中有讲到具有编码器接口的定时器,如下所示。

  • TIMER0、TIMER14、TIMER15、TIMER16 这四个定时器适合做电机控制(带死区插入功能)
  • TIMER0、TIMER1 TIMER2 这三个定时器具有编码器的接口
  • TIMER2、TIMER3 还具有霍尔的接口

关于定时器的其他功能介绍参照【GD32F310开发板试用】PWM 单通道输出

开发环境&参考文档

  • Keil-MDK 5.34
  • Windows10
  • 固件库-GD32F3x0_Firmware_Library_V2.2.0
  • GD32F310xx-数据手册-Rev1.1
  • GD32F3x0-用户手册-Rev2.5
  • GD32F3x0-固件库使用指南-Rev1.2

代码部分

这里我们使用的 96 线编码器,采用编码器模式2

encoder.h 文件

#ifndef _ENCODER_H_
#define _ENCODER_H_

#include "gd32f3x0.h"


void HW_EncoderInit(void);

#endif

encoder.c 文件

#include "encoder.h"




void HW_EncoderInit(void)
{
    timer_parameter_struct Timer_ParamType;
    timer_ic_parameter_struct Timer_IC_ParamType;
    
    rcu_periph_clock_enable(RCU_GPIOA);//启用外设时钟功能
    rcu_periph_clock_enable(RCU_TIMER2);
    
    gpio_af_set(GPIOA,GPIO_AF_1,GPIO_PIN_6);//端口复用为TIMER2_CH0模式
    gpio_af_set(GPIOA,GPIO_AF_1,GPIO_PIN_7);//端口复用为TIMER2_CH1模式
    
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6);

    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_7);

    
    timer_deinit(TIMER2);
    timer_struct_para_init(&Timer_ParamType);
    
    Timer_ParamType.alignedmode = TIMER_COUNTER_EDGE;//配置为边沿对其模式
    Timer_ParamType.clockdivision = TIMER_CKDIV_DIV1;//配置死区时间和采样时钟(DTS)之间的分频系数
    Timer_ParamType.counterdirection = TIMER_COUNTER_UP;//配置计数方向为向上计数
    Timer_ParamType.period = 96*4;//周期
    Timer_ParamType.prescaler = 0;//预分频
    Timer_ParamType.repetitioncounter = 0;
    timer_init(TIMER2,&Timer_ParamType);
    
    timer_channel_input_struct_para_init(&Timer_IC_ParamType);
    
    Timer_IC_ParamType.icfilter = 0x5;//配置滤波器
    Timer_IC_ParamType.icpolarity = TIMER_IC_POLARITY_RISING;
    Timer_IC_ParamType.icselection = TIMER_IC_SELECTION_DIRECTTI;
    Timer_IC_ParamType.icprescaler = TIMER_IC_PSC_DIV1;
    timer_input_capture_config(TIMER2,TIMER_CH_0,&Timer_IC_ParamType);
    timer_input_capture_config(TIMER2,TIMER_CH_1,&Timer_IC_ParamType);

    timer_quadrature_decoder_mode_config(TIMER2,TIMER_ENCODER_MODE2,TIMER_IC_POLARITY_RISING,TIMER_IC_POLARITY_RISING);

    timer_enable(TIMER2);
}

main.c 文件

文件中的其他模块使用请参照前几篇文章

#include "gd32f3x0.h"
#include "systick.h"


#include "gpio.h"
#include "encoder.h"
#include "Printf.h"

uint32_t EncoderValue;
int main(void)
{  
    systick_config();
    HW_GpioInit();
    HW_UsartInit();
    HW_EncoderInit();
    
    while(1)
    {
        /* insert 500 ms delay */
        delay_1ms(100);
        /* toggle the LED */ 
        gpio_bit_toggle(GPIOA,GPIO_PIN_1);
        EncoderValue = timer_counter_read(TIMER2);
        printf("编码器的值:%d",EncoderValue);
    }
}

Snipaste_2022-04-13_22-37-55.png

推荐阅读
关注数
10693
内容数
187
中国高性能通用微控制器领域的领跑者兆易创新GD系列芯片技术专栏。
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息