微步驱动原理:
细分驱动,把加在线圈上的电压 从最大到最小的过程,分四次给完,产生四个中间
状态,即四细分。伟力电机内部转子一个分步角度为60度。四细分之后,就变成
15度。外部指针则转1/12度。
细分方法:
根据电流等分,得到四个电压点,根据这四个电压点,预先计算出四个PWM值。
于是一个过程就需要24个点。
单片机需要处理的就是电流的方向控制。由伟力电机时序图,可以分析出每一个相的
电流方向。有四种情况。
正相增大,正相减小,反向增大,反向减小。
const unsigned char OCRnA_Val[24] =
{
5,48,94,163,220,247,250,247,220,163,94,48,5,207,161,92,34,8,5,8,34,92,161,207
}; //微步码 两个线圈中电流相位是60度,
void step_moto_control(void)
{
if(direction_flag) //正转
{
if(OCRnA_Num_L==0)
{
OCRnA_Num_L = 23;
coil_1B_ON();
}
else
OCRnA_Num_L--;
if(OCRnA_Num_L<=12) coil_1B_CLE();
OCR0A = OCRnA_Val[OCRnA_Num_L]; //左线圈电流
if(OCRnA_Num_R==0)
{
OCRnA_Num_R = 23;
coil_2B_ON();
}
else
OCRnA_Num_R--;
if(OCRnA_Num_R<=12) coil_2B_CLE();
OCR0B = OCRnA_Val[OCRnA_Num_R];
}
else //反转
{
OCRnA_Num_L++;
if(OCRnA_Num_L>=13) coil_1B_ON();
if(OCRnA_Num_L>23)
{
OCRnA_Num_L=0;
coil_1B_CLE();
}
OCR0A = OCRnA_Val[OCRnA_Num_L];
OCRnA_Num_R++;
if(OCRnA_Num_R>=13) coil_2B_ON();
if(OCRnA_Num_R>23)
{
OCRnA_Num_R=0;
coil_2B_CLE();
}
OCR0B = OCRnA_Val[OCRnA_Num_R];
}
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
细分时实验的代码。请您指导一下。
//ICC-AVR application builder : 2014-2-4 9:18:54
// Target : M16
// Crystal: 8.0000Mhz
#include <iom16v.h>
#include <macros.h>
# define unint unsigned int
# define uchar unsigned char
#define SET_BIT(io ,bit) ( io |= (1<<bit) )
//置位: SET_BIT(PORTA,0);SET_BIT(DDRA,0);
#define CLR_BIT(io ,bit) ( io &= ~(1<<bit) )
//清0: CLR_BIT(PORTA,0);CLR_BIT(DDRA,0);
#define GET_BIT(pin,bit) ( pin & (1<<bit) )
//读位: GET_BIT(PINA,0);
#define SET_IN( dir,bit) ( dir &= ~(1<<bit) )
//端口方向输入: SET_IN(DDRA,0);
#define SET_OUT(dir,bit) ( dir |= (1<<bit) )
//端口方向输出: SET_OUT(DDRA,0);
#define INVBIT(io,bit) ( io ^= (1<<bit) )
//反转方向
//
#define STEPPER_LN_1 SET_BIT(PORTB ,0)
#define STEPPER_LN_0 CLR_BIT(PORTB ,0)
//
#define STEPPER_RN_1 SET_BIT(PORTB ,1)
#define STEPPER_RN_0 CLR_BIT(PORTB ,1)
#define STEPPER_LR_1 SET_BIT(PORTD ,4)
#define STEPPER_LR_0 CLR_BIT(PORTD ,4)
#define STEPPER_RL_1 SET_BIT(PORTD ,5)
#define STEPPER_RL_0 CLR_BIT(PORTD ,5)
#define STEP_LN_1 SET_BIT(PORTA ,6)
#define STEP_LN_0 CLR_BIT(PORTA ,6)
#define STEP_RN_1 SET_BIT(PORTA ,4)
#define STEP_RN_0 CLR_BIT(PORTA ,4)
#define STEP_LR_1 SET_BIT(PORTA ,5)
#define STEP_RL_1 SET_BIT(PORTA ,5)
#define STEP_LR_0 CLR_BIT(PORTA ,5)
#define STEP_RL_0 CLR_BIT(PORTA ,5)
unsigned char OCRnA_Num_L ,OCRnA_Num_R ;
unsigned char direction_flag = 1;
const unsigned char OCRnA_Val[24] =
{
5,48,94,163,220,247,250,247,220,163,94,48,5,207,161,92,34,8,5,8,34,92,161,207
//0,65,127,180,221,246,255,246,221,180,127,65,0,190,128,75,34,9,0,9,34,75,128,190
}; //微步码 两个线圈中电流相位是60度,
void delay_1us(void) //1us延时函数
{
asm("nop");
}
void delay_nus(unsigned short int n) //N us延时函数
{
unsigned short int i=0;
for (i=0;i<n;i++)
delay_1us();
}
void Delay_1ms(void) //1ms延时函数
{
unsigned short int i;
for (i=0;i<(unsigned short int)(8*143-2);i++);
}
void Delay_nms(unint n) //n*1mS延时子函数
{
unint i=0;
while(i<n)
{
Delay_1ms();
i++;
}
}
void port_init(void)
{
PORTA = 0xFF;
DDRA = 0xFF;
PORTB = 0x0f;
DDRB = 0xFF;
PORTC = 0x0f; //m103 output only
DDRC = 0xFF;
PORTD = 0xff;
DDRD = 0xff;
}
//TIMER0 initialize - prescale:8
// WGM: Normal
// desired value: 255uSec
// actual value: 255.000uSec (0.0%)
void timer0_init(void)
{
TCCR0 = 0x00; //stop
TCNT0 = 0x01; //set count
OCR0 = 0xFF; //set compare
TCCR0 = 0x01; //start timer
}
//TIMER1 initialize - prescale:8
void timer1_init(void)
{
TCCR1B = 0x00;
//OCR1AH = 0x01;
OCR1AL = 0xF4;
//OCR1BH = 0x01;
OCR1BL = 0xF4;
TCCR1A = 0x61;
TCCR1B = 0x02; //start Timer
}
//call this routine to initialize all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();
//timer0_init();
timer1_init();
MCUCR = 0x00;
GICR = 0x00;
//TIMSK = 0x01; //timer interrupt sources
SEI(); //re-enable interrupts
//all peripherals are now initialized
}
void step_moto_control(void)
{
if(direction_flag) //反转
{
if(OCRnA_Num_L==0) { OCRnA_Num_L = 23;STEPPER_LN_0;}//正负端左接1。
else OCRnA_Num_L--;
if(OCRnA_Num_L <= 12) STEPPER_LN_1; //正负端左接0。
OCR1AL = OCRnA_Val[OCRnA_Num_L]; //左线圈电流
OCR1AH = 0x00;
if(OCRnA_Num_R==0)
{OCRnA_Num_R = 23;STEPPER_RN_1; }//正负端右接1。
else OCRnA_Num_R--;
if(OCRnA_Num_R <= 12) STEPPER_RN_0; //正负端右接0。
OCR1BL = OCRnA_Val[OCRnA_Num_R];//右线圈电流
OCR1BH = 0x00;
}
else //正转
{
if(OCRnA_Num_L>23) {OCRnA_Num_L=0;STEPPER_LN_0;} //正负端左接0。
else {OCRnA_Num_L++;}
if(OCRnA_Num_L>12) STEPPER_LN_1;//正负端左接1。
OCR1AL = OCRnA_Val[OCRnA_Num_L];
OCR1AH = 0x00;
if(OCRnA_Num_R>23) {OCRnA_Num_R=0;STEPPER_RN_0;} //正负端右接1。
else OCRnA_Num_R++;
if(OCRnA_Num_R>12) STEPPER_RN_1;//正负端右接1。
OCR1BL = OCRnA_Val[OCRnA_Num_R];
OCR1BH = 0x00;
}
}
/*
1个脉冲转子转60,指针转1/3度。
1/3度*90(1个周期6个脉冲)=180 (个脉冲)*6/180减速比
*/
//24*90
void main(void)
{
unint k = 2250;
init_devices();
direction_flag = 0;
//逆时针
STEPPER_LN_0;
STEPPER_RN_0;
OCRnA_Num_L = 6;
OCRnA_Num_R = 10;
// 顺时
STEPPER_LN_0;
STEPPER_RN_0;
OCRnA_Num_L = 4;
OCRnA_Num_R = 0;
while(1)
{
delay_nus(255);
step_moto_control();
}
}
#pragma interrupt_handler timer1_ovf_isr:iv_TIM1_OVF
void timer1_ovf_isr(void)
{
TCNT1H = 0xFF;
TCNT1L = 0x00;
//step_moto_control();
}
#pragma interrupt_handler timer0_ovf_isr:iv_TIM0_OVF
void timer0_ovf_isr(void)
{
TCNT0 = 0x00; //reload counter value
//step_moto_control();
}
一周热门 更多>