STM32系列(HAL库) ——定时器编码器/正交解码模式

该文介绍了如何使用Cubemx配置STM32定时器进行正交解码模式设置,以实现电机编码器脉冲检测。通过配置RCC、SYS、串口和定时器的EncoderMode,结合HAL库在keil5中编写代码,实现了计数和判断转动方向的功能。在while(1)循环中,通过HAL库函数读取并打印编码器脉冲数和转动方向。

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

         STM32定时器的正交解码模式多用于检测电机的编码器脉冲数做闭环控制,如PID。本文简单介绍一下定时器在Cubemx如何配置以及程序引用到的API函数。

一、前期准备

1、硬件:

  • STM32C8T6最小系统板
  • USB-TTL串口模块
  • ST-Link下载器

2、软件:

  • keil5-IDE
  • cubeMX 

二、cubeMX配置

1、配置RCC——选着外部时钟源

2、配置SYS—— Serial Wire模式

3、时钟树拉满72M

4、配置串口1          

 5.编码器模式配置

  • 这里配置哪一个定时器都可以,只要在第2步存在 Encoder Mode 选项即可。
  • 第3步Encoder Mode T1 是只计上升沿,Encoder Mode T2是只计下降沿,Encoder Mode T1 and T2 就是2种都计。注意:此处可分别配置2个通道的触发模式,但截图只截到其中一个通道

 

 6.生成工程

        略

三、keil5代码

1、串口配置

        可以参考:STM32系列(HAL库) ——使用串口打印的3种方式,推荐第二种方法。

2、main函数

        ①在while(1)循环前添加初始化

uint16_t Count=0;
uint16_t Diretion=0;
HAL_TIM_Encoder_Start(&htim2, TIM_CHANNEL_ALL);

      ②在whlie(1)循环中打印方向和计数值

 Diretion =  __HAL_TIM_IS_TIM_COUNTING_DOWN(&htim2);     
 Count = __HAL_TIM_GET_COUNTER(&htim2);
 printf("转动方向:%d  脉冲数:%d \r\n",Diretion,Count );
 HAL_delay(500);
  • __HAL_TIM_IS_TIM_COUNTING_DOWN(&htim2):返回 0 或 1 ,代表转动方向
  • __HAL_TIM_GET_COUNTER(&htim2):返回计数脉冲值
  • 如果想看相同时间间隔的脉冲值,可在获得计数后使用 TIM2->CNT=0; 语句将定时器计数值清零。默认情况下定时器会计满65535后变成0

 

