HAL——TIM编码器接口

文章介绍了如何使用单片机配合编码器进行位置和速度的检测。通过CubeMX配置编码器模式,选择合适的计数周期和encoderMode,以及设置GPIO模式和InputFilter,可以实现编码器信号的精确捕捉。通过定时中断计算一段时间内的脉冲数,进而计算旋转速度。此外,还讨论了Z相的处理,用于检测零点位置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、预备知识

1.单片机与编码器配合使用:编码器接口可接收增量(正交)编码器的信号,根据编码器旋转产生的正交信号脉冲,自动控制CNT自增或自减,从而指示编码器的位置旋转方向旋转速度。

2.每个高级定时器和通用定时器都只拥有1个编码器接口,两个输入引脚借用了输入捕获的通道1和通道2(CH1和CH2可以左右编码器输入引脚,CH3和CH4不能作为编码器输入引脚)

脉冲个数→位置(检测到一相跳边沿的同时检测另一相电平状态判断旋转方向,如果正转CNT++,如果反转CNT--)

脉冲频率→速度

两相脉冲边沿情况→方向 

                                

3.关于编码器

                                

编码器种类:机械式,光电式,磁场/霍尔式,最终效果均是将电机旋转的状态转化为单片机可以识别的脉冲信号。

编码器接线:两根电源线(输入),两根正交相线(输出),一个固定位置输出脉冲线(0位校准)

4.编码器倍频:只计次单相脉冲的单个边沿为一倍频;计次单相脉冲的双边沿为二倍频,计次双相脉冲的双边沿为四倍频。倍频越高精度越高,且正交信号可以抵抗噪声干扰(A相发生电平变化但B相无变化则认为A相变化是由噪声引起不产生计次)

5.编码器接口电路结构

                       

下面两排是TIM的输入捕获的通道1和通道2

6.编码器三种工作模式:

                ​​​​​​​    ​​​​​​​

7.示例

 

二、CubeMX配置

1.选编码器模式,该模式可以直接读取脉冲数(不用特意设置捕获了,非常方便)

2.具体参数配置:

d4030a46e1108d4c8c36e3d137200270.jpeg

 1)计数周期一般配置为最大值65535,可以disable自动重装

 2)选择的encoderMode是TI1和TI2模式。这种模式下,AB两相的上升沿和下降沿都会计数,所以计数值是实际值的4倍,需要做分频。也就是第一个参数,分频值设为3,实际上是3+1=4分频。

3)还有个地方需要解释一下,Polarity参数设置的是Rising Edge。这个参数的意思是在检测到上升沿的时候就触发encoder捕获AB相的值,而并不是这里设置的是上升沿就只检测AB相的上升沿,下降沿还是同样会计数的。对于T1T2均计次模式下,极性配置用来选择是否反相

如果CNT增减和电机方向不一致可以通过反向设置某一相的极性解决,也可以将AB相线反接

4)Input Filter滤波值是从1-15,看情况设定,是用来滤除一些杂波的。​​​​​​​

5)GPIO模式配置,上拉下拉与外部接口的默认电平保持一致,不确定时可以选择浮空输入,但是在无输入时会受噪声干扰

3.函数配置

在初始化中添加打开定时器的encoder模式:   

HAL_TIM_Encoder_Start(&htim2, TIM_CHANNEL_ALL);

调用下面一句函数设定计数值:

__HAL_TIM_SET_COUNTER(&htim4, 0);

  然后定期调用下面这一句函数就可以获取到encoder编码器的计数值:

enc1 = (uint32_t)(__HAL_TIM_GET_COUNTER(&htim2));//获取定时器的值

可以使用强制类型转换为有符号的int32_t

4.如果有z相的话,额外将CH3打开作为一个中断, 作为脉冲中断触发,找到每一圈的零点位置

        ​​​​​​​        ​​​​​​​        ​​​​​​​      

同时打开中断

        ​​​​​​​        ​​​​​​​        ​​​​​​​        

三、应用层代码编写(测速)

利用定时中断,每隔一定时间(闸门时间t)将CNT数值赋给一个变量后清零,得到t时间内CNT值,并基于该时间计算速度

w=CNT*2π/(4*3*t)

或者在mian函数中利用延时函数(不推荐)

 

 相关函数介绍

//1.定时器3的通道1和通道2的Encoder Mode开启使能函数
HAL_TIM_Encoder_Start(&htim3,TIM_CHANNEL_1 | TIM_CHANNEL_2);
 
//2.返回值当前脉冲计数值,也可对脉冲计数值进行重新置位
int cnt=__HAL_TIM_GET_COUNTER(&htim3);
__HAL_TIM_GET_COUNTER(&htim3)=0;//脉冲计数值清0
 
