近日考虑DIY1台STM32版的T12焊台,MCU选来选去选中了STM32F070F6P6(CM0内核,TSSOP20封装,48Mhz,32kFlash,6kRam,内置8Mhz晶振和RTC晶振,网上均价5元左右,性价比很高)。因此本文是基于STM32F070F6P6示范,其它stm32的相应设置基本大同小异。
EC11的电气特性
由上图,我们可以看到出
A相上升沿时,B相高电平为顺时针转动,B相低电平则为逆时针转动
不采用Encoder模式的常规方法就是利用上述特点来编程。
EC11部分电路原理图
EC11_A→PA6
EC11_B→PA7
STM32CubeMX的设置
这里,Encoder的channel2我配置的Falling edge(原先设置的Rising edge)。实际这里channel2设置Rising edge/Falling edge都可以,只影响顺/逆时针转动EC11时输出结果+/-的问题。
解码EC11
本例中,我采用中断法解码EC11,CubeMX中还需在NVIC勾选TIM3的全局中断;
配置完成TIM3的初始化代码如下所示:
/**
* @brief TIM3 Initialization Function
* @param None
* @retval None
*/
static void MX_TIM3_Init(void)
{
/* USER CODE BEGIN TIM3_Init 0 */
/* USER CODE END TIM3_Init 0 */
TIM_Encoder_InitTypeDef sConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
/* USER CODE BEGIN TIM3_Init 1 */
/* USER CODE END TIM3_Init 1 */
htim3.Instance = TIM3;
htim3.Init.Prescaler = 3;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 20;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim3.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 = 1;
sConfig.IC2Polarity = TIM_ICPOLARITY_FALLING; //TIM_ICPOLARITY_RISING
sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
sConfig.IC2Filter = 1;
if (HAL_TIM_Encoder_Init(&htim3, &sConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM3_Init 2 */
/* USER CODE END TIM3_Init 2 */
}
EC11A、B相连接的引脚配置在stm32f0xx_hal_msp.c文件中,TIM3的NVIC代码也在相同代码片段,具体代码如下
/**
* @brief TIM_Encoder MSP Initialization
* This function configures the hardware resources used in this example
* @param htim_encoder: TIM_Encoder handle pointer
* @retval None
*/
void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef* htim_encoder)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(htim_encoder->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspInit 0 */
/* USER CODE END TIM3_MspInit 0 */
/* Peripheral clock enable */
__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_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF1_TIM3;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN TIM3_MspInit 1 */
HAL_NVIC_SetPriority(TIM3_IRQn,0,0);
HAL_NVIC_EnableIRQ(TIM3_IRQn);
/* USER CODE END TIM3_MspInit 1 */
}
}
最后还需开启Encoder,代码为:
HAL_TIM_Encoder_Start(&htim3,TIM_CHANNEL_ALL);
欲使用Encoder中断,还需开启相应中断:
> HAL_TIM_Encoder_Start_IT(&htim3,TIM_CHANNEL_1);//这里TIM_CHANNEL_1/TIM_CHANNEL_ALL均可
回调函数
Encoder中断产生的是Capture compare event ,因此我们在TIM3的初始化代码附近补充callback代码:
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance->CR1==0x01)//顺时针
Rotary=1;
if(htim->Instance->CR1==0x11)//逆时针
Rotary=0;
}
上述htim->Instance->CR1==0x01
是Debug观察得出,Rotary用于标记正反转,也可自行修改成+1/-1的操作。
CubeMx配置Encoder模式驱动EC11测试