关于正交解码,我先解释何为正交解码,,,,其实名字挺高大上的,,,,还是先说编码器吧 看一下我用过的一种编码器 编码器的 线 数 ,是说编码器转一圈输出多少个脉冲,,,如果一个编码器是500线,,,说明这个编码器转一圈对应的信号线会输出500个脉冲,,,,为什么说是对应的,,,对于上面的编码器而言是这样的,,,,但是有的编码器里面有好多线,,,有的信号线是转一圈就输出对应多少线的脉冲,,,有的信号线是转一圈就输出一个脉冲,,,,这就要看编码器的资料了...... 看我上面用过的这个编码器,,使用A,B,VCC,GND这四根线,, 编码器转一圈A信号线会输出500个脉冲,,,,B信号线也会输出500个脉冲,,不过 正转的时候 反转的时候 正转的时候信号线A先输出信号,B信号线后输出 反转的时候信号线B先输出信号,A信号线后输出 假设只是单纯的测正转脉冲或者单纯的测反转脉冲,那么只需要用单片机随意选择一个信号线就行了,,然后就是脉冲计数,,,, 如果说要是一个电机既有正转又有反转,,,,我想知道这个电机绝对正转了多少圈 那么就需要用正转的圈数减去反转的圈数了,,,,,,那么问题来了,,,怎么测正转圈数和反转圈数 其实传统的做法 关于D触发器,,,,当clk引脚来一个上升沿,D引脚是什么电平,,那么Q就输出什么电平,,Q非,,与Q相反 现在如果说电机正转 可以看到每当B来上升沿的时候,A信号总为高电平,,,所以Q会输出高电平 设置A为上升沿进入其,,,中断函数 然后判断一下Q是否为高电平,如果为高电平正转变量自加一 如果电机反转 可以看到每当B来上升沿的时候,A信号总为低电平,,,所以Q会输出低电平 设置B为上升沿进入其,,,中断函数 然后判断一下Q是否为低电平,如果为低电平反转变量自加一 然后 正转变量减去反转变量就能得到电机到底正转了多少圈......这样就会得到一个相对的变量,,这个变量呢,就是单片机正交解码的值 说白了单片机正交解码功能就是得到一个正反转,,,相对的变量,,,,这个变量呢,,你正转的时候他会加,你反转的时候他会减, 不过呢,,,,STM32的这个变量有点坑,,,是太坑了,,,他内部定义的这个变量的类型是无符号整形,,,也就是说0---65535,,,,,,,,,,,,, 如果直接利用STM32正交解码功能,,直接读这个值,,这样呢就会出现很麻烦的问题,,,,
### 配置STM32F1 HALTIM2定时器编码器模式控制电机 #### 初始化项目并配置时钟树 为了确保定时器正常工作,在初始化阶段需正确配置系统时钟。这一步骤通常在`stm32f1xx_hal_conf.h`文件中完成,根据具体需求调整PLL设置。 #### 设置GPIO引脚 对于使用TIM2作为编码器接口的情况,需要指定两个外部输入信号连接到特定的GPIO引脚上。这些引脚应该被配置成浮空输入模式,并映射至TIM2_CH1和TIM2_CH2通道[^1]。 ```c __HAL_RCC_GPIOA_CLK_ENABLE(); // 启用GPIOA时钟 // GPIO结构体定义 static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /*Configure GPIO pin : PA0 (TIM2 CH1) and PA1(TIM2 CH2)*/ GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } ``` #### 编码器模式初始化函数编写 创建一个专门用于初始化TIM2为增量型编码器模式的函数。此过程中涉及到重载默认参数以及调用标准API来进行硬件资源分配。 ```c void Encoder_TIM2_Init(uint16_t PrescalerValue){ TIM_Encoder_InitTypeDef sConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; htim2.Instance = TIM2; // 设定预分频系数 htim2.Init.Prescaler = PrescalerValue - 1U; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 65535; htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim2.Init.RepetitionCounter= 0; if (HAL_TIM_Base_Init(&htim2) != HAL_OK){ Error_Handler(); } sConfig.EncoderMode = TIM_ENCODERMODE_TI12; sConfig.IC1Polarity = TIM_ICPOLARITY_RISING; sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI; sConfig.IC1Prescaler = TIM_ICPSC_DIV1; sConfig.IC1Filter = 0; sConfig.IC2Polarity = TIM_ICPOLARITY_RISING; sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI; sConfig.IC2Prescaler = TIM_ICPSC_DIV1; sConfig.IC2Filter = 0; if (HAL_TIM_Encoder_Init(&htim2,&sConfig)!= HAL_OK){ Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if(HAL_TIMEx_MasterConfigSynchronization(&htim2,&sMasterConfig) != HAL_OK){ Error_Handler(); } } ``` 上述代码片段展示了如何利用HAL提供的API来设定TIM2的工作方式为四倍频AB相正交解码模式,即所谓的“Encoder Mode”。这种模式允许处理器依据来自旋转编码盘或类似设备产生的脉冲序列计算位移量变化情况。 #### 中断服务程序处理逻辑设计 当检测到位移事件发生时,会触发相应的中断请求ISR(Interrupt Service Routine),此时可以在该回调函数内部加入具体的业务流程控制语句,比如更新全局变量记录当前的位置信息等。 ```c void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){ static int8_t last_count=-1; if(htim->Instance==TIM2){ uint16_t current_pos=__HAL_TIM_GET_COUNTER(htim); if(current_pos!=last_count){ printf("Position changed to %d\n",current_pos); last_count=current_pos; // Add your motor control logic here based on position change. } } } ``` 这段C语言源代码实现了每当接收到新的位置数据后就打印出来,并且可以在此基础上进一步扩展实现更复杂的运动控制系统逻辑[^2]。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式创客工坊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值