当前位置: 首页 > ops >正文

STM32定时器简单采集编码器脉冲

MCU:STM32H723ZGT6

编码器:(欧姆龙)E6B2-CWZ1X;1000P/R;8根线信号线分别为 A+ A- B+ B- Z+ Z- 以及5V和GND;

  • A 脉冲输出 
  • B 脉冲输出 
  • Z 零点信号 当编码器旋转到零点时,Z信号会发出一个脉冲表示现在是零位置 表示编码器转了1圈,可用来记录编码器转了多少圈,从而知道运行距离

采用定时器1的CH1(PE9)接A+和CH2(PE11)接B+;一般是定时器的通道1和2才能作为编码器输入口,对应编码器输出的两相。

串口1TX(PA9)、RX(PA10)打印输出信息;

编码器介绍

正交编码器(又名双通道增量式编码器),用于将线性移位转换为脉冲信号。通过监控脉冲的数目和两个信号的相对相位,用户可以跟踪旋转位置、旋转方向和速度。另外,第三个通道称为索引信号,可用于对位置计数器进行复位,从而确定绝对位置。

原理:增量型编码器通过内部两个光敏接受管将编码器的转向转化为A相和B相脉冲的时序和相位关系。编码器每转还输出一个Z相脉冲以代表零位参考位。

正转时:A相在上升沿时,B相是低电平;B相上升沿时,A相是高电平;A相在下降沿时,B相是高电平;B相下降沿时,A相是低电平;

反转时:B相在上升沿时,A相是低电平;A相上升沿时,B相是高电平;B相在下降沿时,A相是高电平;A相下降沿时,B相是低电平;可见正转和反转两者对应正好相反!

使用定时器编码器接口模式就是将A相和B相的所有跳变沿作为计数器的计数时钟,出现边沿信号时,计数自增(正转)或自减(反转)!

STMCubeMX配置

时钟树

debug

串口usart1

定时器TIM1

MCU代码

tim.c代码:

相关GPIO配置为配置为上拉输入模式

/* USER CODE BEGIN Header */
/********************************************************************************* @file    tim.c* @brief   This file provides code for the configuration*          of the TIM instances.******************************************************************************* @attention** Copyright (c) 2025 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "tim.h"/* USER CODE BEGIN 0 *//* USER CODE END 0 */TIM_HandleTypeDef htim1;/* TIM1 init function */
void MX_TIM1_Init(void)
{/* USER CODE BEGIN TIM1_Init 0 *//* USER CODE END TIM1_Init 0 */TIM_Encoder_InitTypeDef sConfig = {0};TIM_MasterConfigTypeDef sMasterConfig = {0};/* USER CODE BEGIN TIM1_Init 1 *//* USER CODE END TIM1_Init 1 */htim1.Instance = TIM1;htim1.Init.Prescaler = 0;htim1.Init.CounterMode = TIM_COUNTERMODE_UP;htim1.Init.Period = 65535;htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;htim1.Init.RepetitionCounter = 0;htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;sConfig.EncoderMode = TIM_ENCODERMODE_TI12;sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;sConfig.IC1Prescaler = TIM_ICPSC_DIV1;sConfig.IC1Filter = 0xF;sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;sConfig.IC2Prescaler = TIM_ICPSC_DIV1;sConfig.IC2Filter = 0xF;if (HAL_TIM_Encoder_Init(&htim1, &sConfig) != HAL_OK){Error_Handler();}sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET;sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK){Error_Handler();}/* USER CODE BEGIN TIM1_Init 2 *//* USER CODE END TIM1_Init 2 */}void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef* tim_encoderHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if(tim_encoderHandle->Instance==TIM1){/* USER CODE BEGIN TIM1_MspInit 0 *//* USER CODE END TIM1_MspInit 0 *//* TIM1 clock enable */__HAL_RCC_TIM1_CLK_ENABLE();__HAL_RCC_GPIOE_CLK_ENABLE();/**TIM1 GPIO ConfigurationPE9     ------> TIM1_CH1PE11     ------> TIM1_CH2*/GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_11;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_PULLUP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);/* USER CODE BEGIN TIM1_MspInit 1 *//* USER CODE END TIM1_MspInit 1 */}
}void HAL_TIM_Encoder_MspDeInit(TIM_HandleTypeDef* tim_encoderHandle)
{if(tim_encoderHandle->Instance==TIM1){/* USER CODE BEGIN TIM1_MspDeInit 0 *//* USER CODE END TIM1_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_TIM1_CLK_DISABLE();/**TIM1 GPIO ConfigurationPE9     ------> TIM1_CH1PE11     ------> TIM1_CH2*/HAL_GPIO_DeInit(GPIOE, GPIO_PIN_9|GPIO_PIN_11);/* USER CODE BEGIN TIM1_MspDeInit 1 *//* USER CODE END TIM1_MspDeInit 1 */}
}/* USER CODE BEGIN 1 */
uint16_t Encoder_Get_CNT(void)
{return __HAL_TIM_GET_COUNTER(&htim1);
}/* USER CODE END 1 */

 新添加的代码

 

 __HAL_TIM_GET_COUNTER函数获取当前的CNT计数值!

