博士
最后登录1970-1-1
在线时间 小时
注册时间2018-6-25
|
将STM32F407 TIM2配置成编码器模式测量电机的转速和方向,
TIM3配置成定时器模式,用来定时,比如每隔10ms中断一次,
进入其中断函数处理TIM2中的与相关数据
用单片机的的PA5、PB3分别接编码器的A、B相,编码器是65536线的增量式编码器
配置TIM2的计数器的初始值为0x00FFFFFF(16777215)
我设想的是
当电机带动编码器沿一个方向转动时,计数器的值在初始值0x00FFFFFF的基础,往上加
当电机带动编码器沿另一个相反的方向转动时,计数器的值在初始值0x00FFFFFF的基础,往下减
Encoder.zip
(13.21 MB, 下载次数: 17)
而电机的转速和方向就用间隔10ms进入中断时,
读出来的计数器值减去计数器的初始值0x00FFFFFF,
当相减的结果为正时,可认为转动方向是正方向,
当相减的结果为负时,可认为转动方向是反方向。
实际测试中,无论电机带动编码器往哪个方向转动,
读出来的计数器值都比初始值0x00FFFFFF要大?
现在有个疑问就是,是不是计数器的值只能增不会减?
大家还有其他的方法测量电机的转动方向吗?
请大佬们不吝赐教!!
谢谢!
代码如下:
#define Encoder_TIM_PSC 0
#define Encoder_TIM_PERIOD 0xFFFFFFFF
#define CNT_MAX 4294967296
#define Encoder_InitCNT 0x00FFFFFF
#define Encoder_TIM TIM2
#define Encoder_TIM_CLK RCC_APB1Periph_TIM2
#define Encoder_CH1_PIN GPIO_Pin_5
#define Encoder_CH1_GPIO_PORT GPIOA
#define Encoder_CH1_GPIO_CLK RCC_AHB1Periph_GPIOA
#define Encoder_CH1_PINSOURCE GPIO_PinSource5
#define Encoder_CH1_AF GPIO_AF_TIM2
#define Encoder_CH2_PIN GPIO_Pin_3
#define Encoder_CH2_GPIO_PORT GPIOB
#define Encoder_CH2_GPIO_CLK RCC_AHB1Periph_GPIOB
#define Encoder_CH2_PINSOURCE GPIO_PinSource3
#define Encoder_CH2_AF GPIO_AF_TIM2
/** @brief linear encoder init
* phaseA PA5 T2_CH1
* phaseB PB3 T2_CH2
* @param void
* @retval void
*/
void Encoder_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
// Encoder_IndexConfig();
/* Encoder GPIO Initialization */
RCC_AHB1PeriphClockCmd(Encoder_CH1_GPIO_CLK|Encoder_CH2_GPIO_CLK, ENABLE);
GPIO_PinAFConfig(Encoder_CH1_GPIO_PORT, Encoder_CH1_PINSOURCE, Encoder_CH1_AF);
GPIO_PinAFConfig(Encoder_CH2_GPIO_PORT, Encoder_CH2_PINSOURCE, Encoder_CH2_AF);
GPIO_InitStructure.GPIO_Pin = Encoder_CH1_PIN ; /* Encoder A */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(Encoder_CH1_GPIO_PORT , &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = Encoder_CH2_PIN; /* Encoder B */
GPIO_Init(Encoder_CH2_GPIO_PORT , &GPIO_InitStructure);
/* TIM Initialization */
RCC_APB1PeriphClockCmd(Encoder_TIM_CLK , ENABLE);
TIM_DeInit( Encoder_TIM ); /* TIMER reset */
TIM_TimeBaseStructure.TIM_Prescaler = Encoder_TIM_PSC;
TIM_TimeBaseStructure.TIM_Period = Encoder_TIM_PERIOD ;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(Encoder_TIM, &TIM_TimeBaseStructure);
TIM_EncoderInterfaceConfig(Encoder_TIM, TIM_EncoderMode_TI12,TIM_ICPolarity_BothEdge,TIM_ICPolarity_BothEdge);
TIM_ICStructInit(&TIM_ICInitStructure);
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM_ICInitStructure.TIM_ICFilter = 3;
TIM_ICInit(Encoder_TIM, &TIM_ICInitStructure);
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
TIM_ICInit(Encoder_TIM, &TIM_ICInitStructure);
/* Set counter to default value */
TIM_SetCounter(Encoder_TIM, Encoder_InitCNT);
// Encoder_TIM->CNT=Encoder_InitCNT;
/* Start TIM */
TIM_Cmd(Encoder_TIM, ENABLE);
}
//通用定时器中断初始化
//这里时钟选择为APB1的2倍,而APB1为42M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器3!
void Encoder_TIM_Init(uint16_t arr,uint16_t psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 计数到49为5ms 计数到99为10ms
TIM_TimeBaseStructure.TIM_Prescaler = psc; //设置用来作为TIMx时钟频率除数的预分频值 10khz的计数频率时psc为8399
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
TIM_ITConfig( TIM3, TIM_IT_Update ,ENABLE );//使能或者失能指定的TIM中断
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
TIM_Cmd(TIM3, ENABLE); //使能TIMx外设 计数器使能
}
//定时器3中断服务函数
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET)
{
uint32_t Encoder_SUMCNT ;
uint32_t Encoder_CNT ;
float speed;
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
// Encoder_SUMCNT = Encoder_TIM->CNT ;
Encoder_SUMCNT = TIM_GetCounter(Encoder_TIM);
printf("计数器总值:%d ",Encoder_SUMCNT);
Encoder_CNT= Encoder_SUMCNT- Encoder_InitCNT ;
// Encoder_TIM->CNT=Encoder_InitCNT;
TIM_SetCounter(Encoder_TIM, Encoder_InitCNT);
printf("计数器初始值:%d ",Encoder_TIM->CNT);
printf("计数器变化值:%d ",Encoder_CNT);
// TIM_SetCounter(Encoder_TIM, Encoder_InitCNT);
speed=(float)Encoder_CNT/(65536*4*0.01);
printf("电机速度:%.3f \r\n",speed);
}
} |
|