L297 pregunta de la señal del reloj del controlador del motor paso a paso

1

¿Cómo puedo generar una señal de reloj al controlador del motor paso a paso L297 con un microcontrolador PIC16f877 ?:

    
pregunta 20317

1 respuesta

3

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)

    
respondido por el Oli Glaser

Lea otras preguntas en las etiquetas