/*** @brief  Get the TIM Counter Register value on runtime.* @param  __HANDLE__ TIM handle.* @retval 16-bit or 32-bit value of the timer counter register (TIMx_CNT)*/
#define __HAL_TIM_GET_COUNTER(__HANDLE__)  ((__HANDLE__)->Instance->CNT)

 usart.c代码

/* USER CODE BEGIN Header */
/********************************************************************************* @file    usart.c* @brief   This file provides code for the configuration*          of the USART instances.******************************************************************************* @attention** Copyright (c) 2025 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "usart.h"/* USER CODE BEGIN 0 */
#include "stdio.h"
/* USER CODE END 0 */UART_HandleTypeDef huart1;/* USART1 init function */void MX_USART1_UART_Init(void)
{/* USER CODE BEGIN USART1_Init 0 *//* USER CODE END USART1_Init 0 *//* USER CODE BEGIN USART1_Init 1 *//* USER CODE END USART1_Init 1 */huart1.Instance = USART1;huart1.Init.BaudRate = 115200;huart1.Init.WordLength = UART_WORDLENGTH_8B;huart1.Init.StopBits = UART_STOPBITS_1;huart1.Init.Parity = UART_PARITY_NONE;huart1.Init.Mode = UART_MODE_TX_RX;huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;huart1.Init.OverSampling = UART_OVERSAMPLING_16;huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;if (HAL_UART_Init(&huart1) != HAL_OK){Error_Handler();}if (HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK){Error_Handler();}if (HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK){Error_Handler();}if (HAL_UARTEx_DisableFifoMode(&huart1) != HAL_OK){Error_Handler();}/* USER CODE BEGIN USART1_Init 2 *//* USER CODE END USART1_Init 2 */}void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};if(uartHandle->Instance==USART1){/* USER CODE BEGIN USART1_MspInit 0 *//* USER CODE END USART1_MspInit 0 *//** Initializes the peripherals clock*/PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART1;PeriphClkInitStruct.Usart16ClockSelection = RCC_USART16910CLKSOURCE_D2PCLK2;if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK){Error_Handler();}/* USART1 clock enable */__HAL_RCC_USART1_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();/**USART1 GPIO ConfigurationPA9     ------> USART1_TXPA10     ------> USART1_RX*/GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;GPIO_InitStruct.Alternate = GPIO_AF7_USART1;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);/* USER CODE BEGIN USART1_MspInit 1 *//* USER CODE END USART1_MspInit 1 */}
}void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{if(uartHandle->Instance==USART1){/* USER CODE BEGIN USART1_MspDeInit 0 *//* USER CODE END USART1_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_USART1_CLK_DISABLE();/**USART1 GPIO ConfigurationPA9     ------> USART1_TXPA10     ------> USART1_RX*/HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);/* USER CODE BEGIN USART1_MspDeInit 1 *//* USER CODE END USART1_MspDeInit 1 */}
}/* USER CODE BEGIN 1 */
int fputc(int ch, FILE *f)
{HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);return ch;
}/* USER CODE END 1 */

 添加重定向函数,添加头文件#include "stdio.h"

 勾选微库

 

 main.c代码

