Skip to content

Instantly share code, notes, and snippets.

@ajarmst
Created December 7, 2023 21:47
Show Gist options
  • Save ajarmst/44c5d899c5f66e0a1d307b127dda7b81 to your computer and use it in GitHub Desktop.
Save ajarmst/44c5d899c5f66e0a1d307b127dda7b81 to your computer and use it in GitHub Desktop.
Stepper Motor Control Demo (9S12 Board)
/////////////////////////////////////////////////////////////////////////////
// HC12 Program: Stepper (Port A4-A7) Demo
// Processor: MC9S12XDP512
// Bus Speed: 20 MHz (Requires Active PLL)
// Author: AJ Armstrong
// Details: Simple Demo of Full-Wave Reversible Stepper Control
// (using a )
// Date: Dec 2023
// Revision History :
/////////////////////////////////////////////////////////////////////////////
#include <stdio.h> // For sprintf, etc
#include <ctype.h> // For character utilities
#include <string.h> // Various string utilities
#include <hidef.h> // Common defines and macros
#include "derivative.h" // Derivative-specific definitions
#include "pll.h" // Phase-locked loop clock control
#include "swled.h" // GPIO switches and LEDs
#include "segs.h" // 7-Segment Displays
#include "timer.h" // Enhanced capture timer
#include "portj.h" // Interrupt buttons
#include "pit.h" // Periodic Interrupt timer
#include "rti.h" // Realtime interrupts
#include "lcd.h" // LCD Display
#include "sci.h" // Serial communications interface (EIA/TIA-232)
#include "i2c.h" // Carlos Estay's I2C Driver Libraries
/////////////////////////////////////////////////////////////////////////////
// Local Prototypes
/////////////////////////////////////////////////////////////////////////////
void ProcessStep(void); // RTI Function to advance through waveforms
void SwitchDirection(void); //RTI Function to switch direction through wave
/////////////////////////////////////////////////////////////////////////////
// Global Variables
/////////////////////////////////////////////////////////////////////////////
int direction = 0; // True or false for direction
/////////////////////////////////////////////////////////////////////////////
// Constants
/////////////////////////////////////////////////////////////////////////////
//Waveforms for bipolar full stepping
const unsigned char waveLength = 8; //Number of entries in waveform map below
const unsigned char gkA1[] = {1,1,0,0,1,1,0,0};
const unsigned char gkA2[] = {0,0,1,1,0,0,1,1};
const unsigned char gkB1[] = {0,1,1,0,0,1,1,0};
const unsigned char gkB2[] = {1,0,0,1,1,0,0,1};
/////////////////////////////////////////////////////////////////////////////
// Main Entry
/////////////////////////////////////////////////////////////////////////////
void main(void)
{
/////////////////////////////////////////////////////////////////////////////
// One-Time Initializations
/////////////////////////////////////////////////////////////////////////////
_DISABLE_COP(); // No watchdog
PLL_To20MHz(); // Configure the main clock to 20 MHz (implications for timers)
SWL_Init(); // Standard initialization for switches and LEDs
SEG_Init(); // Standard initializaton for 7-seg displays
RTI_Init(); // Initialize RTI timer
/////////////////////////////////////////////////////////////////////////////
// Main Program Loop
/////////////////////////////////////////////////////////////////////////////
EnableInterrupts; // Ensure our board will respond to interrupt signals.
LCD_Init(); // My current LCD drivers need RTI and interrupts. //FIXME
LCD_StringRCentered(0,"Stepper Demo"); //Top line, centered
LCD_StringRCentered(1,"------------"); //Second line, centered
//I'm just going to bit-bang using Port A, which is pretty available.
// Connections:
// PA7 -> Coil 1 (A)
// PA6 -> Coil 2 (A')
// PA7 -> Coil 3 (B)
// PA9 -> Coil 4 (B')
//Set up Port A, bits 4-7, as outputs
DDRA |= 0b11110000;
//Use RTI interrupts to set step period (msec)
RTI_RegisterEvent(0,ProcessStep,10);
//Use RTI to flip the direction
RTI_RegisterEvent(1,SwitchDirection,5000); //Switch direction every 5 sec
for (;;)
{
asm WAI; //Wait for something interesting to happen
}
}
/////////////////////////////////////////////////////////////////////////////
// Functions
/////////////////////////////////////////////////////////////////////////////
// RTI Interupt handler, which sets the next part of the pulses on Port A
void ProcessStep(void)
{
static unsigned char currStep = 0; // Keep track of which part of wave we're on
// Now, set my four bits in the upper nibble by the current waveform state
unsigned char temp = PORTA & 0x0F; // Grab lower bits on port
SWL_ClearLEDs(eAllLEDs);
if (direction) {
SWL_SetLEDs(eGreen);
temp |= (gkA1[currStep] << 7) // Bit 7 is A1
| (gkA2[currStep] << 6) // Bit 6 is A2
| (gkB1[currStep] << 5) // Bit 5 is B2
| (gkB2[currStep] << 4); // Bit 4 is B1
} else { //Flip Current direction in A to get opposite direction
SWL_SetLEDs(eRed);
temp |= (gkA2[currStep] << 7) // Bit 7 is A2 (note flip from above)
| (gkA1[currStep] << 6) // Bit 6 is A1 (note flip from above)
| (gkB1[currStep] << 5) // Bit 5 is B1
| (gkB2[currStep] << 4); // Bit 4 is B2
}
//Write current state of waveform.
PORTA = temp;
// Advance step to the next step, cycling 7->0
currStep = (currStep + 1) % waveLength;
}
void SwitchDirection(void)
{
//Flip the bit on direction.
direction = direction?0:1; //Boolean toggle 0->1, 1->0
}
/////////////////////////////////////////////////////////////////////////////
// Interrupt Service Routines
/////////////////////////////////////////////////////////////////////////////
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment