单片机通用定时器编码器接口实验 单片机 STM32F407开发板DMF407电机开发板平台keil V5.31HSE 为8MHZHSI为16MHZ原理图一、编码器接口一主函数int main(void) { uint8_t i 0; HAL_Init(); /* 初始化HAL库 */ sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */ delay_init(168); /* 延时初始化 */ usart_init(115200); /* 串口初始化为115200 */ led_init(); /* 初始化LED */ gtim_timx_encoder_chy_init(0XFFFF, 0); /* 不分频直接84M的计数频率 */ while (1) { i; if( i % 10 0) { LED0_TOGGLE(); } printf(编码器的计数值为%d\r\n,gtim_get_encode()); delay_ms(10); } }配置#define GTIM_TIMX_ENCODER_CH1_GPIO_PORT GPIOC #define GTIM_TIMX_ENCODER_CH1_GPIO_PIN GPIO_PIN_6 #define GTIM_TIMX_ENCODER_CH1_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOC_CLK_ENABLE(); }while(0) /* PC口时钟使能 */ #define GTIM_TIMX_ENCODER_CH2_GPIO_PORT GPIOC #define GTIM_TIMX_ENCODER_CH2_GPIO_PIN GPIO_PIN_7 #define GTIM_TIMX_ENCODER_CH2_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOC_CLK_ENABLE(); }while(0) /* PC口时钟使能 */ /* TIMX 引脚复用设置 * 因为PC6、PC7默认并不是TIM3的功能脚, 必须开启复用, 才能用作TIM3的编码器功能引脚 */ #define GTIM_TIMX_ENCODERCH1_GPIO_AF GPIO_AF2_TIM3 /* 端口复用到TIM3 */ #define GTIM_TIMX_ENCODERCH2_GPIO_AF GPIO_AF2_TIM3 #define GTIM_TIMX_ENCODER TIM3 /* TIM3 */ #define GTIM_TIMX_ENCODER_INT_IRQn TIM3_IRQn #define GTIM_TIMX_ENCODER_INT_IRQHandler TIM3_IRQHandler #define GTIM_TIMX_ENCODER_CH1 TIM_CHANNEL_1 /* 通道Y, 1 Y 4 */ #define GTIM_TIMX_ENCODER_CH1_CLK_ENABLE() do{ __HAL_RCC_TIM3_CLK_ENABLE(); }while(0) /* TIM3 时钟使能 */ #define GTIM_TIMX_ENCODER_CH2 TIM_CHANNEL_2 /* 通道Y, 1 Y 4 */ #define GTIM_TIMX_ENCODER_CH2_CLK_ENABLE() do{ __HAL_RCC_TIM3_CLK_ENABLE(); }while(0) /* TIM3 时钟使能 */void gtim_timx_encoder_chy_init(uint16_t arr, uint16_t psc) { GPIO_InitTypeDef gpio_init_struct; TIM_Encoder_InitTypeDef g_timx_encoder_chy_handle; GTIM_TIMX_ENCODER_CH1_GPIO_CLK_ENABLE(); /* 开启通道1的IO时钟 */ GTIM_TIMX_ENCODER_CH2_GPIO_CLK_ENABLE(); /* 开启通道2的IO时钟 */ GTIM_TIMX_ENCODER_CH1_CLK_ENABLE(); /* 开启通道1定时器时钟 */ GTIM_TIMX_ENCODER_CH2_CLK_ENABLE(); /* 开启通道2定时器时钟 */ gpio_init_struct.Pin GTIM_TIMX_ENCODER_CH1_GPIO_PIN; /* 通道1的IO口即编码器的A相 */ gpio_init_struct.Mode GPIO_MODE_AF_PP; /* 复用推挽输出 */ gpio_init_struct.Pull GPIO_NOPULL; /* 不上下拉 */ gpio_init_struct.Speed GPIO_SPEED_FREQ_HIGH; /* 高速 */ gpio_init_struct.Alternate GTIM_TIMX_ENCODERCH1_GPIO_AF; /* IO复用把IO作为定时器3功能 */ HAL_GPIO_Init(GTIM_TIMX_ENCODER_CH1_GPIO_PORT, gpio_init_struct); gpio_init_struct.Alternate GTIM_TIMX_ENCODERCH2_GPIO_AF; gpio_init_struct.Pin GTIM_TIMX_ENCODER_CH2_GPIO_PIN; /* 通道2的IO口即编码器的B相 */ HAL_GPIO_Init(GTIM_TIMX_ENCODER_CH2_GPIO_PORT, gpio_init_struct); g_timx_encode_chy_handle.Instance GTIM_TIMX_ENCODER; /* 定时器3 */ g_timx_encode_chy_handle.Init.Prescaler psc; /* 定时器分频 */ g_timx_encode_chy_handle.Init.Period arr; /* 自动重装载值 */ g_timx_encode_chy_handle.Init.ClockDivision TIM_CLOCKDIVISION_DIV1; /* 不分频 */ g_timx_encoder_chy_handle.EncoderMode TIM_ENCODERMODE_TI12; /* TI1,TI2都检测 */ g_timx_encoder_chy_handle.IC1Polarity TIM_ICPOLARITY_RISING; /* 边沿检测器设置非反向 */ g_timx_encoder_chy_handle.IC1Selection TIM_ICSELECTION_DIRECTTI; /* 通道1映射到IC1*/ g_timx_encoder_chy_handle.IC1Prescaler TIM_ICPSC_DIV1; /* 不分频 */ g_timx_encoder_chy_handle.IC1Filter 10; /* 滤波器设置 */ g_timx_encoder_chy_handle.IC2Polarity TIM_ICPOLARITY_RISING; /* 边沿检测器设置非反向 */ g_timx_encoder_chy_handle.IC2Selection TIM_ICSELECTION_DIRECTTI; /* 通道2映射到IC2 */ g_timx_encoder_chy_handle.IC2Prescaler TIM_ICPSC_DIV1; /* 不分频 */ g_timx_encoder_chy_handle.IC2Filter 10; /* 滤波器设置 */ HAL_TIM_Encoder_Init(g_timx_encode_chy_handle, g_timx_encoder_chy_handle); HAL_TIM_Encoder_Start(g_timx_encode_chy_handle,GTIM_TIMX_ENCODER_CH1); /* 开启编码器通道1 */ HAL_TIM_Encoder_Start(g_timx_encode_chy_handle,GTIM_TIMX_ENCODER_CH2); /* 开启编码器通道2 */ HAL_NVIC_SetPriority(GTIM_TIMX_ENCODER_INT_IRQn, 2, 0); /* 抢占优先级2响应优先级0 */ HAL_NVIC_EnableIRQ(GTIM_TIMX_ENCODER_INT_IRQn); /* 开启定时器3中断 */ __HAL_TIM_CLEAR_FLAG(g_timx_encode_chy_handle,TIM_IT_UPDATE); /* 清除更新中断 */ __HAL_TIM_ENABLE_IT(g_timx_encode_chy_handle,TIM_IT_UPDATE); /* 开启更新中断 */ }中断void GTIM_TIMX_ENCODER_INT_IRQHandler(void) { HAL_TIM_IRQHandler(g_timx_encode_chy_handle); } void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(__HAL_TIM_IS_TIM_COUNTING_DOWN(g_timx_encode_chy_handle)) /* 判断CR1的DIR位 */ { g_timx_encode_count--; /* DIR位为1也就是递减计数 */ } else { g_timx_encode_count; /* DIR位为0也就是递增计数 */ } } int32_t gtim_get_encode(void) { /* 计算当前总计数值当前总计数值 计数器当前值 溢出次数*65536 */ return ( int32_t )(__HAL_TIM_GET_COUNTER(g_timx_encode_chy_handle) g_timx_encode_count * 65536); }测试i结果二、编码器接口2主函数int main(void) { uint8_t i 0; HAL_Init(); /* 初始化HAL库 */ sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */ delay_init(168); /* 延时初始化 */ usart_init(115200); /* 串口初始化为115200 */ led_init(); /* 初始化LED */ gtim_timx_encoder_chy_init(0XFFFF, 0); /* 不分频直接84M的计数频率 */ while (1) { i; if( i % 10 0) { LED0_TOGGLE(); } printf(编码器的计数值为%d\r\n,gtim_get_encode()); delay_ms(10); } }配置/* TIMX 编码器接口定义 */ #define GTIM_TIMX_ENCODER_CH1_GPIO_PORT GPIOA #define GTIM_TIMX_ENCODER_CH1_GPIO_PIN GPIO_PIN_15 #define GTIM_TIMX_ENCODER_CH1_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0) /* PA口时钟使能 */ #define GTIM_TIMX_ENCODER_CH2_GPIO_PORT GPIOB #define GTIM_TIMX_ENCODER_CH2_GPIO_PIN GPIO_PIN_3 #define GTIM_TIMX_ENCODER_CH2_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0) /* PB口时钟使能 */ /* TIMX 引脚复用设置 * 因为PA15、PB3默认并不是TIM2的功能脚, 必须开启复用, 才能用作TIM2的编码器功能引脚 */ #define GTIM_TIMX_ENCODERCH1_GPIO_AF GPIO_AF1_TIM2 /* 端口复用到TIM2 */ #define GTIM_TIMX_ENCODERCH2_GPIO_AF GPIO_AF1_TIM2 #define GTIM_TIMX_ENCODER TIM2 /* TIM2 */ #define GTIM_TIMX_ENCODER_INT_IRQn TIM2_IRQn #define GTIM_TIMX_ENCODER_INT_IRQHandler TIM2_IRQHandler #define GTIM_TIMX_ENCODER_CH1 TIM_CHANNEL_1 /* 通道Y, 1 Y 4 */ #define GTIM_TIMX_ENCODER_CH1_CLK_ENABLE() do{ __HAL_RCC_TIM2_CLK_ENABLE(); }while(0) /* TIM2 时钟使能 */ #define GTIM_TIMX_ENCODER_CH2 TIM_CHANNEL_2 /* 通道Y, 1 Y 4 */ #define GTIM_TIMX_ENCODER_CH2_CLK_ENABLE() do{ __HAL_RCC_TIM2_CLK_ENABLE(); }while(0) /* TIM2 时钟使能 */void gtim_timx_encoder_chy_init(uint16_t arr, uint16_t psc) { GPIO_InitTypeDef gpio_init_struct; TIM_Encoder_InitTypeDef g_timx_encoder_chy_handle; GTIM_TIMX_ENCODER_CH1_GPIO_CLK_ENABLE(); /* 开启通道1的IO时钟 */ GTIM_TIMX_ENCODER_CH2_GPIO_CLK_ENABLE(); /* 开启通道2的IO时钟 */ GTIM_TIMX_ENCODER_CH1_CLK_ENABLE(); /* 开启通道1定时器时钟 */ GTIM_TIMX_ENCODER_CH2_CLK_ENABLE(); /* 开启通道2定时器时钟 */ gpio_init_struct.Pin GTIM_TIMX_ENCODER_CH1_GPIO_PIN; /* 通道1的IO口即编码器的A相 */ gpio_init_struct.Mode GPIO_MODE_AF_PP; /* 复用推挽输出 */ gpio_init_struct.Pull GPIO_NOPULL; /* 不上下拉 */ gpio_init_struct.Speed GPIO_SPEED_FREQ_HIGH; /* 高速 */ gpio_init_struct.Alternate GTIM_TIMX_ENCODERCH1_GPIO_AF; /* IO复用把IO作为定时器2功能 */ HAL_GPIO_Init(GTIM_TIMX_ENCODER_CH1_GPIO_PORT, gpio_init_struct); gpio_init_struct.Alternate GTIM_TIMX_ENCODERCH2_GPIO_AF; gpio_init_struct.Pin GTIM_TIMX_ENCODER_CH2_GPIO_PIN; /* 通道2的IO口即编码器的B相 */ HAL_GPIO_Init(GTIM_TIMX_ENCODER_CH2_GPIO_PORT, gpio_init_struct); g_timx_encode_chy_handle.Instance GTIM_TIMX_ENCODER; /* 定时器2 */ g_timx_encode_chy_handle.Init.Prescaler psc; /* 定时器分频 */ g_timx_encode_chy_handle.Init.Period arr; /* 自动重装载值 */ g_timx_encode_chy_handle.Init.ClockDivision TIM_CLOCKDIVISION_DIV1; /* 不分频 */ g_timx_encoder_chy_handle.EncoderMode TIM_ENCODERMODE_TI12; /* TI1,TI2都检测 */ g_timx_encoder_chy_handle.IC1Polarity TIM_ICPOLARITY_RISING; /* 边沿检测器设置非反向 */ g_timx_encoder_chy_handle.IC1Selection TIM_ICSELECTION_DIRECTTI; /* 通道1映射到IC1*/ g_timx_encoder_chy_handle.IC1Prescaler TIM_ICPSC_DIV1; /* 不分频 */ g_timx_encoder_chy_handle.IC1Filter 10; /* 滤波器设置 */ g_timx_encoder_chy_handle.IC2Polarity TIM_ICPOLARITY_RISING; /* 边沿检测器设置非反向 */ g_timx_encoder_chy_handle.IC2Selection TIM_ICSELECTION_DIRECTTI; /* 通道2映射到IC2 */ g_timx_encoder_chy_handle.IC2Prescaler TIM_ICPSC_DIV1; /* 不分频 */ g_timx_encoder_chy_handle.IC2Filter 10; /* 滤波器设置 */ HAL_TIM_Encoder_Init(g_timx_encode_chy_handle, g_timx_encoder_chy_handle); HAL_TIM_Encoder_Start(g_timx_encode_chy_handle,GTIM_TIMX_ENCODER_CH1); /* 开启编码器通道1 */ HAL_TIM_Encoder_Start(g_timx_encode_chy_handle,GTIM_TIMX_ENCODER_CH2); /* 开启编码器通道2 */ HAL_NVIC_SetPriority(GTIM_TIMX_ENCODER_INT_IRQn, 2, 0); /* 抢占优先级2响应优先级0 */ HAL_NVIC_EnableIRQ(GTIM_TIMX_ENCODER_INT_IRQn); /* 开启定时器2中断 */ __HAL_TIM_CLEAR_FLAG(g_timx_encode_chy_handle,TIM_IT_UPDATE); /* 清除更新中断 */ __HAL_TIM_ENABLE_IT(g_timx_encode_chy_handle,TIM_IT_UPDATE); /* 开启更新中断 */ }中断void GTIM_TIMX_ENCODER_INT_IRQHandler(void) { HAL_TIM_IRQHandler(g_timx_encode_chy_handle); } void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(__HAL_TIM_IS_TIM_COUNTING_DOWN(g_timx_encode_chy_handle)) /* 判断CR1的DIR位 */ { g_timx_encode_count--; /* DIR位为1也就是递减计数 */ } else { g_timx_encode_count; /* DIR位为0也就是递增计数 */ } } int32_t gtim_get_encode(void) { /* 计算当前总计数值当前总计数值 计数器当前值 溢出次数*65536 */ return ( int32_t )(__HAL_TIM_GET_COUNTER(g_timx_encode_chy_handle) g_timx_encode_count * 65536); }测试结果