完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
电机编码器测速
编码器(encoder)是将信号(如比特流)或数据进行编制、转换为可用以通讯、传输和存储的信号形式的设备。编码器把角位移或直线位移转换成电信号 编码器分类及原理: 按编码器原理分增量式和绝对式 增量式编码器:增量式编码器是将位移转换成周期性的电信号,再把这个电信号转变成计数脉冲,用脉冲的个数表示位移的大小。 增量式编码器通常有A,B,Z三相,A,B相之间延迟1/4的周期(90度)的脉冲输出,根据延时的关系可以区别正反转。而且通过A,B相的上升沿和下降沿可以进行2倍频和4倍频,用来提高精度,Z相为单圈脉冲,我们的直流有刷电机比较便宜,所以没带Z相,所以我就不解释了。想知道的可以自行了解 绝对式编码器:绝对编码器光码盘上有许多道刻线,每道刻线依次以2线、4线、8线、16线。。。。。。编排,这样, 在编码器的每一个位置,通过读取每道刻线的通、暗,获得一组从2的零次方到2的n-1次方的唯一的2进制编码(格雷码),这就称为n位绝对编码器。 直流有刷电机参数:
编码器是上升沿触发还是下降沿触发,还是双边沿触发,这个后面生成代码再改
```c ```c /* 私有变量 ------------------------------------------------------------------*/ __IO uint16_t time_count=0; // 时间计数,每1ms增加一(与滴答定时器频率有关) __IO int32_t CaptureNumber[4]={0}; // 输入捕获数 #define ENCODER 16 // 编码器线数 #define SPEEDRATIO 30 // 电机减速比 #define PPR (SPEEDRATIO*ENCODER*4) // Pulse/r 每圈可捕获的脉冲数 TIM_HandleTypeDef TIM1_Encoder; TIM_HandleTypeDef TIM2_Encoder; TIM_HandleTypeDef TIM3_Encoder; TIM_HandleTypeDef TIM4_Encoder; float Speed1 = 0; float Speed2 = 0; float Speed3 = 0; float Speed4 = 0; __IO int16_t OverflowCount[4] = {0};//定时器溢出次数 void Encoder_Tim1_Init(void) { TIM_Encoder_InitTypeDef EncoderConfig; TIM_MasterConfigTypeDef sMasterConfig; // __HAL_RCC_TIM1_CLK_ENABLE(); /* 定时器基础配置 */ TIM1_Encoder.Instance = TIM1; TIM1_Encoder.Init.Prescaler = 0;//预分频系数 TIM1_Encoder.Init.CounterMode = TIM_COUNTERMODE_UP;//定时器计数方式 TIM1_Encoder.Init.Period = 0xFFFF;//定时器周期 TIM1_Encoder.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;//时钟分频 TIM1_Encoder.Init.RepetitionCounter = 0;//重复计数器 /* 定时器编码器模式配置 */ EncoderConfig.EncoderMode = TIM_ENCODERMODE_TI12; /* 定时器编码器IC1配置 */ EncoderConfig.IC1Polarity = TIM_ICPOLARITY_RISING; EncoderConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI; EncoderConfig.IC1Prescaler = TIM_ICPSC_DIV1; EncoderConfig.IC1Filter = 0; /* 定时器编码器IC2配置 */ EncoderConfig.IC2Polarity = TIM_ICPOLARITY_RISING; EncoderConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI; EncoderConfig.IC2Prescaler = TIM_ICPSC_DIV1; EncoderConfig.IC2Filter = 0; __HAL_TIM_SET_COUNTER(&TIM1_Encoder,0); /* 初始化编码器接口 */ HAL_TIM_Encoder_Init(&TIM1_Encoder, &EncoderConfig); // __HAL_TIM_CLEAR_IT(&TIM1_Encoder, TIM_IT_UPDATE); //清除更新中断标志位 __HAL_TIM_URS_ENABLE(&TIM1_Encoder); //仅允许计数器溢出才产生更新中断 __HAL_TIM_ENABLE_IT(&TIM1_Encoder,TIM_IT_UPDATE); //使能更新中断 HAL_NVIC_SetPriority(ENCODER_TIM1_IRQn, 1, 3); HAL_NVIC_EnableIRQ(ENCODER_TIM1_IRQn); sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; HAL_TIMEx_MasterConfigSynchronization(&TIM1_Encoder, &sMasterConfig); } void Encoder_Tim2_Init(void) { // __HAL_RCC_TIM2_CLK_ENABLE(); TIM_Encoder_InitTypeDef EncoderConfig; // TIM_MasterConfigTypeDef sMasterConfig; /* 定时器基础配置 */ TIM2_Encoder.Instance = TIM2; TIM2_Encoder.Init.Prescaler = 0; TIM2_Encoder.Init.CounterMode = TIM_COUNTERMODE_UP; TIM2_Encoder.Init.Period = 0xFFFF; /* 定时器编码器模式配置 */ TIM2_Encoder.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; /* 定时器编码器IC1配置 */ EncoderConfig.EncoderMode = TIM_ENCODERMODE_TI12; EncoderConfig.IC1Polarity = TIM_ICPOLARITY_RISING; EncoderConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI; EncoderConfig.IC1Prescaler = TIM_ICPSC_DIV1; EncoderConfig.IC1Filter = 0; /* 定时器编码器IC2配置 */ EncoderConfig.IC2Polarity = TIM_ICPOLARITY_RISING; EncoderConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI; EncoderConfig.IC2Prescaler = TIM_ICPSC_DIV1; EncoderConfig.IC2Filter = 0; __HAL_TIM_SET_COUNTER(&TIM2_Encoder,0); /* 初始化编码器接口 */ HAL_TIM_Encoder_Init(&TIM2_Encoder, &EncoderConfig); // __HAL_TIM_CLEAR_IT(&TIM2_Encoder, TIM_IT_UPDATE); //清除更新中断标志位 __HAL_TIM_URS_ENABLE(&TIM2_Encoder); //仅允许计数器溢出才产生更新中断 __HAL_TIM_ENABLE_IT(&TIM2_Encoder,TIM_IT_UPDATE); //使能更新中断 HAL_NVIC_SetPriority(ENCODER_TIM2_IRQn, 1, 3); HAL_NVIC_EnableIRQ(ENCODER_TIM2_IRQn); } void Encoder_Tim3_Init(void) { // __HAL_RCC_TIM3_CLK_ENABLE(); TIM_Encoder_InitTypeDef EncoderConfig; /* 定时器基础配置 */ TIM3_Encoder.Instance = TIM3; TIM3_Encoder.Init.Prescaler = 0; TIM3_Encoder.Init.CounterMode = TIM_COUNTERMODE_UP; TIM3_Encoder.Init.Period = 0xFFFF; TIM3_Encoder.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; /* 定时器编码器模式配置 */ EncoderConfig.EncoderMode = TIM_ENCODERMODE_TI12; /* 定时器编码器IC1配置 */ EncoderConfig.IC1Polarity = TIM_ICPOLARITY_RISING; EncoderConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI; EncoderConfig.IC1Prescaler = TIM_ICPSC_DIV1; EncoderConfig.IC1Filter = 0; /* 定时器编码器IC2配置 */ EncoderConfig.IC2Polarity = TIM_ICPOLARITY_RISING; EncoderConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI; EncoderConfig.IC2Prescaler = TIM_ICPSC_DIV1; EncoderConfig.IC2Filter = 0; __HAL_TIM_SET_COUNTER(&TIM3_Encoder,0); /* 初始化编码器接口 */ HAL_TIM_Encoder_Init(&TIM3_Encoder, &EncoderConfig); __HAL_TIM_CLEAR_IT(&TIM3_Encoder, TIM_IT_UPDATE); //清除更新中断标志位 __HAL_TIM_URS_ENABLE(&TIM3_Encoder); //仅允许计数器溢出才产生更新中断 __HAL_TIM_ENABLE_IT(&TIM3_Encoder,TIM_IT_UPDATE); //使能更新中断 HAL_NVIC_SetPriority(ENCODER_TIM3_IRQn, 1, 3); HAL_NVIC_EnableIRQ(ENCODER_TIM3_IRQn); } void Encoder_Tim4_Init(void) { // __HAL_RCC_TIM4_CLK_ENABLE(); TIM_Encoder_InitTypeDef EncoderConfig; // TIM_MasterConfigTypeDef sMasterConfig; /* 定时器基础配置 */ /* 定时器基础配置 */ TIM4_Encoder.Instance = TIM4; TIM4_Encoder.Init.Prescaler = 0; TIM4_Encoder.Init.CounterMode = TIM_COUNTERMODE_UP; TIM4_Encoder.Init.Period = 0xFFFF; TIM4_Encoder.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; /* 定时器编码器模式配置 */ EncoderConfig.EncoderMode = TIM_ENCODERMODE_TI12; /* 定时器编码器IC1配置 */ EncoderConfig.IC1Polarity = TIM_ICPOLARITY_RISING; EncoderConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI; EncoderConfig.IC1Prescaler = TIM_ICPSC_DIV1; EncoderConfig.IC1Filter = 0; /* 定时器编码器IC2配置 */ EncoderConfig.IC2Polarity = TIM_ICPOLARITY_RISING; EncoderConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI; EncoderConfig.IC2Prescaler = TIM_ICPSC_DIV1; EncoderConfig.IC2Filter = 0; __HAL_TIM_SET_COUNTER(&TIM4_Encoder,0); /* 初始化编码器接口 */ HAL_TIM_Encoder_Init(&TIM4_Encoder, &EncoderConfig); // __HAL_TIM_CLEAR_IT(&TIM4_Encoder, TIM_IT_UPDATE); //清除更新中断标志位 __HAL_TIM_URS_ENABLE(&TIM4_Encoder); //仅允许计数器溢出才产生更新中断 __HAL_TIM_ENABLE_IT(&TIM4_Encoder,TIM_IT_UPDATE); //使能更新中断 HAL_NVIC_SetPriority(ENCODER_TIM4_IRQn, 1, 3); HAL_NVIC_EnableIRQ(ENCODER_TIM4_IRQn); } /** * 函数功能: 基本定时器硬件初始化配置 * 输入参数: htim_base:基本定时器句柄类型指针 * 返 回 值: 无 * 说 明: 该函数被HAL库内部调用 */ void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef* htim_base) { GPIO_InitTypeDef GPIO_InitStruct ; if(htim_base->Instance == ENCODER_TIM1) { __HAL_RCC_TIM1_CLK_ENABLE(); __HAL_RCC_GPIOE_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /**TIM1 GPIO Configuration PE9 ------> TIM1_CH1 PA9 ------> TIM1_CH2 */ GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Alternate = GPIO_AF1_TIM1; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Alternate = GPIO_AF1_TIM1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } else if(htim_base->Instance == ENCODER_TIM2) { __HAL_RCC_TIM2_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); /**TIM2 GPIO Configuration PA0 ------> TIM2_CH1 PA1 ------> TIM2_CH2 */ GPIO_InitStruct.Pin = GPIO_PIN_0; //PA0 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Alternate = GPIO_AF1_TIM2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_1; //PA1 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Alternate = GPIO_AF1_TIM2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } else if(htim_base->Instance == ENCODER_TIM3) { __HAL_RCC_TIM3_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /**TIM3 GPIO Configuration PA6 ------> TIM3_CH1 PA7 ------> TIM3_CH2 */ GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF2_TIM3; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } else if(htim_base->Instance == ENCODER_TIM4) { __HAL_RCC_TIM4_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); /**TIM4 GPIO Configuration PD12 ------> TIM4_CH1 PD13 ------> TIM4_CH2 */ GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13; //PD12 ,PD13 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Alternate = GPIO_AF2_TIM4; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); } } /** * 函数功能: 基本定时器硬件反初始化配置 * 输入参数: htim_base:基本定时器句柄类型指针 * 返 回 值: 无 * 说 明: 该函数被HAL库内部调用 */ 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 */ /* 基本定时器外设时钟禁用 */ __HAL_RCC_TIM1_CLK_DISABLE(); /**TIM1 GPIO Configuration PE9 ------> TIM1_CH1 PA9 ------> TIM1_CH2 */ HAL_GPIO_DeInit(GPIOE, GPIO_PIN_9); HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9); } else if(tim_encoderHandle->Instance==TIM2) { /* 基本定时器外设时钟禁用 */ __HAL_RCC_TIM2_CLK_DISABLE(); /**TIM2 GPIO Configuration PA5 ------> TIM2_CH1 PB3 ------> TIM2_CH2 */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5); HAL_GPIO_DeInit(GPIOB, GPIO_PIN_3); } else if(tim_encoderHandle->Instance==TIM3) { /* 基本定时器外设时钟禁用 */ __HAL_RCC_TIM3_CLK_DISABLE(); /**TIM2 GPIO Configuration PA6 ------> TIM3_CH1 PA7 ------> TIM3_CH2 */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_6); HAL_GPIO_DeInit(GPIOA, GPIO_PIN_7); } else if(tim_encoderHandle->Instance==TIM4) { /* USER CODE BEGIN TIM4_MspDeInit 0 */ /* USER CODE END TIM4_MspDeInit 0 */ /* 基本定时器外设时钟禁用 */ __HAL_RCC_TIM4_CLK_DISABLE(); /**TIM4 GPIO Configuration PD12 ------> TIM4_CH1 PD13 ------> TIM4_CH2 */ HAL_GPIO_DeInit(GPIOD, GPIO_PIN_12); HAL_GPIO_DeInit(GPIOD, GPIO_PIN_13); } } void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { OSIntEnter(); if(htim == &TIM1_Encoder) { if(__HAL_TIM_IS_TIM_COUNTING_DOWN(htim)) OverflowCount[Encoder_1]--; //向下计数溢出 else OverflowCount[Encoder_1]++; //向上计数溢出 } else if(htim == &TIM2_Encoder) { if(__HAL_TIM_IS_TIM_COUNTING_DOWN(htim)) OverflowCount[Encoder_2]--; //向下计数溢出 else OverflowCount[Encoder_2]++; //向上计数溢出 } else if(htim == &TIM3_Encoder) { if(__HAL_TIM_IS_TIM_COUNTING_DOWN(htim)) OverflowCount[Encoder_3]--; //向下计数溢出 else OverflowCount[Encoder_3]++; //向上计数溢出 } else if(htim == &TIM4_Encoder) { if(__HAL_TIM_IS_TIM_COUNTING_DOWN(htim)) OverflowCount[Encoder_4]--; //向下计数溢出 else OverflowCount[Encoder_4]++; //向上计数溢出 } OSIntExit(); } /************************************************************************** 函数功能:单位时间读取编码器计数 入口参数:定时器 返回 值:速度值 **************************************************************************/ float Read_Encoder(uint16_t TIMX) { int Speed; switch(TIMX) { case 1: CaptureNumber[Encoder_1] = ( int16_t )__HAL_TIM_GET_COUNTER(&TIM1_Encoder)+OverflowCount[Encoder_1]*65535; Speed = (float)CaptureNumber[Encoder_1]/PPR; __HAL_TIM_SET_COUNTER(&TIM1_Encoder,0); break ; case 2: CaptureNumber[Encoder_2] = ( int16_t )__HAL_TIM_GET_COUNTER(&TIM2_Encoder)+OverflowCount[Encoder_2]*65535; Speed = (float)CaptureNumber[Encoder_2]/PPR; __HAL_TIM_SET_COUNTER(&TIM2_Encoder,0); break ; case 3: CaptureNumber[Encoder_3] = ( int16_t )__HAL_TIM_GET_COUNTER(&TIM3_Encoder)+OverflowCount[Encoder_3]*65535; Speed = (float)CaptureNumber[Encoder_3]/PPR; __HAL_TIM_SET_COUNTER(&TIM3_Encoder,0); break ; case 4: CaptureNumber[Encoder_4] = ( int16_t )__HAL_TIM_GET_COUNTER(&TIM4_Encoder)+OverflowCount[Encoder_4]*65535; Speed = (float)CaptureNumber[Encoder_4]/PPR; __HAL_TIM_SET_COUNTER(&TIM4_Encoder,0); break ; } return Speed ; } ```c 在主函数里添加这函数,可以用printf函数打印 int Encoder_A,Encoder_B,Encoder_C,Encoder_D; //编码器的脉冲计数 Encoder_A= Read_Encoder(1); Encoder_A= Read_Encoder(2); Encoder_C= Read_Encoder(3); Encoder_D= Read_Encoder(4); printf("Encoder_A%d",Encoder_A); printf("Encoder_B%d",Encoder_B); printf("Encoder_C%d",Encoder_C); printf("Encoder_D%d",Encoder_D); |
|
|
|
只有小组成员才能发言,加入小组>>
2397 浏览 0 评论
8958 浏览 4 评论
36572 浏览 19 评论
4995 浏览 0 评论
24434 浏览 34 评论
1404浏览 2评论
1657浏览 1评论
2066浏览 1评论
1467浏览 0评论
424浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-30 05:20 , Processed in 1.026247 second(s), Total 46, Slave 41 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号