【GD32F427开发板试用】04-编码器接口的使用
定时器中编码器接口的简介及特点
正交译码器
正交译码器功能使用由 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
注意: "-" 意思是"无计数"; "X" 意思是不可能。
在【GD32F427开发板试用】03-PWM单通道输出文章中有讲到具有编码器接口的定时器,如下所示。
- TIMER0 TIMER7 这两个定时器适合做电机控制(带死区插入功能)
- TIMER0 TIMER7 TIMER1 TIMER2 TIMER3 TIMER4 这六个定时器具有编码器的接口和霍尔的接口
开发环境&参考文档
- Keil-MDK 5.27.1.0
- Windows11
- 固件库-GD32F4xx_Firmware_Library_V3.0.2
- GD32F427xx_Datasheet_Rev1.2
- GD32F4xx_User_Manual_Rev2.7_CN
- GD32F4xx 固件库使用指南_V1.0
代码部分
这里我们使用的 2000 线编码器,采用编码器模式2
encoder.h 文件
#ifndef _ENCODER_H_
#define _ENCODER_H_
#include "gd32f4xx.h"
void Encoder_Init(void);
#endif
encoder.c 文件
#include "encoder.h"
void Encoder_Init(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_2,GPIO_PIN_6);//端口复用为TIMER2_CH0模式
gpio_af_set(GPIOA,GPIO_AF_2,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 = 2000*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 "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>
#include "gpio.h"
#include "uart.h"
#include "encoder.h"
uint32_t EncoderValue;
int main(void)
{
systick_config(); //配置系统时钟
GPIO_Init();
USART_Init();
Encoder_Init();
while(1)
{
gpio_bit_toggle(GPIOC, GPIO_PIN_6); //反转PC6
// delay_1ms(200);
EncoderValue = timer_counter_read(TIMER2);
printf("samples:%d\n",EncoderValue);
}
}
上位机获取角度
这里使用的上位机为 vofa+