STM32F407最小系统板HAL库定时器配置编码器模式CNT一直为0,编码器是AB相增量式霍尔编码器
定时器和IO口使用的是TIM3 CH1 CH2, PA6, PA7
编码器初始化:
TIM_HandleTypeDef TIM3_Handler;
TIM_Encoder_InitTypeDef TIM3_Encoder_Handler;
void Encoder_Init(void) {
TIM_Encoder_InitTypeDef sConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
/* USER CODE BEGIN TIM3_Init 1 */
/* USER CODE END TIM3_Init 1 */
TIM3_Handler.Instance = TIM3;
TIM3_Handler.Instance->SMCR &= ~TIM_SMCR_SMS;
TIM3_Handler.Init.Prescaler = 0;
TIM3_Handler.Init.CounterMode = TIM_COUNTERMODE_UP;
TIM3_Handler.Init.Period = 65535;
TIM3_Handler.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
TIM3_Handler.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 = 10;
sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
sConfig.IC2Filter = 10;
if (HAL_TIM_Encoder_Init(&TIM3_Handler, &sConfig) != HAL_OK) {
printf("TIM3 Encoder Init Error!/r/n");
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&TIM3_Handler, &sMasterConfig) != HAL_OK) {
printf("TIM3 Master Config Error!/r/n");
}
// /* 清零计数器 */
__HAL_TIM_SET_COUNTER(&TIM3_Handler, 0);
// /* 清零中断标志位 */
__HAL_TIM_CLEAR_IT(&TIM3_Handler,TIM_IT_UPDATE);
// /* 使能定时器的更新事件中断 */
// __HAL_TIM_ENABLE_IT(&TIM3_Handler,TIM_IT_UPDATE);
// /* 设置更新事件请求源为:计数器溢出 这个地方可能会忘记设置 */
// __HAL_TIM_URS_ENABLE(&TIM3_Handler);
// /* 设置中断优先级 */
// HAL_NVIC_SetPriority(TIM3_IRQn, 1, 0);
// /* 使能定时器中断 */
// HAL_NVIC_EnableIRQ(TIM3_IRQn);
HAL_TIM_Encoder_Start(&TIM3_Handler, TIM_CHANNEL_ALL);
}
void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef *htim) {
if (htim->Instance == TIM3) {
printf("TIM3 Encoder Msp Init\r\n");
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_TIM3_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_Initure.Pin = GPIO_PIN_6 | GPIO_PIN_7;
GPIO_Initure.Mode = GPIO_MODE_AF_PP;
GPIO_Initure.Pull = GPIO_PULLUP;
GPIO_Initure.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_Initure.Alternate = GPIO_AF2_TIM3;
HAL_GPIO_Init(GPIOA, &GPIO_Initure);
// HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0);
// HAL_NVIC_EnableIRQ(TIM3_IRQn);
}
}
主循环代码:
Encoder_Init();
while (1) {
CaptureNumber = ( int16_t )TIM3->CNT;
printf("输入捕获值:%d \r\n", CaptureNumber);
// 4 : 使用定时器编码器接口捕获AB相的上升沿和下降沿,一个脉冲*4.
// 11:编码器线数(转速一圈输出脉冲数)
// 34:电机减数比,内部电机转动圈数与电机输出轴转动圈数比,即减速齿轮比
printf("电机实际转动速度:%0.2f(圈/s)\r\n",(float) CaptureNumber/4/11/34);
TIM3->CNT = 0;
delay_ms(200);
}
网上大部分HAL库的都试过了
能正常读取编码器数据就行
注意两个问题:一个是存在相位差的信号,二是两组方波信号
定时器配置
注:*这种测速的情况必须开启另一个定时器,用来表示在多少时间内测得的脉冲数。例如目前使用TIM1,设为1s进行计数。
STM32Cube MX中进行定时器配置:定时器时钟频率为80MHz。
定时器编码器模式设置
使用TIM3设为编码器模式,可以对两路有相位差(90°或者270°)的方波信号进行脉冲计数和方向位测试。
在主循环开始前
HAL_TIM_Encoder_Start_IT(&htim3,TIM_CHANNEL_ALL);//打开编码器中断
HAL_TIM_Base_Start_IT(&htim1);//开启1S定时中断
__HAL_TIM_ENABLE_IT(&htim3,TIM_IT_UPDATE);//更新中断用于溢出计数
在中断中
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//捕获中断中可以添加自己所需要的标志位
{undefined
if(htim3.Instance->CR1 == 0x01)//顺时针
{}
if(htim3.Instance->CR1 == 0x11)//逆时针
{}
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{undefined
if(TIM1 == htim->Instance)
{undefined
t200 = 1;
}
if(TIM3 == htim->Instance)
{undefined
TIM3UP++;
__HAL_TIM_CLEAR_IT(&htim3,TIM_IT_UPDATE);
if(htim3.Instance->CR1 == 0x01)//顺时针
{undefined
circle_count++;
}
if(htim3.Instance->CR1 == 0x11)//逆时针
{undefined
circle_count–;
}
}
}
在主循环中
if(t200 == 1)
{
t200 = 0;
HAL_TIM_Encoder_Stop(&htim3,TIM_CHANNEL_ALL);
__HAL_TIM_DISABLE_IT(&htim3,TIM_IT_UPDATE);
directuinA = __HAL_TIM_IS_TIM_COUNTING_DOWN(&htim3);//用来获取方向
if(directuinA == 0)//顺时针,会从0开始向上计数,来一个脉冲,增加一个计数
{
CaptureNumberA = TIM3UP * 65535 + __HAL_TIM_GET_COUNTER(&htim3);
}
else if(directuinA == 1)//逆时针,会从65535开始向下计数,来一个脉冲,减去一个计数;TIM3UP 是为了计数溢出所添加的
{
CaptureNumberA = TIM3UP * 65535 - __HAL_TIM_GET_COUNTER(&htim3) + 1;
}
//除以4是由于四倍频的缘故,PULSE_CIRCLE是指一圈有多少脉冲,*60是为了换算成r/min
T_SPEED = (CaptureNumberA / 4.0) / PULSE_CIRCLE * 60;
HAL_TIM_Base_Stop(&htim3);
__HAL_TIM_SET_COUNTER(&htim3,0);
TIM3UP = 0;
HAL_TIM_Base_Start(&htim3);
}
编码器是否是OC(集电极开路)门,接了上拉没有,没有需要接上啦,如果不使用Z信号,需要把外部中断清零的那部分代码去掉