# L297 stepper motor controller clock signal question

How i can generate clock signal to L297 stepper motor controller with a PIC16f877 microcontroller?:

If you mean the CLOCK input, then for a single step, you can simply set the pin low for a short time (for a minimum of 0.5us according to the datasheet, so something like 10us would do) then set high again.

For a stream of pulses, then you could use the PWM (or Timer) peripheral. You could write a function that takes the number of steps and speed as the arguments, then sets the peripheral to pulse this number of times, incrementing the count in the Interrupt Service Routine (ISR)

This frees your main loop from doing all the work.

If you need a code example let me know and I'll post something.

Code Example

Here is some code based on the Timer 1 peripheral and Compare Peripheral.
The stepper_step(5, 50); sets up 5 pulses at 50Hz. Basically it sets the pin at the start of the Timer period (adjusted by the speed variable) then clears it using the Compare peripheral 1/10 of the period later. A count variable keeps track of the number of steps. I used the XC8 compiler:

/*
* 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
}
}


Here is a scope shot of the 5 pulses at 50Hz (notice the cursor measurement of 50Hz in the left hand box)

• I will need a stream of pulses so i will be very glad if you could post an example in order to understand it and change it for my project. I use assembly code, but if you dont have something in assembly i can change the C code. Thanks! – 20317 Mar 25 '13 at 12:35
• @20317 - no problem, I'll post something in a few hours when I finish work. My assembly is a bit too rusty to do quickly, so it will be in C though (you can hopefully still get the idea - maybe compile and disassemble it) – Oli Glaser Mar 25 '13 at 16:04
• @20317 - Sorry it's been a while, didn't finish till late last night. I added a rough example using the Timer and Compare peripherals. You can also use the PWM peripheral (better at faster speeds) I will try and add another snippet for this later. – Oli Glaser Mar 26 '13 at 9:59
• You are the best! Thank you very much! I am going to understand and then change to assembly code. Much appreciated what you did! – 20317 Mar 27 '13 at 0:54