前期准备:
要实现减速电机的配置,首先我们要了解自己的电机上编码器的参数。例如这款电机型号为:CHR-GM37-520
其参数如下图:
从图上的基础脉冲数为11PPR我们可以看出电机轴转一圈可以产生11个脉冲信号;
在电机的标签上看到电机减速比为1:90;
那么电机转动一圈实际上产生脉冲数就是:90*11 = 990;
在单片机采用4倍频计数提高精度之后脉冲数:990 * 4 = 3,960;
这就意味着电机一圈的转动我们的单片机就会捕获3960个脉冲信号。
测速方法:在一定时间内,捕获脉冲数。
实际速度:一圈对应3960个脉冲,物理计算出一圈的长度,除以时间,得到实际速度。
驱动使用:l298n
由图可知单片机需要输出3个信号:一个pwm信号,2个方向控制信号。
code : timer
TIM1:PWM输出 TIM3:输入捕获 TIM4:定时器(都在里面运行)
GPIOA: 3,4方向控制信号线 8,11pwm输出控制线
#ifndef __TIMER_H
#define __TIMER_H
#include "sys.h"
extern float cnt;
extern int Tim3_Arr;
extern int Tim3_Psc;
void Encoder_Init_TIM3(void);
void Pwm_Init_TIM1(u16 arr, u16 psc);
void Timer_Init_TIM4(u16 arr, u16 psc);
int Read_Encoder(void);
#endif
#include "timer.h"
#include "sys.h"
#include "delay.h"
#include "led.h"
uint16_t TIM1_CCR1_Val = 2000;
uint16_t TIM1_CCR4_Val = 18000;
uint16_t DEMO = 1000;
float zheng;
float fu;
float cnt;
int Tim3_Arr = 5999;
int Tim3_Psc = 0;
void Encoder_Init_TIM3(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
TIM_TimeBaseStructInit(&TIM_TimeBaseInitStructure);
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = Tim3_Arr;
TIM_TimeBaseInitStructure.TIM_Prescaler = Tim3_Psc;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
TIM_ICStructInit(&TIM_ICInitStructure);
TIM_ICInitStructure.TIM_ICFilter = 10; //滤波器值
TIM_ICInit(TIM3, &TIM_ICInitStructure);
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); //允许TIM3溢出中断
NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x01;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_SetCounter(TIM3, 0); //TIM3 ->CNT = 0
TIM_Cmd(TIM3, ENABLE);
}
void Timer_Init_TIM4(u16 arr, u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE); ///使能TIM4时钟
TIM_TimeBaseInitStructure.TIM_Period = arr; //自动重装载值
TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //定时器分频
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure);//初始化TIM4
TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE); //允许定时器4更新中断
TIM_Cmd(TIM4,ENABLE); //使能定时器4
NVIC_InitStructure.NVIC_IRQChannel=TIM4_IRQn; //定时器3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x00; //抢占优先级1
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void Pwm_Init_TIM1(u16 arr, u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitSture;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);// //使能定时器1的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIO外设时钟使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
//PA8 TIM1_CH1 PA11 TIM1_CH4
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_11; //TIM_CH1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//IO口速度为50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 80K
TIM_TimeBaseStructure.TIM_Prescaler = psc; //设置用来作为TIMx时钟频率除数的预分频值 不分频
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OCInitStructure.TIM_Pulse = TIM1_CCR1_Val;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_OCInitStructure.TIM_Pulse = TIM1_CCR4_Val;
TIM_OC4Init(TIM1, &TIM_OCInitStructure);
TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的预装载寄存器
TIM_CtrlPWMOutputs(TIM1,ENABLE); //MOE 主输出使能
NVIC_InitSture.NVIC_IRQChannel = TIM1_UP_IRQn;
NVIC_InitSture.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitSture.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitSture.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&NVIC_InitSture);
TIM_Cmd(TIM1,ENABLE); //使能TIM1
}
void Data_Prc(void)
{
if(cnt < Tim3_Arr/2)
{
zheng = cnt/3960;
}
else if(cnt > Tim3_Arr/2)
{
fu = (cnt - Tim3_Arr)/3960;
}
}
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET)//溢出中断
{
TIM_ClearITPendingBit(TIM3,TIM_IT_Update); //清除中断标志位
}
}
void TIM4_IRQHandler(void)
{
if(TIM_GetITStatus(TIM4,TIM_IT_Update)==SET) //溢出中断
{
LED0 = !LED0;
cnt=TIM_GetCounter(TIM3);
Data_Prc();
TIM_SetCounter(TIM3,0);
TIM_SetCounter(TIM4,0);
TIM_SetCompare1(TIM1, DEMO);
TIM_SetCompare4(TIM1, DEMO);
TIM_ClearITPendingBit(TIM4,TIM_IT_Update); //清除中断标志位
TIM_ClearITPendingBit(TIM3,TIM_IT_Update); //清除中断标志位
}
}
code: main
#include "stm32f10x.h"
#include "sys.h"
#include "timer.h"
#include "delay.h"
#include "moter.h"
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
Pwm_Init_TIM1(19999,71);
Moter_Init();
Encoder_Init_TIM3();
Timer_Init_TIM4(999, 7199);
delay_init();
while(1)
{
Motor_Forward();
}
}
code:motor
#ifndef __MOTER_H
#define __MOTER_H
#include "sys.h"
#define M1_P PAout(4)
#define M1_N PAout(5)
void Moter_Init(void);
void Moter_Stop(void);
void Motor_Forward(void);
void Motor_Recede(void);
#endif
#include "moter.h"
#include "led.h"
void Moter_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PA端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5; //端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化PA4/5
}
void Moter_Stop(void)
{
M1_P = 0;
LED0 = 0;
M1_N = 0;
LED1 = 0;
}
void Motor_Forward(void)
{
M1_P = 1;
LED0 = 1;
M1_N = 0;
LED1 = 0;
}
void Motor_Recede(void)
{
M1_P = 0;
LED0 = 0;
M1_N = 1;
LED1 = 1;
}
这样就能简单的控制减速电机CHR-GM37-520转动拉。
版权声明:本文为weixin_45770795原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。