int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MPU Configuration--------------------------------------------------------*/MPU_Config();/* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_TIM1_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */printf("Init-ok!\r\n");/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */uint16_t speed = 0;/* 使能编码器接口 */HAL_TIM_Encoder_Start(&htim1, TIM_CHANNEL_ALL);while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */speed = Encoder_Get_CNT();printf("cnt = %d\r\n",speed);HAL_Delay(500);}/* USER CODE END 3 */
}

 串口打印

顺时针旋转计数值增加,逆时针旋转计数值减少!转一圈计数4000!

采用4倍频方式,即分别在A、B相波形的上升沿和下降沿计数,分辨率可以提高4倍!

想只测速,在不分方向的情况下,只需要用单片机随意选择一个信号线就行了,然后定时器边沿触发,检测脉冲计数,然后清零!

定时器编码器模式介绍

表中的TI1FP1信号可类比上文提到的A相,TI2FP2信号可类比B相;上升对应A/B相上升沿、下降对应A/B相的下降沿;

仅在TI1处计数,指在A相的跳变沿进行计数,不考虑B相的跳变沿;仅在TI2处计数,指在B相的跳变沿进行计数,不考虑A相的跳变沿;

在TI1和TI2处均计数,类似上文提到的正转反转的情况!

正转对应递增情况:TI1FP1信号(A相)上升(上升沿)低(B相低电平)、TI1FP1信号(A相)下降(下降沿)高(B相高电平);TI2FP2信号(B相)上升(上升沿)高(A相高电平)、TI2FP2信号(B相)下降(下降沿)低(A相低电平);

类似可分析反转情况!

分析:TI1上升(上升沿),TI2低,递增;TI2上升,TI1高,递增;TI1下降,TI2高,递增;TI2下降,TI1低,递增;可以看到抖动对计数没干扰!类似可分析反向递减的情况!

对应CH1或CH2的极性选择,这里CH1或者CH2某一个选择下降沿就会变成反相,如果两个又都选为FallingEdge,则又变回正常模式(反相的反相)!

http://www.xdnf.cn/news/7684.html

相关文章:

  • 【ubuntu服务器显卡老是坏掉】
  • BGP边界网关协议
  • 9、AI测试辅助-代码Bug分析提示词优化
  • 静态代理有哪些优势
  • 深入理解指针(一)
  • HarmonyOS实战:3秒实现一个自定义轮播图
  • 纯前端实现 导入/导出/模板下载功能
  • 变频器如何通过Profibus DP主站转Modbus RTU/TCP接入到上位机
  • DeepSeek的走红,会不会带动芯片市场新一轮增长?
  • Java中的ImageIo支持webp解析
  • 小白成长之路-Linux磁盘管理(一)
  • 如何管理和优化内核参数
  • [IMX] 07.LCD 显示
  • 【高斯函数】
  • 驱动相关基础
  • leetcode刷题日记——从前序与中序遍历序列构造二叉树
  • MES管理系统电子看板驱动企业智能制造
  • python Numpy-数组
  • 探索nsupdate:动态DNS更新的终极指南
  • 码钉枪行业2025数据分析报告
  • Java程序员从0学AI(二)
  • 使用F5-tts复刻音色
  • ArrayList源码分析
  • 实现商品列表
  • 建站系统哪个好?
  • 基于CATIA参数化圆锥建模的自动化插件开发实践——NX建模之圆锥体命令的参考与移植(二)
  • 笔记:显示实现接口如何实现,作用是什么
  • ollama部署模型
  • 工单派单应用:5 大核心功能提升协作效率
  • Ai学习之LangChain框架