网站建设辶金手指排名十五,php网站开发 在本地修改 服务器源文件同步,杭州app外包公司排名,视频号推广平台STM32之增量式编码器电机测速 编码器编码器种类按监测原理分类光电编码器霍尔编码器 按输出信号分类增量式编码器绝对式编码器 编码器参数分辨率精度最大响应频率信号输出形式 编码器倍频 STM32的编码器模式编码器模式编码器的计数方向仅在TI1计数电机正转#xff0c;向上计数… STM32之增量式编码器电机测速 编码器编码器种类按监测原理分类光电编码器霍尔编码器 按输出信号分类增量式编码器绝对式编码器 编码器参数分辨率精度最大响应频率信号输出形式 编码器倍频 STM32的编码器模式编码器模式编码器的计数方向仅在TI1计数电机正转向上计数。电机反转向下计数。 仅在TI2计数在TI1和TI2上均计数电机正转向上计数。电机反转向下计数。 编码器计数实例TI1FP1和TI1FP2极性不反相RisingTI1FP1和TI1FP2极性反相Falling 正交式霍尔传感器测速码盘编码器电机测速模块介绍TB6612FNG电机驱动模块真值表电机控制 JGB37-520编码器电机 接线TB6612FNG模块与STM32板子接线TB6612FNG模块与520电机接线520电机与STM32板子接线 STM32CubeMX相关配置配置SYS配置RCC配置GPIO配置USART1配置定时器2、3、4配置NVIC使用Micro库 文件编写添加文件motor.c添加文件motor.h修改文件usart.c修改文件usart.h修改文件tim.cmain.c文件编写 编码器
编码器是一种用来测量机械旋转或位移的传感器。它能够测量机械部件在旋转或直线运动时的位移位置或速度等信息并将其转换成一系列电信号。 .
编码器种类
按监测原理分类
光电编码器
光电编码器是一种通过光电转换将输出轴上的机械几何位移量转换成脉冲或数字量的传感器。这是目前应用最多的传感器光电编码器是由光源、光码盘和光敏元件组成。
光栅盘是在一定直径的圆板上等分地开通若干个长方形孔。由于光电码盘与电动机同轴电动机旋转时光栅盘与电动机同速旋转经发光二极管等电子元件组成的检测装置检测输出若干脉冲信号通过计算每秒光电编码器输出脉冲的个数就能反映当前电动机的转速。为了判断旋转方向码盘还可提供相位相差90°的两路脉冲信号。 .
霍尔编码器
霍尔编码器是一种通过磁电转换将输出轴上的机械几何位移量转换成脉冲或数字量的传感器。 霍尔编码器是由霍尔码盘磁环和霍尔元件组成。 霍尔码盘是在一定直径的圆板上等分地布置有不同的磁极。霍尔码盘与电动机同轴电动机旋转时霍尔元件检测输出若干脉冲信号为判断转向一般输出两组存在一定相位差的方波信号。 .
按输出信号分类
增量式编码器
增量式编码器也称正交式编码器是将设备运动时的位移信息变成连续的脉冲信号脉冲个数表示位移量的大小。
特点 只有当设备运动时才会输出信号。 一般会输出通道A和通道B 两组信号并且有90° 的相位差1/4个周期同时采集这两组信号就可以计算设备的运动速度和方向。 如下图通道A和通道B的信号的周期相同且相位相差1/4个周期结合两相的信号值 当B相和A相先是都读到高电平1 1再B读到高电平A读到低电平1 0则为顺时针转当B相和A相先是都读到低电平0 0再B读到高电平A读到低电平1 0则为逆时针转除通道A、通道B 以外还会设置一个额外的通道Z 信号表示编码器特定的参考位置 如下图传感器转一圈后Z 轴信号才会输出一个脉冲在Z轴输出时可以通过将AB通道的计数清零实现对码盘绝对位置的计算。 增量式编码器只输出设备的位置变化和运动方向不会输出设备的绝对位置。 .
绝对式编码器
绝对式编码器在总体结构上与增量式比较类似都是由码盘、检测装置和放大整形电路构成但是具体的码盘结构和输出信号含义不同。它是将设备运动时的位移信息通过二进制编码的方式特殊的码盘变成数字量直接输出。
特点 其码盘利用若干透光和不透光的线槽组成一套二进制编码这些二进制码与编码器转轴的每一个不同角度是唯一对应的。 绝对式编码器的码盘上有很多圈线槽被称为码道每一条圈码道内部线槽数量和长度都不同。它们共同组成一套二进制编码一条圈码道对应二进制数的其中一个位通常是码盘最外侧的码道表示最低位最内侧的码道表示最高位。 码道的数量决定了二进制编码的位数一个绝对式编码器有N 条码道则它输出二进制数的总个数是2的N次方个。 读取这些二进制码就能知道设备的绝对位置所以称之为绝对式编码器。 编码方式一般采用自然二进制、格雷码或者BCD 码等。 自然二进制的码盘易于理解但当码盘的制造工艺有误差时在两组信号的临界区域所有码道的值可能不会同时变化或因为所有传感器检测存在微小的时间差导致读到错误的值。比如从000跨越到111理论上应该读到111但如果从内到外的3条码道没有完全对齐可能会读到如001或其它异常值。格雷码的相邻的两个2进制数只有1个位不同码盘可以避免二进制码盘的数据读取异常因为格雷码码盘的相邻两个信号组只会有1位的变化就算制造工艺有误差导致信号读取有偏差最多也只会产生1个偏差相邻信号的偏差.
编码器参数
分辨率
分辨率是指编码器能够分辨的最小单位。
对于增量式编码器其分辨率表示为编码器转轴旋转一圈所产生的脉冲数即脉冲数/转(Pulse Per Revolution或PPR)。码盘上透光线槽的数目其实就等于分辨率也叫多少线。对于绝对式编码器内部码盘所用的位数就是它的分辨率单位是位(bit)具体还分单圈分辨率和多圈分辨率。 .
精度
精度是指编码器每个读数与转轴实际位置间的最大误差通常用角度、角分或角秒来表示。
精度由码盘刻线加工精度、转轴同心度、材料的温度特性、电路的响应时间等各方面因素共同决定。例如有些绝对式编码器参数表里会写±20′′这个就表示编码器输出的读数与转轴实际位置之间存在正负20 角秒的误差。 .
最大响应频率
最大响应频率是指编码器每秒输出的脉冲数单位是Hz。
计算公式最大响应频率 分辨率 * 轴转速 / 60 .
信号输出形式
对于增量式编码器每个通道的信号独立输出输出电路形式通常有集电极开路输出、推挽输出、差分输出等。对于绝对式编码器由于是直接输出几十位的二进制数为了确保传输速率和信号质量一般采用串行输出或总线型输出例如同步串行接口(SSI)、RS485、CANopen或EtherCAT 等也有一部分是并行输出输出电路形式与增量式编码器相同。 .
编码器倍频
增量式编码器输出的脉冲波形一般为占空比50% 的方波通道A 和B 相位差为90°。
如果只使用通道A或通道B计数并且只捕获通道A或通道B的上升沿或下降沿即为1倍频没有倍频。如果只使用通道A或通道B计数并且捕获了通道A或通道B的上升沿和下降沿则编码器转一圈的计数值翻倍实现2倍频。如果既使用通道A计数又使用通道B计数而且都捕获了上升沿和下降沿则实现了4倍频。 如果某个增量式编码器的分辨率为11PPR能分辨的最小角度为0.6°那么经过4倍频后它的分辨率能提高到44PPR能分辨的最小角度为0.15°即编码器进行倍频能提高其精度。 .
STM32的编码器模式
在STM32中高级定时器TIM1、TIM8和通用定时器TIM2、TIM3、TIM4、TIM5都提供编码器接口模式不过该模式是适用于增量式编码器的。 .
编码器模式
模式1计数器仅在TI1的边沿处计数。2倍频模式2计数器仅在TI2的边沿处计数。2倍频模式3计数器既在TI1的边沿处计数又在TI1的边沿处计数。4倍频 .
编码器的计数方向
编码器模式下计数器的计数方向递增计数还是递减计数会根据增量编码器的速度和方向自动进行修改因此其计数值始终表示编码器的位置。计数方向对应于所连传感器的旋转方向。 STM32 的编码器接口在计数的时候并不是单纯采集某一通道信号的上升沿或下降沿而是需要综合另一个通道信号的电平。 . TI1 – 通道A . TI2 – 通道B 仅在TI1计数
电机正转向上计数。
假定电机正转时编码器的通道A的信号比通道B提前1/4个周期也即相位提前90度在通道A的上升沿与下降沿均计数,因为计数的方向代表的电机转动的方向所以在正转的情况下
通道A上升沿通道B为低电平向上计数代表电机正转。通道A下降沿通道B为高电平向上计数代表电机正转。 .
电机反转向下计数。
假定电机反转时编码器的通道A的信号比通道B滞后1/4个周期也即相位滞后90度在通道A的上升沿与下降沿均计数,因为计数的方向代表的电机转动的方向所以在反转的情况下
通道A下降沿通道B为低电平向下计数代表电机反转。通道A上升沿通道B为高电平向下计数代表电机反转。 .
仅在TI2计数
同理与仅在TI1计数不多赘述。 .
在TI1和TI2上均计数
电机正转向上计数。
假定电机正转时编码器的通道A的信号比通道B提前1/4个周期也即相位提前90度在通道A和通道B的上升沿与下降沿均计数,因为计数的方向代表的电机转动的方向所以在正转的情况下
通道A上升沿通道B为低电平向上计数代表电机正转。通道B上升沿通道A为高电平向上计数代表电机正转。通道A下降沿通道B为高电平向上计数代表电机正转。通道B下降沿通道A为高电平向上计数代表电机正转。 .
电机反转向下计数。
假定电机反转时编码器的通道A的信号比通道B滞后1/4个周期也即相位滞后90度在通道A和通道B的上升沿与下降沿均计数,因为计数的方向代表的电机转动的方向所以在反转的情况下
通道A上升沿通道B为高电平向下计数代表电机反转。通道A下降沿通道B为高电平向下计数代表电机反转。通道B上升沿通道A为低电平向下计数代表电机反转。通道B下降沿通道A为高电平向下计数代表电机反转。
编码器计数实例
TI1FP1和TI1FP2极性不反相Rising
电机正转时编码器的通道ATI1的信号超前通道BTI2计数器向上计数。电机反转时编码器的通道ATI1的信号滞后通道BTI2计数器向下计数。 .
TI1FP1和TI1FP2极性反相Falling
极性反相可以改变计数器计数方向。
电机正转时编码器的通道ATI1的信号超前通道BTI2计数器向下计数。电机反转时编码器的通道ATI1的信号滞后通道BTI2计数器向上计数。
正交式霍尔传感器测速码盘编码器电机测速
使用TB6612FNG电机驱动模块来驱动电机控制电机的正转、反转、制动、停止等功能利用STM32的定时器作为编码器模式来获取电机在单位时间内产生的脉冲数来达到电机测速的目的。 .
模块介绍
TB6612FNG电机驱动模块 TB6612FNG是双驱动也就是可以驱动两个电机VM外接12V左右电源GND连接一个即可。 .
真值表
输入输出IN1IN2PWMSTBYO1O2电机状态HighLowHighHighHighLow正转LowHighHighHighLowHigh反转HighHighxHighLowLow刹车LowHighLowHighLowLowHighLowLowHighLowLowLowLowHighHighOFF自由刹车xxxLowOFF待机
x可以是High也可以是Low。刹车电机停止时通过提供电源来将电机锁定在当前位置。这样可以防止电机继续旋转也可以提供一定的力矩来抵消负载。自由刹车将电机锁定在当前位置不允许电机旋转但也不提供额外的电源以保持电机的当前位置。待机该模块不工作。 .
电机控制
如果PWM引脚给予一个高电平那么通过IN1和IN2引脚就能控制电机的四个状态电机旋转时为全速状态。如果PWM引脚给予PWM波有效电平为高电平实测80kHz好用那么可以通过PWM波的占空比大小来控制电机旋转时的速度同样通过IN1和IN2引脚就能控制电机的四个状态。 .
JGB37-520编码器电机 JGB37-520编码器电机AB相增量式霍尔编码器是一款直流减速电机使用的是一款霍尔传感器测速码盘配有 11 线强磁码盘即编码器线数为11ppr减速比为1:30即减速前转速为330rpm。在电机旋转一圈单相输出11个脉冲在四倍频情况下电机旋转一圈输出11 * 30 * 4 1320个计数。 .
接线
TB6612FNG模块与STM32板子接线
PB3 - STBYPB4 - AIN1PB5 - AIN2PA6(定时器3通道1输出PWM波) - PWMA12V左右外接电源 - VM单片机5V或3.3V - VCCGND - GND连接一个即可 .
TB6612FNG模块与520电机接线
M(M1) - AO1M-(M2) - AO2 .
520电机与STM32板子接线
PA0(定时器2通道1编码器模式) - A相PA1(定时器2通道2编码器模式) - B相单片机5V或3.3V - VCCGND - GND .
STM32CubeMX相关配置
配置SYS .
配置RCC .
配置GPIO
PB3引脚配置成输出高电平模式。PB4引脚配置成输出高电平模式。PB5引脚配置成输出高电平模式。 .
配置USART1 .
配置定时器2、3、4
配置定时器2为编码器模式。配置定时器3通道1输出PWM波80kHZ好用。配置定时器4定时1s产生溢出中断。 .
配置定时器2为编码器模式。 . . 配置定时器3通道1输出PWM波80kHZ好用。 . . 配置定时器4定时1s产生溢出中断。 .
配置NVIC
打开定时器4中断和USART1中断。 .
使用Micro库
只要映射了printf用来发送数据去串口都要使用这个库。
.
文件编写
添加文件motor.c
#include gpio.h
#include motor.h#define STBY_pin GPIO_PIN_3#define AIN1_pin GPIO_PIN_4
#define AIN2_pin GPIO_PIN_5#define STBY(x) do{ x ? HAL_GPIO_WritePin(GPIOB, STBY_pin, GPIO_PIN_SET) : HAL_GPIO_WritePin(GPIOB, STBY_pin, GPIO_PIN_RESET); }while(0)#define AIN1(x) do{ x ? HAL_GPIO_WritePin(GPIOB, AIN1_pin, GPIO_PIN_SET) : HAL_GPIO_WritePin(GPIOB, AIN1_pin, GPIO_PIN_RESET); }while(0)
#define AIN2(x) do{ x ? HAL_GPIO_WritePin(GPIOB, AIN2_pin, GPIO_PIN_SET) : HAL_GPIO_WritePin(GPIOB, AIN2_pin, GPIO_PIN_RESET); }while(0)void motor_left_forward()
{STBY(1);AIN1(1);AIN2(0);
}void motor_left_back()
{ STBY(1);AIN1(0);AIN2(1);
}void motor_left_stop()
{STBY(1);AIN1(0);AIN2(0);
}
.
添加文件motor.h
void motor_left_forward(void);void motor_left_back(void);void motor_left_stop(void);
.
修改文件usart.c
/* USER CODE BEGIN Header */
/********************************************************************************* file usart.c* brief This file provides code for the configuration* of the USART instances.******************************************************************************* attention** Copyright (c) 2023 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
#include string.h#define USART_REC_LEN 200// 串口接收缓存1字节
uint8_t buf 0;uint8_t UART1_RX_Buffer[USART_REC_LEN]; // 接收缓冲串口接收的数据存放地点// 串口接收状态16位
uint16_t UART1_RX_STA 0;
// bit15 如果是1表示接收完成
// bit14 如果是1表示接收到回车(0x0d)
// bit13~bit0 接收到的有效字节数目/* 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;if (HAL_UART_Init(huart1) ! HAL_OK){Error_Handler();}/* USER CODE BEGIN USART1_Init 2 *//* 开启串口1的接收中断 */HAL_UART_Receive_IT(huart1, buf, 1); /* 每接收一个串口数据调用一次串口接收完成回调函数 */printf(usart1 is ok\r\n);/* USER CODE END USART1_Init 2 */}void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{GPIO_InitTypeDef GPIO_InitStruct {0};if(uartHandle-InstanceUSART1){/* USER CODE BEGIN USART1_MspInit 0 *//* USER CODE END USART1_MspInit 0 *//* 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_InitStruct.Mode GPIO_MODE_AF_PP;GPIO_InitStruct.Speed GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOA, GPIO_InitStruct);GPIO_InitStruct.Pin GPIO_PIN_10;GPIO_InitStruct.Mode GPIO_MODE_INPUT;GPIO_InitStruct.Pull GPIO_NOPULL;HAL_GPIO_Init(GPIOA, GPIO_InitStruct);/* USART1 interrupt Init */HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);HAL_NVIC_EnableIRQ(USART1_IRQn);/* USER CODE BEGIN USART1_MspInit 1 *//* USER CODE END USART1_MspInit 1 */}
}void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{if(uartHandle-InstanceUSART1){/* 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);/* USART1 interrupt Deinit */HAL_NVIC_DisableIRQ(USART1_IRQn);/* USER CODE BEGIN USART1_MspDeInit 1 *//* USER CODE END USART1_MspDeInit 1 */}
}/* USER CODE BEGIN 1 *//* 重写stdio.h文件中的prinft()里的fputc()函数 */
int fputc(int my_data, FILE *p)
{unsigned char temp my_data;// 改写后使用printf()函数会将数据通过串口一发送出去HAL_UART_Transmit(huart1, temp, 1, 0xffff); // 0xfffff为最大超时时间return my_data;
}/* 串口接收完成回调函数 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{// 判断中断是哪个串口触发的if (huart-Instance USART1){// 判断接收是否完成即判断UART1_RX_STA的bit15是否为1if (!(UART1_RX_STA 0x8000)){ // 如果没接收完成就进入接收流程// 判断是否接收到回车0x0dif (UART1_RX_STA 0x4000){// 判断是否接收到换行0x0aif (buf 0x0a){// 如果回车和换行都接收到了则表示接收完成,即把bit15拉高UART1_RX_STA | 0x8000;}else{ // 如果接收到回车0x0d没有接收到换行0x0a// 则认为接收错误重新开始接收UART1_RX_STA 0;}}else{ // 如果没有接收到回车0x0d// 则判断收到的这个字符是否是回车0x0dif (buf 0x0d){// 如果这个字符是回车则将将bit14拉高表示接收到回车UART1_RX_STA | 0x4000;}else{ // 如果不是回车// 则将这个字符存放到缓存数组中UART1_RX_Buffer[UART1_RX_STA 0x3ffff] buf;UART1_RX_STA;// 如果接收数据大于UART1_REC_LEN200字节则重新开始接收if (UART1_RX_STA USART_REC_LEN - 1){UART1_RX_STA 0;}}}}// 如果接收完成则重新开启串口1的接收中断HAL_UART_Receive_IT(huart1, buf, 1);}
}/* 对串口接收数据的处理 */
void usart1_receive_data_handle()
{/* 判断判断串口是否接收完成 */if (UART1_RX_STA 0x8000){printf(接收完成\r\n);// 串口接收完数据后对串口数据进行处理if (!strcmp((const char *)UART1_RX_Buffer, haozige)){printf(浩子哥\r\n);}// 接收到其他数据进行报错else{printf(%s\r\n, 输入错误请重新输入);}// 换行重新开始下一次接收memset(UART1_RX_Buffer, 0, USART_REC_LEN);UART1_RX_STA 0;}
}/* USER CODE END 1 */
.
修改文件usart.h
.
/* USER CODE BEGIN Header */
/********************************************************************************* file usart.h* brief This file contains all the function prototypes for* the usart.c file******************************************************************************* attention** Copyright (c) 2023 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 */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USART_H__
#define __USART_H__#ifdef __cplusplus
extern C {
#endif/* Includes ------------------------------------------------------------------*/
#include main.h/* USER CODE BEGIN Includes *//* USER CODE END Includes */extern UART_HandleTypeDef huart1;/* USER CODE BEGIN Private defines *//* USER CODE END Private defines */void MX_USART1_UART_Init(void);/* USER CODE BEGIN Prototypes */void usart1_receive_data_handle(void);/* USER CODE END Prototypes */#ifdef __cplusplus
}
#endif#endif /* __USART_H__ */
修改文件tim.c
/* USER CODE BEGIN Header */
/********************************************************************************* file tim.c* brief This file provides code for the configuration* of the TIM instances.******************************************************************************* attention** Copyright (c) 2023 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 htim2;
TIM_HandleTypeDef htim3;
TIM_HandleTypeDef htim4;/* TIM2 init function */
void MX_TIM2_Init(void)
{/* USER CODE BEGIN TIM2_Init 0 *///编码器/* USER CODE END TIM2_Init 0 */TIM_Encoder_InitTypeDef sConfig {0};TIM_MasterConfigTypeDef sMasterConfig {0};/* USER CODE BEGIN TIM2_Init 1 *//* USER CODE END TIM2_Init 1 */htim2.Instance TIM2;htim2.Init.Prescaler 0;htim2.Init.CounterMode TIM_COUNTERMODE_UP;htim2.Init.Period 65535;htim2.Init.ClockDivision TIM_CLOCKDIVISION_DIV1;htim2.Init.AutoReloadPreload TIM_AUTORELOAD_PRELOAD_DISABLE;sConfig.EncoderMode TIM_ENCODERMODE_TI12;sConfig.IC1Polarity TIM_ICPOLARITY_RISING;sConfig.IC1Selection TIM_ICSELECTION_DIRECTTI;sConfig.IC1Prescaler TIM_ICPSC_DIV1;sConfig.IC1Filter 6;sConfig.IC2Polarity TIM_ICPOLARITY_RISING;sConfig.IC2Selection TIM_ICSELECTION_DIRECTTI;sConfig.IC2Prescaler TIM_ICPSC_DIV1;sConfig.IC2Filter 6;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();}/* USER CODE BEGIN TIM2_Init 2 */__HAL_TIM_SetCounter(htim2,0); //设置定时器2的计数值为0__HAL_TIM_ENABLE(htim2); //使能定时器2HAL_TIM_Encoder_Start(htim2,TIM_CHANNEL_ALL); //开启TIM2的编码器模式/* USER CODE END TIM2_Init 2 */}
/* TIM3 init function */
void MX_TIM3_Init(void)
{/* USER CODE BEGIN TIM3_Init 0 *///输出PWM/* USER CODE END TIM3_Init 0 */TIM_ClockConfigTypeDef sClockSourceConfig {0};TIM_MasterConfigTypeDef sMasterConfig {0};TIM_OC_InitTypeDef sConfigOC {0};/* USER CODE BEGIN TIM3_Init 1 *//* USER CODE END TIM3_Init 1 */htim3.Instance TIM3;htim3.Init.Prescaler 8;htim3.Init.CounterMode TIM_COUNTERMODE_UP;htim3.Init.Period 99;htim3.Init.ClockDivision TIM_CLOCKDIVISION_DIV1;htim3.Init.AutoReloadPreload TIM_AUTORELOAD_PRELOAD_ENABLE;if (HAL_TIM_Base_Init(htim3) ! HAL_OK){Error_Handler();}sClockSourceConfig.ClockSource TIM_CLOCKSOURCE_INTERNAL;if (HAL_TIM_ConfigClockSource(htim3, sClockSourceConfig) ! HAL_OK){Error_Handler();}if (HAL_TIM_PWM_Init(htim3) ! HAL_OK){Error_Handler();}sMasterConfig.MasterOutputTrigger TIM_TRGO_RESET;sMasterConfig.MasterSlaveMode TIM_MASTERSLAVEMODE_DISABLE;if (HAL_TIMEx_MasterConfigSynchronization(htim3, sMasterConfig) ! HAL_OK){Error_Handler();}sConfigOC.OCMode TIM_OCMODE_PWM1;sConfigOC.Pulse 0;sConfigOC.OCPolarity TIM_OCPOLARITY_HIGH;sConfigOC.OCFastMode TIM_OCFAST_DISABLE;if (HAL_TIM_PWM_ConfigChannel(htim3, sConfigOC, TIM_CHANNEL_1) ! HAL_OK){Error_Handler();}/* USER CODE BEGIN TIM3_Init 2 */HAL_TIM_PWM_Start(htim3, TIM_CHANNEL_1); 开启定时器3的通道1的PWM/* USER CODE END TIM3_Init 2 */HAL_TIM_MspPostInit(htim3);}
/* TIM4 init function */
void MX_TIM4_Init(void)
{/* USER CODE BEGIN TIM4_Init 0 *///定时1s/* USER CODE END TIM4_Init 0 */TIM_ClockConfigTypeDef sClockSourceConfig {0};TIM_MasterConfigTypeDef sMasterConfig {0};/* USER CODE BEGIN TIM4_Init 1 *//* USER CODE END TIM4_Init 1 */htim4.Instance TIM4;htim4.Init.Prescaler 7199;htim4.Init.CounterMode TIM_COUNTERMODE_UP;htim4.Init.Period 9999;htim4.Init.ClockDivision TIM_CLOCKDIVISION_DIV1;htim4.Init.AutoReloadPreload TIM_AUTORELOAD_PRELOAD_ENABLE;if (HAL_TIM_Base_Init(htim4) ! HAL_OK){Error_Handler();}sClockSourceConfig.ClockSource TIM_CLOCKSOURCE_INTERNAL;if (HAL_TIM_ConfigClockSource(htim4, sClockSourceConfig) ! HAL_OK){Error_Handler();}sMasterConfig.MasterOutputTrigger TIM_TRGO_RESET;sMasterConfig.MasterSlaveMode TIM_MASTERSLAVEMODE_DISABLE;if (HAL_TIMEx_MasterConfigSynchronization(htim4, sMasterConfig) ! HAL_OK){Error_Handler();}/* USER CODE BEGIN TIM4_Init 2 */HAL_TIM_Base_Start_IT(htim4); //启动定时器4并使能中断/* USER CODE END TIM4_Init 2 */}void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef* tim_encoderHandle)
{GPIO_InitTypeDef GPIO_InitStruct {0};if(tim_encoderHandle-InstanceTIM2){/* USER CODE BEGIN TIM2_MspInit 0 *//* USER CODE END TIM2_MspInit 0 *//* TIM2 clock enable */__HAL_RCC_TIM2_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();/**TIM2 GPIO ConfigurationPA0-WKUP ------ TIM2_CH1PA1 ------ TIM2_CH2*/GPIO_InitStruct.Pin GPIO_PIN_0|GPIO_PIN_1;GPIO_InitStruct.Mode GPIO_MODE_INPUT;GPIO_InitStruct.Pull GPIO_PULLUP;HAL_GPIO_Init(GPIOA, GPIO_InitStruct);/* USER CODE BEGIN TIM2_MspInit 1 *//* USER CODE END TIM2_MspInit 1 */}
}void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{if(tim_baseHandle-InstanceTIM3){/* USER CODE BEGIN TIM3_MspInit 0 *//* USER CODE END TIM3_MspInit 0 *//* TIM3 clock enable */__HAL_RCC_TIM3_CLK_ENABLE();/* USER CODE BEGIN TIM3_MspInit 1 *//* USER CODE END TIM3_MspInit 1 */}else if(tim_baseHandle-InstanceTIM4){/* USER CODE BEGIN TIM4_MspInit 0 *//* USER CODE END TIM4_MspInit 0 *//* TIM4 clock enable */__HAL_RCC_TIM4_CLK_ENABLE();/* TIM4 interrupt Init */HAL_NVIC_SetPriority(TIM4_IRQn, 0, 0);HAL_NVIC_EnableIRQ(TIM4_IRQn);/* USER CODE BEGIN TIM4_MspInit 1 *//* USER CODE END TIM4_MspInit 1 */}
}
void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle)
{GPIO_InitTypeDef GPIO_InitStruct {0};if(timHandle-InstanceTIM3){/* USER CODE BEGIN TIM3_MspPostInit 0 *//* USER CODE END TIM3_MspPostInit 0 */__HAL_RCC_GPIOA_CLK_ENABLE();/**TIM3 GPIO ConfigurationPA6 ------ TIM3_CH1*/GPIO_InitStruct.Pin GPIO_PIN_6;GPIO_InitStruct.Mode GPIO_MODE_AF_PP;GPIO_InitStruct.Speed GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOA, GPIO_InitStruct);/* USER CODE BEGIN TIM3_MspPostInit 1 *//* USER CODE END TIM3_MspPostInit 1 */}}void HAL_TIM_Encoder_MspDeInit(TIM_HandleTypeDef* tim_encoderHandle)
{if(tim_encoderHandle-InstanceTIM2){/* USER CODE BEGIN TIM2_MspDeInit 0 *//* USER CODE END TIM2_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_TIM2_CLK_DISABLE();/**TIM2 GPIO ConfigurationPA0-WKUP ------ TIM2_CH1PA1 ------ TIM2_CH2*/HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0|GPIO_PIN_1);/* USER CODE BEGIN TIM2_MspDeInit 1 *//* USER CODE END TIM2_MspDeInit 1 */}
}void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
{if(tim_baseHandle-InstanceTIM3){/* USER CODE BEGIN TIM3_MspDeInit 0 *//* USER CODE END TIM3_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_TIM3_CLK_DISABLE();/* USER CODE BEGIN TIM3_MspDeInit 1 *//* USER CODE END TIM3_MspDeInit 1 */}else if(tim_baseHandle-InstanceTIM4){/* USER CODE BEGIN TIM4_MspDeInit 0 *//* USER CODE END TIM4_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_TIM4_CLK_DISABLE();/* TIM4 interrupt Deinit */HAL_NVIC_DisableIRQ(TIM4_IRQn);/* USER CODE BEGIN TIM4_MspDeInit 1 *//* USER CODE END TIM4_MspDeInit 1 */}
}/* USER CODE BEGIN 1 *//* USER CODE END 1 */
.
main.c文件编写
/* USER CODE BEGIN Header */
/********************************************************************************* file : main.c* brief : Main program body******************************************************************************* attention** Copyright (c) 2023 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 main.h
#include tim.h
#include usart.h
#include gpio.h/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include stdio.h
#include motor.h/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */short encoder; //定义编码值
short pulse; //定义电机实际脉冲值
float speed;/* 获取定时器2计数值 */
short get_left_encoder(void) //使用计数值
{short encoder_cnt;encoder_cnt (short)__HAL_TIM_GetCounter(htim2); //获取定时器2的脉冲值__HAL_TIM_SetCounter(htim2,0); //将定时器2计数值清0return encoder_cnt;
}/* 定时器中断的回调函数 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{// 如果是定时器4产生的中断1s产生一次中断if (htim4.Instance TIM4){encoder get_left_encoder();pulse encoder / 4; //4倍频speed (float)encoder / 1320;printf(encoder: %d\r\n,encoder);printf(pulse: %d\r\n,pulse);printf(speed: %0.2f c/s\r\n,speed);}
}/* USER CODE END 0 *//*** brief The application entry point.* retval int*/
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* 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_TIM2_Init();MX_TIM3_Init();MX_TIM4_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */__HAL_TIM_SetCompare(htim3, TIM_CHANNEL_1, 22); //修改PWM占空比motor_left_back();//motor_left_forward();/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */usart1_receive_data_handle();}/* USER CODE END 3 */
}/*** brief System Clock Configuration* retval None*/
void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct {0};RCC_ClkInitTypeDef RCC_ClkInitStruct {0};/** Initializes the RCC Oscillators according to the specified parameters* in the RCC_OscInitTypeDef structure.*/RCC_OscInitStruct.OscillatorType RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState RCC_HSE_ON;RCC_OscInitStruct.HSEPredivValue RCC_HSE_PREDIV_DIV1;RCC_OscInitStruct.HSIState RCC_HSI_ON;RCC_OscInitStruct.PLL.PLLState RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLMUL RCC_PLL_MUL9;if (HAL_RCC_OscConfig(RCC_OscInitStruct) ! HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses clocks*/RCC_ClkInitStruct.ClockType RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider RCC_HCLK_DIV2;RCC_ClkInitStruct.APB2CLKDivider RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(RCC_ClkInitStruct, FLASH_LATENCY_2) ! HAL_OK){Error_Handler();}
}/* USER CODE BEGIN 4 *//* USER CODE END 4 *//*** brief This function is executed in case of error occurrence.* retval None*/
void Error_Handler(void)
{/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state */__disable_irq();while (1){}/* USER CODE END Error_Handler_Debug */
}#ifdef USE_FULL_ASSERT
/*** brief Reports the name of the source file and the source line number* where the assert_param error has occurred.* param file: pointer to the source file name* param line: assert_param error line source number* retval None*/
void assert_failed(uint8_t *file, uint32_t line)
{/* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,ex: printf(Wrong parameters value: file %s on line %d\r\n, file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */