我呢鼓捣了很久 也在网上那个也找了很多资料 原理都讲得透透的但是就没见一个完整的代码 很是难受
我就不废话了直接来干货
1 我用的是AB相增量式编码器 两个线那种 不是ABZ相
2 STM32FI03ZET6自带有编码器模式 可以通过此模式实现测速!
3 测量一个编码器的速度至少要用到2个定时器!!!
如上图 只有CH1与CH2支持编码器接口模式,而外部接的AB两相就相当于一个频率可能改变的外部时钟,我们配置计数器计数是使用内部时钟源计数的 而编码器接口模式AB相产生的方波作为计数器的时钟源。
按照AB相的时钟源来计数 可以设置他的溢出值为65536-1
核心部分:
我们可以配置一个以AB相产生的方波作为时钟源的计数器,然后再额外使能一个定时器中断来读出单位时间内这个计数器的次数(单位时间是指定时中断 eg:5ms就中断一次)就可以依次算出转速了,由此也可得到速度 路程等等
下面贴出我的代码
这是两个编码器测速共用一个中断5ms读取一次计数值
#include "stm32f1.h"
#include "encode.h"
#define Perimter 0.3768;//车轮周长(m)
#define K 32;//n=cnt/k;k=电机线数/减数比*采集时间*齿数比 ;线数=11 正交乘4=44,减数比1:36,采集时间T=5ms=0.005s,齿数比=15:60=>k=44*36*0.005*60/15=31.68=32
_encoder Encoder;
void TIM4_Encoder_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
// NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
/*- 正交编码器输入引脚 PB->6 PB->7 -*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/*- TIM4编码器模式配置 -*/
//TIM_DeInit(TIM4);
TIM_TimeBaseStructure.TIM_Period = 65535;//计次数;
TIM_TimeBaseStructure.TIM_Prescaler = 0;//
TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1 ;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_BothEdge ,TIM_ICPolarity_BothEdge); //配置编码器模式触发源和极性
// TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; //CC1S=01 选择输入端 IC1映射到TI1上
// TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕获
// TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上
// TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置输入分频,不分频?
// TIM_ICInitStructure.TIM_ICFilter = 0x01;//IC1F=0000 配置输入滤波器 不滤
TIM_ICInit(TIM4, &TIM_ICInitStructure);
// NVIC_InitStructure.NVIC_IRQChannel=TIM4_IRQn;
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//中断优先级分组 暂时设置
// NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
// NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
// NVIC_Init(&NVIC_InitStructure);
// TIM4->CNT = 0;
// TIM_ClearFlag(TIM4, TIM_FLAG_Update);
// TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
TIM_SetCounter(TIM4,0);
TIM_Cmd(TIM4, ENABLE); //启动TIM4
void TIM5_Encoder_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
// NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/*- 正交编码器输入引脚 PA->0 PA->1 -*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0| GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/*- TIM5编码器模式配置 -*/
//TIM_DeInit(TIM5);
TIM_TimeBaseStructure.TIM_Period = 1000-1;//计次数;
TIM_TimeBaseStructure.TIM_Prescaler = 0;//
TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1 ;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);
TIM_EncoderInterfaceConfig(TIM5, TIM_EncoderMode_TI12, TIM_ICPolarity_BothEdge ,TIM_ICPolarity_BothEdge); //配置编码器模式触发源和极性
// TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; //CC1S=01 选择输入端 IC1映射到TI2上
// TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_BothEdge; //上升沿捕获
// TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI2上
// TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置输入分频,不分频?
// TIM_ICInitStructure.TIM_ICFilter = 0x01;//IC1F=0000 配置输入滤波器 不滤
TIM_ICInit(TIM5, &TIM_ICInitStructure);
// NVIC_InitStructure.NVIC_IRQChannel=TIM4_IRQn;
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//中断优先级分组 暂时设置
// NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
// NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
// NVIC_Init(&NVIC_InitStructure);
// TIM4->CNT = 0;
// TIM_ClearFlag(TIM4, TIM_FLAG_Update);
// TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
TIM_SetCounter(TIM5,0);
TIM_Cmd(TIM5, ENABLE); //启动TIM5定时器
}
void TIM6_IRQHandler(void)
{
if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET)
printf("count1: %d\r\n",TIM4->CNT);
printf("count2: %d\r\n",TIM5->CNT);
Encoder.M1_rev=TIM4->CNT/K;
Encoder.M2_rev=TIM5->CNT/K;
Encoder.M1speed=Encoder.M1_rev*Perimter; // 车轮速度 m/s
Encoder.M2speed=Encoder.M2_rev*Perimter; // 车轮速度 m/s
Encoder.M1speed/=100;
Encoder.M2speed/=100;
Encoder.M1Lneth+=Encoder.M1speed*0.005;//路程 t=0.005s
Encoder.M2Lneth+=Encoder.M2speed*0.005;//路程 t=0.005s
printf("M1转速:%0.2fr/s \r\n",Encoder.M1_rev);
printf("M2转速:%0.2fr/s \r\n",Encoder.M2_rev);
printf("M1车速:%fm/s\r\n",Encoder.M1speed);
printf("M2车速:%fm/s\r\n",Encoder.M2speed);
printf("M1路程:%fm\r\n",Encoder.M1Lneth);
printf("M2路程:%fm\r\n",Encoder.M2Lneth);
TIM_SetCounter(TIM5,0);
TIM_SetCounter(TIM4,0);
TIM_ClearITPendingBit(TIM6, TIM_IT_Update);
}
在这里插入代码片`
在这#ifndef __ENCODE_H__
#define __ENCODE_H__
#include "sys.h"
void TIM4_Encoder_Init(void);
void TIM5_Encoder_Init(void);
typedef struct
{
float M1Lneth;
float M2Lneth;
float M1_rev;
float M2_rev;
float M1speed;
float M2speed;
}_encoder;
#endif
这是我的代码,是双边沿检测的
主函数是 初始化以后在设置串口波特率然后一个while循环就行了
然后想知道编码器模式的看看这个手册 : <
这个链接里的也讲的很好大家可以参口参考
http://www.51hei.com/bbs/dpj-40950-1.html