//3.返回值为bool类型,当计数器向下计数时,返回true,可以用来判断编码器旋转方向
 __HAL_TIM_IS_TIM_COUNTING_DOWN(&htim3);

定义两个全局变量(之所以定义成全局变量,是为了方便后边将这个变量变量在debug模式中添加到watch窗口中查看)

/* USER CODE BEGIN PV */
uint8_t Direction;
uint16_t CaptureNumber;
/* USER CODE END PV */

在main函数中开启编码器模式

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

while(1)循环中不断循环检测当前的脉冲计数值

/* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
    Direction=__HAL_TIM_IS_TIM_COUNTING_DOWN(&htim3); //读取编码器旋转方向
    CaptureNumber=__HAL_TIM_GET_COUNTER(&htim3);   //读取脉冲计数值
  }
  /* USER CODE END 3 */

<think>好的,我需要回答用户关于HAL_TIM_PWM_Stop_DMA函数的作用及用法的问题。首先,我需要查找用户提供的参考资料中的相关信息。用户引用了四个文档,其中引用[3]提到了HAL_TIM_Base_Stop_DMA,引用[2]提到了HAL_TIM_Encoder_Stop_DMA,而引用[1]则提到了HAL_TIM_OC_Stop_DMA。虽然这些函数属于不同的TIM模式(基本定时器、编码器模式、输出比较模式),但它们的命名结构类似,可能具有相似的功能。 HAL_TIM_PWM_Stop_DMA可能属于PWM模式下的DMA停止函数,类似于其他模式中的Stop_DMA函数。根据HAL库的命名惯例,这个函数的作用应该是停止通过DMA传输的PWM信号生成。通常,这类函数会涉及停止DMA请求,并可能关闭定时器的相关通道。 接下来,我需要确认函数的参数。参考其他Stop_DMA函数,例如HAL_TIM_OC_Stop_DMA,其参数通常是定时器句柄和通道号。因此,HAL_TIM_PWM_Stop_DMA可能也需要这两个参数:htimTIM_HandleTypeDef指针)和Channel(uint32_t类型通道标识)。 使用步骤可能包括:初始化PWM并启动DMA传输后,当需要停止时调用该函数。注意事项可能涉及确保DMA配置正确,及时处理状态标志以避免错误。 需要验证这些信息是否符合用户提供的文档中的描述。例如,引用[3]中的HAL_TIM_Base_Stop_DMA用于基本定时器,而用户的问题是关于PWM的,因此需要对应到PWM相关的函数。可能需要引用正确的文档部分,但用户提供的引用中没有直接提到HAL_TIM_PWM_Stop_DMA,可能需要根据相似函数推断。 最终,整理出函数的作用、参数、使用步骤和注意事项,并生成相关问题。</think>### HAL_TIM_PWM_Stop_DMA 函数详解 #### 作用 `HAL_TIM_PWM_Stop_DMA` 用于 **停止通过DMA传输的PWM信号生成**。具体功能包括: 1. 关闭TIM通道的PWM输出; 2. 停止与PWM相关的DMA请求; 3. 释放DMA和定时器资源,避免总线冲突[^3][^1]。 #### 函数原型 ```c HAL_StatusTypeDef HAL_TIM_PWM_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel); ``` - **参数**: - `htim`: TIM定时器句柄(例如`&htim2`),需提前初始化PWM模式; - `Channel`: 定时器通道(例如`TIM_CHANNEL_1`),需与DMA配置匹配。 - **返回值**: - `HAL_OK`: 操作成功; - `HAL_ERROR`: 参数错误或外设状态异常。 #### 使用步骤 1. **配置TIM和DMA** 初始化TIM为PWM模式,并绑定DMA传输(参考`HAL_TIM_PWM_Start_DMA`)。 ```c HAL_TIM_PWM_Start_DMA(&htim2, TIM_CHANNEL_1, (uint32_t*)pwm_data, buffer_length); ``` 2. **停止PWM的DMA传输** 在需要停止时调用该函数: ```c HAL_TIM_PWM_Stop_DMA(&htim2, TIM_CHANNEL_1); ``` 3. **后续处理** - 检查DMA和TIM状态寄存器是否复位; - 若需重新启动,需重新配置DMA缓冲区。 #### 注意事项 - **时序要求**:避免在DMA传输过程中突然停止,可能导致数据不完整; - **资源释放**:调用后需手动释放用户定义的DMA缓冲区内存; - **错误处理**:建议检查返回值,并结合`HAL_TIM_GetState()`确认状态[^4]。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值