STM32旋转编码器接口测速(TIM)

该实验用的是最小系统板和面包板,先上接线图: 

为什么选择PA6和PA7口呢,看张图: 

可以看到编码器接口的两个输入TI1FP1和TI2PF2来自定时器的输入捕获的两个通道TIMx_CH1和TIMx_CH2 ,所以在选择引脚时要选择能复用为某定时器通道1和通道2的引脚,可以再参考引脚定义:

PA6和PA7确实可以被复用为定时器TIM3的两个通道TIM3_CH1和TIM3_CH2。于是大致流程就是先配置引脚时钟和定时器时钟,初始化引脚和时基单元,注意配置时基单元时计数模式的配置是不起作用的,计数方向是由我们之后使用编码器接口配置的库函数所决定的,接口定时器运行控制使能。再配置输入捕获通道,因为输入捕获通道只有包含极性选择和滤波之前的配置对编码器接口起作用,这里配置时只用先给相关结构体赋默认值,再对少数参数进行修改,但是极性选择这一配置再之后编码器接口的配置里也会涉及到,所以只用配置滤波。配置完输入捕获通道后最后便可以用库函数配置编码器接口了:

Encode.c:

#include "stm32f10x.h"                  // Device header
int16_t Compar=0;
void Encode_Init()
{
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
		GPIO_InitTypeDef GPIO_InitStructure;
		GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
		GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7;
		GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
		GPIO_Init(GPIOA,&GPIO_InitStructure);
	
		TIM_TimeBaseInitTypeDef TIM_InitStructure;
		TIM_InitStructure.TIM_ClockDivision=TIM_CKD_DIV2;
		TIM_InitStructure.TIM_CounterMode=TIM_CounterMode_Up;
		TIM_InitStructure.TIM_Period=65536-1;
		TIM_InitStructure.TIM_Prescaler=1-1;
		TIM_InitStructure.TIM_RepetitionCounter=0;
		TIM_TimeBaseInit(TIM3,&TIM_InitStructure);
		
		TIM_ICInitTypeDef TIM_ICInitStructure;
		TIM_ICStructInit(&TIM_ICInitStructure);
		TIM_ICInitStructure.TIM_Channel=TIM_Channel_1;
		TIM_ICInitStructure.TIM_ICFilter=0xF;//采样频率(滤波)
		TIM_ICInit(TIM3,&TIM_ICInitStructure);
		TIM_ICInitStructure.TIM_Channel=TIM_Channel_2;
		TIM_ICInitStructure.TIM_ICFilter=0xF;
		TIM_ICInit(TIM3,&TIM_ICInitStructure);
		TIM_Cmd(TIM3,ENABLE);
		
		TIM_EncoderInterfaceConfig(TIM3,TIM_EncoderMode_TI12,TIM_ICPolarity_Falling,TIM_ICPolarity_Rising);
}
int16_t TIM_EncodeCount()
{
		int16_t tmp=TIM_GetCounter(TIM3);
		TIM_SetCounter(TIM3,0);
		return tmp;
}

编码器如何根据旋转使CNT计次可以参考下图:

 

为了达到 测速的目的,我们还可以使用一个定时器每隔一段时间读取计次,这样就可以测速了,再配置一个定时器:

Timer.c:

#include "stm32f10x.h" // Device header
#include "Encode.h"
void Timer_Init()//TIM2
{
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
		
		TIM_InternalClockConfig(TIM2);//内部时钟模式
		//周期1s
		TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
		TIM_TimeBaseInitStructure.TIM_Prescaler=7200-1;
		TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
		TIM_TimeBaseInitStructure.TIM_Period=10000-1;
		TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV4;
		TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//高级计数器配置
		TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
		TIM_Cmd(TIM2,ENABLE);
		TIM_ClearFlag(TIM2,TIM_FLAG_Update);//配置完会立刻更新中断,要重置标志位
		
		TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//如何中断
	
		NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//NVIC
		NVIC_InitTypeDef NVIC_InitStructure;
		NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn;
		NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
		NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
		NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
		NVIC_Init(&NVIC_InitStructure);
}

主函数和OLED之类的就不写了,以上内容仅供参考,谢谢!

### STM32 HAL库实现编码器模式进行速度测量 在STM32微控制器中,利用HAL库可以通过配置定时器的编码器模式来实现对霍尔编码器或AB相增量式编码器的速度测量。以下是详细的说明和示例代码。 #### 定时器编码器模式简介 STM32中的定时器支持多种工作模式,其中一种是编码器模式。在这种模式下,两个输入通道(通常是TIMx_CH1和TIMx_CH2)分别接收来自编码器A相和B相信号。通过分析这两个信号的变化顺序,可以计算出旋转的方向和角度变化量[^1]。 #### 主要函数及其作用 - **`HAL_TIM_Encoder_Init()`**: 初始化定时器进入编码器模式。 - **`HAL_TIM_Encoder_GetValue()`**: 返回当前编码器的计数值,可用于进一步计算转速或其他参数[^3]。 - **`HAL_TIM_Encoder_Start()`**: 启动编码器模式下的定时器操作。 #### 示例代码 下面是一个简单的例子展示如何设置并使用STM32 HAL库来进行编码器测速: ```c #include "stm32f4xx_hal.h" // 定义全局变量存储时间戳和前一次计数值 uint32_t previous_count = 0; float rpm = 0; void EncoderInit(TIM_HandleTypeDef *htim) { TIM_Encoder_InitTypeDef sConfig = {0}; // 配置定时器为编码器模式 sConfig.EncoderMode = TIM_ENCODERMODE_TI12; // 使用TI1和TI2作为编码器输入 sConfig.IC1Polarity = TIM_ICPOLARITY_RISING; // A相上升沿触发 sConfig.IC2Polarity = TIM_ICPOLARITY_RISING; // B相上升沿触发 sConfig.IC1Prescaler = TIM_ICPSC_DIV1; // 不分频 sConfig.IC2Prescaler = TIM_ICPSC_DIV1; if (HAL_TIM_Encoder_Init(htim, &sConfig) != HAL_OK){ Error_Handler(); // 错误处理程序 } __HAL_TIM_ENABLE(htim); // 开启定时器 } void CalculateSpeed(TIM_HandleTypeDef *htim) { uint32_t current_count = HAL_TIM_Encoder_GetValue(htim); // 计算每秒脉冲数(假设采样间隔固定) float pulses_per_second = ((current_count - previous_count) / elapsed_time_in_seconds); // 转换为RPM(具体取决于编码器分辨率) rpm = (pulses_per_second * 60) / encoder_resolution; previous_count = current_count; // 更新上次计数值 } ``` 上述代码片段展示了初始化过程以及基本的速度计算逻辑[^4]。 #### 注意事项 当采用DMA方式采集数据时,能够显著减轻CPU负载,适合高频应用场合。然而,在实际项目实施过程中需要注意合理分配资源以避免冲突。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值