- 概述
- 示例代码
- include “bsp_encoder.h”
- include
- define RCU_ENCODER_L1 RCU_GPIOA // PA15
- define PORT_ENCODER_L1 GPIOA
- define PIN_ENCODER_L1 GPIO_PIN_15
- define AF_ENCODER_L1 GPIO_AF_1
- define TIMER_CH_ENCODER_L1 TIMER_CH_0
- define RCU_ENCODER_L2 RCU_GPIOB //PB3
- define PORT_ENCODER_L2 GPIOB
- define PIN_ENCODER_L2 GPIO_PIN_3
- define AF_ENCODER_L2 GPIO_AF_1
- define TIMER_CH_ENCODER_L2 TIMER_CH_1
- define TIMER_ENCODER_L TIMER1
- define RCU_TIMER_ENCODER_L RCU_TIMER1
- define RCU_ENCODER_R1 RCU_GPIOB //PB4
- define PORT_ENCODER_R1 GPIOB
- define PIN_ENCODER_R1 GPIO_PIN_4
- define AF_ENCODER_R1 GPIO_AF_2
- define TIMER_CH_ENCODER_R1 TIMER_CH_0
- define RCU_ENCODER_R2 RCU_GPIOB //PB5
- define PORT_ENCODER_R2 GPIOB
- define PIN_ENCODER_R2 GPIO_PIN_5
- define AF_ENCODER_R2 GPIO_AF_2
- define TIMER_CH_ENCODER_R2 TIMER_CH_1
- define RCU_TIMER_ENCODER_R RCU_TIMER2
- define TIMER_ENCODER_R TIMER2
概述
编码器的作用是用来计算电机的转速, 下图清晰的展示了编码器的工作原理. 通过在电机的传动轴上加装一个码盘,电机带动码盘转动, 而发射机与接收器成一对,
- 当光线穿过码盘上的孔的时候,我们假定接收器收到了高电平
- 当光线被阻断的时候,我们认为接收器收到了低电平
这样通过计算单位时间内高电平的次数除以码盘的孔数我们就可以很轻松的计算出电机的转速
我们常用的是霍尔编码器也称AB相编码器,它通过电路信号的变化来获取电机的转速,如果正转,一相输出超前另一相,如果反转一相滞后另一相
通过这样的方式,我们就可以计算电机转动的方向,同时还可以读取电机的转速
我们所用的减速电机是7线的, 减速比是1:50 电机转动50圈输出轴输出1圈, 每圈会产生7个信号.
由于每相都有上升沿和下降沿,所以单相1圈信号数量为 72, 再由于信号是AB相同时产生的, 所以电机转动一圈所产生的实际信号量= 72(上升沿和下降沿)*2(A相和B相)
了解了编码器的原理,接下来我们就使用GD32来获取编码器数据.
原理图
示例代码
实现编码器数据读取开发步骤:
- 选定gpio口, PA15,PB3 TIMER1_CH0,TIMER1_CH1
- 使用GD32定时器编码器模式
define RCU_ENCODER_L1 RCU_GPIOA // PA15
define PORT_ENCODER_L1 GPIOA
define PIN_ENCODER_L1 GPIO_PIN_15
define AF_ENCODER_L1 GPIO_AF_1
define TIMER_CH_ENCODER_L1 TIMER_CH_0
define RCU_ENCODER_L2 RCU_GPIOB //PB3
define PORT_ENCODER_L2 GPIOB
define PIN_ENCODER_L2 GPIO_PIN_3
define AF_ENCODER_L2 GPIO_AF_1
define TIMER_CH_ENCODER_L2 TIMER_CH_1
define TIMER_ENCODER_L TIMER1
define RCU_TIMER_ENCODER_L RCU_TIMER1
define RCU_ENCODER_R1 RCU_GPIOB //PB4
define PORT_ENCODER_R1 GPIOB
define PIN_ENCODER_R1 GPIO_PIN_4
define AF_ENCODER_R1 GPIO_AF_2
define TIMER_CH_ENCODER_R1 TIMER_CH_0
define RCU_ENCODER_R2 RCU_GPIOB //PB5
define PORT_ENCODER_R2 GPIOB
define PIN_ENCODER_R2 GPIO_PIN_5
define AF_ENCODER_R2 GPIO_AF_2
define TIMER_CH_ENCODER_R2 TIMER_CH_1
define RCU_TIMER_ENCODER_R RCU_TIMER2
define TIMER_ENCODER_R TIMER2
void bsp_encoder_gpio_left_init(){ // 开启时钟线 rcu_periph_clock_enable(RCU_ENCODER_L1); rcu_periph_clock_enable(RCU_ENCODER_L2);
gpio_af_set(PORT_ENCODER_L1,AF_ENCODER_L1,PIN_ENCODER_L1);
gpio_mode_set(PORT_ENCODER_L1,GPIO_MODE_AF,GPIO_PUPD_NONE,PIN_ENCODER_L1);
gpio_af_set(PORT_ENCODER_L2,AF_ENCODER_L2,PIN_ENCODER_L2);
gpio_mode_set(PORT_ENCODER_L2,GPIO_MODE_AF,GPIO_PUPD_NONE,PIN_ENCODER_L2);
}
void bsp_encoder_gpio_right_init(){ // 开启时钟线 rcu_periph_clock_enable(RCU_ENCODER_R1); rcu_periph_clock_enable(RCU_ENCODER_R2);
gpio_mode_set(PORT_ENCODER_R1,GPIO_MODE_AF,GPIO_PUPD_NONE,PIN_ENCODER_R1);
gpio_mode_set(PORT_ENCODER_R2,GPIO_MODE_AF,GPIO_PUPD_NONE,PIN_ENCODER_R2);
gpio_af_set(PORT_ENCODER_R1,AF_ENCODER_R1,PIN_ENCODER_R1);
gpio_af_set(PORT_ENCODER_R2,AF_ENCODER_R2,PIN_ENCODER_R2);
}
void bsp_encoder_timer_left_init(){ rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4); rcu_periph_clock_enable(RCU_TIMER_ENCODER_L);
timer_deinit(TIMER_ENCODER_L);
// 配置定时器参数
timer_parameter_struct timer_parameter;
timer_struct_para_init(&timer_parameter);
timer_parameter.period = 65535;
timer_parameter.prescaler = 0;
timer_init(TIMER_ENCODER_L,&timer_parameter);
// 配置定时器输入
timer_ic_parameter_struct timer_ic_parameter;
timer_channel_input_struct_para_init(&timer_ic_parameter);
timer_ic_parameter.icfilter = 10;
timer_input_capture_config(TIMER_ENCODER_L,TIMER_CH_ENCODER_L1,&timer_ic_parameter);
timer_input_capture_config(TIMER_ENCODER_L,TIMER_CH_ENCODER_L2,&timer_ic_parameter);
timer_quadrature_decoder_mode_config(TIMER_ENCODER_L,TIMER_QUAD_DECODER_MODE2,TIMER_IC_POLARITY_FALLING,TIMER_IC_POLARITY_FALLING);
timer_counter_value_config(TIMER_ENCODER_L,0);
timer_auto_reload_shadow_enable(TIMER_ENCODER_L);
timer_enable(TIMER_ENCODER_L);
}
void bsp_encoder_timer_right_init(){ rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4); rcu_periph_clock_enable(RCU_TIMER_ENCODER_R);
timer_deinit(TIMER_ENCODER_R);
// 配置定时器参数
timer_parameter_struct timer_parameter;
timer_struct_para_init(&timer_parameter);
timer_parameter.period = 65535;
timer_parameter.prescaler = 0;
timer_init(TIMER_ENCODER_R,&timer_parameter);
// 配置定时器输入
timer_ic_parameter_struct timer_ic_parameter;
timer_channel_input_struct_para_init(&timer_ic_parameter);
timer_ic_parameter.icfilter = 10;
timer_input_capture_config(TIMER_ENCODER_R,TIMER_CH_ENCODER_R1,&timer_ic_parameter);
timer_input_capture_config(TIMER_ENCODER_R,TIMER_CH_ENCODER_R2,&timer_ic_parameter);
timer_quadrature_decoder_mode_config(TIMER_ENCODER_R,TIMER_QUAD_DECODER_MODE2,TIMER_IC_POLARITY_FALLING,TIMER_IC_POLARITY_FALLING);
timer_counter_value_config(TIMER_ENCODER_R,0);
timer_auto_reload_shadow_enable(TIMER_ENCODER_R);
timer_enable(TIMER_ENCODER_R);
}
void bsp_encoder_init(void) { bsp_encoder_gpio_left_init(); bsp_encoder_timer_left_init();
bsp_encoder_gpio_right_init();
bsp_encoder_timer_right_init();
}
short bsp_encoder_get_left()
{
short value = (short)timer_counter_read(TIMER_ENCODER_L);
//timer_counter_value_config(TIMER_ENCODER_L, 0);
return value;
}
short bsp_encoder_get_right()
{
short value = (short)timer_counter_read(TIMER_ENCODER_R);
//timer_counter_value_config(TIMER_ENCODER_R, 0);
return value;
}
void bsp_encoder_test(){ bsp_encoder_init();
while(1){
short left = bsp_encoder_get_left();
short right = bsp_encoder_get_right();
printf("left=%d,right=%d\r\n",left,right);
delay_1ms(100);
}
}
<a name="Vgkgm"></a>
### 读编码器
```c
short enc = (short)timer_counter_read(TIMER_RENCODER1);
返回值若为正数,说明电机正转, 反之电机为反转. 这里我们需要定时器的寄存器是16位的,所以刚好是两个字节,那么它的取值范围是-32767到32767之间的整数值。
如果超过了这个范围, 寄存器数据就会溢出,所以为了避免数据溢出,我们每次读完之后,应该将清空寄存器中的数值
timer_counter_value_config(TIMER_RENCODER1, 0);