Skip to content

Instantly share code, notes, and snippets.

@ajarmst
Created November 16, 2023 23:43
Show Gist options
  • Save ajarmst/f542bdcbe2a29c9c95abee5757bda89f to your computer and use it in GitHub Desktop.
Save ajarmst/f542bdcbe2a29c9c95abee5757bda89f to your computer and use it in GitHub Desktop.
Simple demo of the HC9S12 Pulse Accumulator used as a frequency counter.
/////////////////////////////////////////////////////////////////////////////
// HC12 Program: Pulse Accumulator Demo
// Processor: MC9S12XDP512
// Bus Speed: 20 MHz (Requires Active PLL)
// Author: AJ Armstrong
// Details: Very rudimentary demo of a frequency counter
// using Pulse Accumulator A
// 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 GetCount(void); //RTI event to read (duration below sets length of read)
void ShowCount(void); // RTI event to calculate events since last event and
// calculate the frequency of the input.
/////////////////////////////////////////////////////////////////////////////
// Global Variables
/////////////////////////////////////////////////////////////////////////////
int const sampleDuration = 25; //How long to measure in mSec.
int const updateDuration = 500; //How frequently to update display in mSec.
volatile unsigned int count = 0; //PACA count in most recent window
volatile unsigned int freq = 0; //Frequency (KHz) of count
/////////////////////////////////////////////////////////////////////////////
// Constants
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// Main Entry
/////////////////////////////////////////////////////////////////////////////
void main(void)
{
// Variables
_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
// I'm going to measure in 25 msec intervals. I could use the PIT or the ECT, but
// my RTI is already set up.
// So, I'm just going to use the 16-bit Pulse Accumulator A (PACA) (same pin as PT7)
// It has two modes: Gated Time Accumulation---which simply counts clock cycles
// as long as PT7 is high (not counting when it is low) and
// Event-Count---which simply counts events (transitions) on TC7. Counting
// can be started and stopped. The counter can be reset by just setting it to 0.
// We're going to use PACA in Event-Count mode to implement a simple frequency
// counter. In this configuration, it will be good from 1 KHz to about 2.6 MHz.
//Configuring PACA (Enabled, Event-Count mode, Rising Edge)
//I also have the option of setting interrupts on edge detection or on overflow
//I don't need those for this application.
PACTL |= PACTL_PAEN_MASK | PACTL_PEDGE_MASK;
//Now that I'm set up, start measuring. I'm going to use my RTI to determine the intervals
RTI_RegisterEvent(0,GetCount,sampleDuration); //How long to count edges
RTI_RegisterEvent(1,ShowCount,updateDuration); //How frequently to update the segs
// NB: If I wanted to get fancy, I could automatically adjust the sample duration
// for longer when the frequency is low and shorter when the frequency is high
// to keep my counter as accurate as possible over a greater range. (A 16-bit
// pulse accumulator can only count to 65,535. But even then, I could use my PACA
// overflow interrupt to keep track of longer values. This is left as an exercise---
// or future assignment---for the reader.)
/////////////////////////////////////////////////////////////////////////////
// Main Program Loop
/////////////////////////////////////////////////////////////////////////////
EnableInterrupts; // Ensure our board will respond to interrupt signals.
for (;;)
{
//Nothing to do.
asm WAI;
}
}
/////////////////////////////////////////////////////////////////////////////
// Functions
/////////////////////////////////////////////////////////////////////////////
//Used by RTI to get events since last read, calculate frequency, display.
void GetCount(void)
{
//Update count from last measure
count = PACN32; //Read current value of PACA
PACN32 = 0; //Reset my count to 0 (why do I do this at the top?)
freq = count / sampleDuration; // Because 1 ms RTI, this is KHz.
}
void ShowCount(void)
{
SEG_16D(count,0); // Show the raw count
SEG_16D(freq ,1); // Display frequency in KHz.
}
/////////////////////////////////////////////////////////////////////////////
// Interrupt Service Routines
/////////////////////////////////////////////////////////////////////////////
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment