本帖最后由 RISCVLAR 于 2021-2-24 15:22 编辑
CH32V103应用教程——TIM-编码器模式
编码器,是一种用来测量机械旋转或位移的传感器。这种传感器能够测量机械部件在旋转或直线运动时的位移位置或速度等信息,并将其转换成一系列电信号。定时器可配置成编码器模式,本章教程主要对定时器编码器模式进行基本配置。
1、TIM简介及相关函数介绍 编码器模式是定时器的一个典型应用,可以用来接入编码器的双相输出,核心计数器的计数方向和编码器的转轴方向同步,编码器每输出一个脉冲就会使核心计数器加一或减一。使用编码器的步骤为:将SMS域置为001b(只在TI2边沿计数)、010b(只在TI1边沿计数)或者011b(在TI1和TI2双边沿计数),将编码器接到比较捕获通道1、2的输入端,给重装值寄存器设一个值,这个值可以设的大一点。在编码器模式时,定时器内部的比较捕获寄存器,预分频器,重复计数寄存器等都正常工作。下表表明了计数方向和编码器信号的关系。
2、硬件设计 本章教程将TIM2配置成编码器模式,需要用到PA0(TIM2_CH1)和PA1(TIM2_CH2)两个引脚。这两个引脚与编码器的连接方式如下: - PA0连接编码器的B相输出;
- PA1连接编码器的A相输出;
注意:本章教程所用编码器为增量式旋转编码器。
3、软件设计 本章教程主要进行定时器TIM编码器模式的基本配置,具体程序如下: encoder.h文件 #ifndef __ENCODER_H
#define __ENCODER_H
#include "ch32v10x_conf.h"
void Encoder_Init_TIM2(void);
void TIM2_IRQHandler(void);
#endif
encoder.h文件主要进行函数的声明; encoder.c文件
#include "encoder.h"
void TIM2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
//TIM编码器模式配置函数
void Encoder_Init_TIM2(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
//使能相应时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //使能AFIO复用功能模块时钟
//GPIO初始化配置 TIM2_CH1(PA0) TIM2_CH2(PA1)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
//定时器初始化配置
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = 0xFFFF; //计数器自动重装载值
TIM_TimeBaseStructure.TIM_Prescaler = 1; //预分频器值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; //重复计数器值
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //初始化结构体
TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising); //使用编码器模式3
//输入捕获配置
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1|TIM_Channel_2;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //输入捕获极性设置,可用于配置编码器正反相
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //输入捕获预分频器设置
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //输入捕获通道选择,编码器模式需选用此配置
TIM_ICInitStructure.TIM_ICFilter = 10; //输入捕获滤波器设置
TIM_ICInit(TIM2, &TIM_ICInitStructure);
TIM_ClearFlag(TIM2, TIM_FLAG_Update); //清除TIM更新标志位
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //使能开启TIM中断
//Reset counter
TIM_SetCounter(TIM2,0);
TIM_Cmd(TIM2, ENABLE);
}
//中断服务函数
void TIM2_IRQHandler(void)
{
if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET) //是否产生更新(溢出)中断
{
TIM_ClearITPendingBit(TIM2,TIM_IT_Update); //清空TIM5中断标志位
}
}
encoder.c文件主要进行定时器的编码器模式配置,与应用教程第九章输入捕获类似。 main.c文件 int main(void)
{
Delay_Init();
USART_Printf_Init(115200);
Encoder_Init_TIM2();
printf("SystemClk:%d\r\n",SystemCoreClock);
printf("This is encoder example\r\n");
while(1)
{
enc = TIM_GetCounter(TIM2);
TIM_SetCounter(TIM2,0);
printf("enc = %d\r\n", enc);
Delay_Ms(500);
}
}
main.c文件主要进行函数初始化以及计数器值的打印输出。
4、下载验证 将编译好的程序下载到开发板并复位,转动编码器,串口打印如下(其中正负代表方向): 正转: 反转:
|