Skip to content

Instantly share code, notes, and snippets.

@ajarmst
Created November 15, 2023 16:42
Show Gist options
  • Save ajarmst/55676d620a906e8ccb53f179a35e3087 to your computer and use it in GitHub Desktop.
Save ajarmst/55676d620a906e8ccb53f179a35e3087 to your computer and use it in GitHub Desktop.
Demonstration of using the ECT to control a HC-SR04 ultrasonic distance sensor
/////////////////////////////////////////////////////////////////////////////
// HC12 Program: Exam 1 - Solution
// Processor: MC9S12XDP512
// Bus Speed: 20 MHz (Requires Active PLL)
// Author: AJ Armstrong, based on work by Carlos Estay
// Details: Demo of using the ECT for an HC-SR04 ultrasonic distance snsr
// Date: Nov 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)
/////////////////////////////////////////////////////////////////////////////
// Local Prototypes
/////////////////////////////////////////////////////////////////////////////
void SegsUpdate(void); //RTI event
/////////////////////////////////////////////////////////////////////////////
// Global Variables
/////////////////////////////////////////////////////////////////////////////
volatile unsigned int rEdge = 0, fEdge = 0;
volatile char update = 0; //Do I need to update my range (controlled by RTI)
/////////////////////////////////////////////////////////////////////////////
// Constants
/////////////////////////////////////////////////////////////////////////////
//I use constants for parameters that would otherwise be magic numbers.
int const gkiTriggerPeriod = 65000; //usec between trigger pulses
int const gkiTriggerDuration = 12; //usec duration of trigger pulse
double const gkdSndSpd = 1.7241e-4; // m/s (58 usec/cm) for calc. distance
/////////////////////////////////////////////////////////////////////////////
// Main Entry
/////////////////////////////////////////////////////////////////////////////
void main(void)
{
// Variables
int pWidth = 0; //Return pulse width in uS
double distance = 0.0; //Calculated distance in mm
_DISABLE_COP(); // No watchdog
/////////////////////////////////////////////////////////////////////////////
// One-Time Initializations
/////////////////////////////////////////////////////////////////////////////
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
//Configure RTI to trigger the update flag every 500 msec
RTI_RegisterEvent(0,SegsUpdate,500);
//Configure a 1 uSec tick time (1 MHz is 20 MHz / 20)
TSCR1 |= TSCR1_PRNT_MASK; //Enable precision timer
PTPSR = 20 - 1; //Prescale by 20 - tick timer @1us;
//////////////////////////////////////////////////////
// Use Output Compare to create a very specific pulse
// to trigger my HC-SR04 device
/////////////////////////////////////////////////////
//Configure OC Timer on pins 1,7 for my triggering pulse
TIOS_IOS7 = 1; //enable channel 7 as output
TIOS_IOS1 = 1; //enable channel 1 as output
//I want my output pulse to be 12 uSec, every 65 msec.
//See the datasheet for my sensor.
TC7 = gkiTriggerPeriod; //65 ms after TCNT = 0 (TC1 to go high)
TC1 = TC7 + gkiTriggerDuration; //12 us after that (TC1 to go back low)
//I'm not actually going to use Pin PT7, but I can set it to
//toggle for testing purposes
TCTL1_OM7 = 0;
TCTL1_OL7 = 1;
//TC1 I do want to toggle (although, in practice, because TC7 will
//be forcing it up to a one, it will always be toggling down)
TCTL2_OM1 = 0;
TCTL2_OL1 = 1;
//This is the fun bit: I'm going to use TC7 to drag the pin for TC1 high
//before the toggle event on TC1 drags TC1 low 12 uSec later
OC7M |= OC7M_OC7M1_MASK; //Affect PT1 on CH7 compare event
OC7D |= OC7M_OC7M1_MASK; //Transfer a high to PT1 on event
//Turn on interrupts for the pins I care about
TIE_C7I = 1; //Pin 7
TIE_C1I = 1; //Pin 1
//////////////////////////////////////////////////////
// Use Input Capture to measure exactly when the HC-SR04
// detects the return pulse.
/////////////////////////////////////////////////////
//Configure TC0 to use input capture
TIOS_IOS0 = 0;
//Capture any edge (rising or falling)
//BA = 00 (No capture), 01 (Rising), 10 (falling), 11 (both)
TCTL4_EDG0B = 1;
TCTL4_EDG0A = 1;
//Turn on interrupts on the channel I care about
TIE_C0I = 1;
// Enable entire timer subsystem
TSCR1 |= TSCR1_TEN_MASK;
/////////////////////////////////////////////////////////////////////////////
// Main Program Loop
/////////////////////////////////////////////////////////////////////////////
EnableInterrupts; // Ensure our board will respond to interrupt signals.
for (;;)
{
//Based on my RTI event, I'm going to update the distance on my 7 Segs
if(update)
{
update = 0;
pWidth = fEdge - rEdge; // width of pulse in uSec
distance = pWidth * gkdSndSpd * 1000.0; //Calculate distance in mm
SEG_16D(pWidth,0); // Width of pulse in uSec
SEG_16D((int)distance,1); // Distance in mm
}
}
}
/////////////////////////////////////////////////////////////////////////////
// Functions
/////////////////////////////////////////////////////////////////////////////
void SegsUpdate(void)
{
update = 1; // Trigger an update
}
/////////////////////////////////////////////////////////////////////////////
// Interrupt Service Routines
/////////////////////////////////////////////////////////////////////////////
//Timer 7 will trigger the start of arming pulse, every 65 ms
interrupt VectorNumber_Vtimch7 void Vtimch7_ISR(void)
{
TC7 += gkiTriggerPeriod; //Re-arm
TFLG1 = TFLG1_C7F_MASK; //Clear flag (not using FFC this time)
}
//Timer 1 will trigger the end of arming pulse, every 12 uSec later
//Timer 1 and 7 already offset by 12 usec, so just add 65000
interrupt VectorNumber_Vtimch1 void Vtimch1_ISR(void)
{
TC1 += gkiTriggerPeriod; //Re-arm
TFLG1 = TFLG1_C1F_MASK; //Clear flag
}
//Timer 0 will capture every edge of the returning pulse.
//Capturing both edges allows me to measure width of return pulse
interrupt VectorNumber_Vtimch0 void Vtimch0_ISR(void)
{
// I Can figure out if it was leading or trailing by just reading the pin value
if(PTT & PTT_PTT0_MASK) // PT0 is currently High, must have been leading edge
rEdge = TC0; //Time of rising edge
else // must have been low
fEdge = TC0; //That was the falling edge
TFLG1 = TFLG1_C0F_MASK; //Clear flag
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment