STM32CubeMX笔记(10)--定时器TIM4的Encoder Mode(编码器模式)使用


1、编码器相关知识

1.1 相关编码器的知识点:

机器人开发过程中,对于直流电机来说,编码器至关重要,它不仅可以使我们对电极进行精确的速度闭环,位置闭环,还可以通过时间积分,根据运动学关系,获得速度、位置等信息

STM32的定时器有编码器模式,大大的方便我们的开发。使用STM32cubeMX配置工具,使得这个过程变得无比简单

该笔记中使用STM32cubeMX 开发配置编码器,STM32定时器编码器模式(Encoder Mode),使用定时器TIM4编码器模式读取编码器的值,做闭环控制


1.2 STM32相关定时器编码器模式(Encoder Mode)的知识点:

stm32使用手册可以看到如下的配置,和图片。基本上程序也是这样去设置的相关寄存器的。

如果TI1TI2分别接电机的A相B相的话,那么,当电机正转的时候,如下图计数器回想上计数,反转的时候会向下计数,注意了这个向下计数并不会出现负的值,依旧是从(0-ARR)计数。
这种模式的好处:1.上升沿和下降沿都会计数,所以被软件4倍频了。2.当某一相有毛刺的时候,计数器会在硬件上停止计数。

在这里插入图片描述


2、STM32CubeMX引脚设置和代码生成

2.1 相关STM32CubeMX生成代码配置如下:

2.1.1 配置定时器TIM4的编码器模式

  • 1、设置定时器TIM4的Combined Channels的选项为Encoder Mode,编码器模式;
  • 2、设置定时器TIM4相关参数:PSC:0Counter:65535 (设置计数器的值为65535,最大值);

2.1.2 配置定时器TIM4的编码器模式相关参数

  • 1、在参数配置中的Econder Mode中选择Econder Mode TI1 and TI2
  • 2、在TI1、TI2的选项中选择Rising Edge上升沿计数;
  • 3、选择GPIO模式配置,配置定时器两个GPIO引脚模式,全部改成Pull-Up,即上拉模式,主要用于没有外部上拉的编码器读取时,可以确定引脚电平,防止出错;

配置定时器TIM4的编码器模式
在这里插入图片描述

编码器模式配置
在这里插入图片描述
定时器引脚设置上拉模式
在这里插入图片描述


3、编写相关的C函数文件

3.1、相关定时器的Encoder Mode配置函数开启:

1)添加定时器4的通道1和通道2的Encoder Mode开启使能函数,放置于到main.c中的用户代码区
定时器TIM4的Encoder Mode(编码器模式)使用的是TIM4的通道1和通道2;

/* USER CODE BEGIN 2 */
	HAL_TIM_Encoder_Start(&htim4,TIM_CHANNEL_1 | TIM_CHANNEL_2);
/* USER CODE END 2 */

3.2、编码器数据的读取使用

2)编码器数据的读取使用:
在循环中调用 __HAL_TIM_IS_TIM_COUNTING_DOWN 可以获得当前电机的转向 0为正、1为负
在循环中调用 __HAL_TIM_GET_COUNTER 获取计数器的计数值,即编码器的脉冲数

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		int 	Direction = __HAL_TIM_IS_TIM_COUNTING_DOWN(&htim4);   //读取电机转动方向
		int CaptureNumber =	(short)__HAL_TIM_GET_COUNTER(&htim4);	  //读取编码器数据
		__HAL_TIM_GET_COUNTER(&htim4) = 0;							  //计数器值重新置位
		
		UART1_printf_DMA("Direction is %d \r\n",Direction);
		HAL_Delay(10);
		UART1_printf_DMA("CaptureNumber is %d \r\n",CaptureNumber);
		HAL_Delay(500);

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */

以下代码与上面代码片相同,直接使用读取寄存器的值,进行读取编码器数据;

	int CaptureNumber= (short)TIM4 -> CNT; //读取定时器2的计数值
	TIM4 -> CNT=0;                   	   //清零计数
	UART1_printf_DMA("Encoder_TIM is %d \r\n",CaptureNumber);
	HAL_Delay(500);

3.3、使用(short)强制类型转换,编码器数据正负处理

使用(short)强制类型转换,读取编码器数据正负

上面这样传进去要读的定时器,返回的是相关编码器的速度值。但是为什么,会是一个负数呢。计数器只能计数(0-ARR);
注意看上面使用了强制类型转换。把寄存器的值读出来了之后,转换成了short型(2字节,32位系统下),范围为(-32768-32767),此时当我们把计数器的初始值设置为0之后,如果出现反转,它就会从0开始向下计数(0,65535,65534,…)但是经过强制类型转换之后就变成了(0,-1,-2,…)。

short的表示范围(-32768-32767),也就是说当读出来的值为(32767, 32768, 32769,…,65535,65536,65537…)的时候会因为溢出而转换为
(32767,-32768,-32767,…, -1, ,0, , 1)就这样不断地循环下去。所以我们的电机反转的时候读出的数就是反方向的速度值。而不必用65535去减去读出的值再加上负号才可以的到方便观察的值。只需要一个强制类型转换就可以了。


3.4、编码器数据读取函数整理

可以根据下面的代码片改成自己的代码风格

int Read_Encoder(u8 TIMX)
{
   int Encoder_TIM;    
   switch(TIMX)
	 {
	     case 2:   Encoder_TIM = (short)TIM2 -> CNT;   TIM2 -> CNT=0;	 break;
		 case 3:   Encoder_TIM = (short)TIM3 -> CNT;   TIM3 -> CNT=0;	 break;	
		 case 4:   Encoder_TIM = (short)TIM4 -> CNT;   TIM4 -> CNT=0;	 break;	
		 default:  Encoder_TIM = 0;
	 }
		return Encoder_TIM;
}

4、编译工程文件,使用ST-Link烧录,测试定时器TIM4的Encoder Mode(编码器模式)使用

在这里插入图片描述


  • 50
    点赞
  • 352
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
以下是配置 STM32F4 系列的高级定时器 TIM8 编码接口模式的代码示例: ```c #include "stm32f4xx.h" void TIM8_Encoder_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct; TIM_ICInitTypeDef TIM_ICInitStruct; // 使能 TIM8 时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE); // 配置 TIM8_CH1 和 TIM8_CH2 引脚 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP ; GPIO_Init(GPIOC, &GPIO_InitStruct); // 配置引脚复用功能 GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_TIM8); GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_TIM8); // 配置定时器基本参数 TIM_TimeBaseStruct.TIM_Prescaler = 0; TIM_TimeBaseStruct.TIM_Period = 0xFFFF; // 最大计数值为 65535 TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStruct.TIM_ClockDivision = 0; TIM_TimeBaseStruct.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStruct); // 配置编码器模式 TIM_EncoderInterfaceConfig(TIM8, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising); // 配置输入捕获通道 TIM_ICInitStruct.TIM_Channel = TIM_Channel_1; TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising; TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStruct.TIM_ICFilter = 0; TIM_ICInit(TIM8, &TIM_ICInitStruct); TIM_ICInitStruct.TIM_Channel = TIM_Channel_2; TIM_ICInit(TIM8, &TIM_ICInitStruct); // 启动定时器 TIM_Cmd(TIM8, ENABLE); } ``` 上述代码中,首先使能了 TIM8 的时钟,并配置了 TIM8_CH1 和 TIM8_CH2 的引脚。然后,配置了定时器的基本参数和编码器模式,并初始化了输入捕获通道。最后,启动了定时器。 在使用这段代码之前,请确保已经正确配置了相关的引脚和时钟。此外,还需根据实际需求进行必要的修改和补充。 希望对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值