¿Cómo puedo generar una señal de reloj al controlador del motor paso a paso L297 con un microcontrolador PIC16f877 ?:
¿Cómo puedo generar una señal de reloj al controlador del motor paso a paso L297 con un microcontrolador PIC16f877 ?:
Si te refieres a la entrada de RELOJ, entonces para un solo paso, simplemente puedes establecer el pin bajo durante un corto tiempo (por un mínimo de 0.5us según datasheet , por lo tanto, algo así como 10us haría) y luego volverá a ser alto.
Para un flujo de pulsos, entonces podría usar el periférico PWM (o temporizador). Podría escribir una función que tome el número de pasos y la velocidad como argumentos, y luego configure el periférico para que pulse este número de veces, incrementando el conteo en la Rutina de servicio de interrupción (ISR)
Esto libera a tu bucle principal de hacer todo el trabajo.
Si necesitas un ejemplo de código, avísame y publicaré algo.
Ejemplo de código
Aquí hay un código basado en el periférico Timer 1 y Compare Peripheral.
El stepper_step(5, 50);
configura 5 pulsos a 50Hz. Básicamente, establece el pin al inicio del período del temporizador (ajustado por la variable de velocidad) y luego lo borra utilizando el periférico Comparar 1/10 del período posterior. Una variable de cuenta realiza un seguimiento del número de pasos. Utilicé el compilador XC8:
/*
* File: stepper_pulse_example_2.c
* Author: Oli Glaser
*
* Created on 26 March 2013, 08:00
*/
#include <xc.h>
// Turn the Watchdog Timer off
#pragma config WDTE = OFF
/* Defines */
#define FOSC 4000000L
#define FCY (FOSC/4)L
#define TMR_MAX 65535
#define HZ 62500
/* Function definitions */
void delay(int d);
void init(void);
void stepper_step(unsigned int count, unsigned int speed);
/* Global variables */
unsigned int stepper_count = 0;
unsigned int stepper_speed = 0;
unsigned int stepper_pulse = 0;
/* Main */
int main(int argc, char** argv) {
// Initialisation routine
init();
while(1) // Infinite loop
{
delay(1000);
// Step 5 times at 50Hz
stepper_step(5, 50);
}
}
/* Interrupt Service Routine */
void interrupt int_routine(void)
{
// Check it's Timer 1 that has interrupted
if (PIE1bits.TMR1IE && PIR1bits.TMR1IF)
{
PIR1bits.TMR1IF = 0; // Clear interrupt flag
T1CONbits.TMR1ON = 0; // Turn timer off to reset count register
TMR1H = (stepper_speed >> 8); // Set Timer registers
TMR1L = (stepper_speed & 0x00FF);
T1CONbits.TMR1ON = 1; // Turn timer back on
stepper_count--; // decrement pulse count
PIR1bits.CCP1IF = 0; // Clear compare flag
CCP1CON = 0x00; // Reset Compare peripheral
// Set for Compare mode: set pin and then clear pin on match
if(stepper_count) CCP1CONbits.CCP1M = 0b1001;
CCPR1H = (stepper_pulse >> 8); // Set clear pin timing
CCPR1L = (stepper_pulse & 0x00FF);
// Have pulses completed?
if(stepper_count == 0)
{
T1CONbits.TMR1ON = 0; // Turn Timer 1 off
CCP1CON = 0x00; // Reset Compare peripheral
PORTCbits.RC5 = 0; // Make sure pin is left low
}
}
// process other interrupt sources here, if required
}
/* Initialisation routine */
void init(void)
{
// Make all pins digital
ANSEL = 0;
ANSELH = 0;
TRISCbits.TRISC5 = 1; // Disable RC5 output driver till PWM configured
CCP1CON = 0x00; // Reset CCP Peripheral
PIR1bits.TMR1IF = 0; // Clear Timer 1 interrupt flag
PIR1bits.CCP1IF = 0; // Clear Compare interrupt flag
// Setup Timer 1
T1CON = 0;
T1CONbits.T1CKPS0 = 1; // T1CKPS = 11 = 1:8 prescaler
T1CONbits.T1CKPS1 = 1; // so timer clock = 1MHz / 8 = 125kHz
/* Timer 1 clock is 125kHz, so for example if we want 2Hz,
* we divide 125kHz by 2 = 62,500.
* Then we subtract this from the rollover value of 65,535,
* so 65,535 - 62,500 = 3035 which is 0x0BDB in hex.
* Timer 1 has two 8-bit high and low registers,
* so we put 0x0B in the high and 0xDB in the low */
INTCONbits.GIE = 1; // Enable global interrupts
INTCONbits.PEIE = 1; // Enable peripheral interrupts
PIR1bits.TMR1IF = 0; // Clear Timer 1 interrupt flag
PIE1bits.TMR1IE = 1; // Enable Timer 1 interrupt
PORTCbits.RC5 = 0; // Clear RC5
TRISCbits.TRISC5 = 0; // Sets pin RC5 to output
}
/* This routine works well for slow steps
* from 2Hz - 1kHz or so.
* Above this using the PWM is better.
* count = number of pulses
* speed = pulse speed in Hz */
void stepper_step(unsigned int count, unsigned int speed)
{
unsigned int temp_speed = HZ / (speed / 2);
stepper_count = count;
if(stepper_count < 1) stepper_count = 1;
stepper_speed = (TMR_MAX - (temp_speed));
// Make duty cycle 1:10
stepper_pulse = (stepper_speed + ((temp_speed) / 10));
// Split 16-bit integer over the two 8-bit Timer 1 registers
TMR1H = (stepper_speed >> 8);
TMR1L = (stepper_speed & 0x00FF);
// Do the same for the compare registers
CCPR1H = (stepper_pulse >> 8);
CCPR1L = (stepper_pulse & 0x00FF);
PIR1bits.CCP1IF = 0;
CCP1CON = 0x00; // Reset CCP Peripheral
CCP1CONbits.CCP1M = 0b1001; // Set up for Compare mode, clear pin on match
T1CONbits.TMR1ON = 1;
}
/* Rough delay routine */
void delay(int d)
{
int i; // Declare variable to be used in the loop
while(d) // While d > 0
{
i = 100; // set i to 100 for inner loop
while(i) // while i > 0
{
i--; // decrement i (e.g. i will equal 99, 98, 97,...)
}
d--; // decrement d
}
}
Aquí hay un plano de alcance de los 5 pulsos a 50Hz (observe la medida del cursor de 50Hz en el cuadro de la izquierda)
Lea otras preguntas en las etiquetas stepper-motor