The following example is large, however it demonstrates several programming techniques learned over years of micro-controller programming with a range of processors and compilers.
The code could used to run a “whole house” power monitor to learn how much power each circuit in a house uses, both instantaneously, and over a programmable interval (hour, day, week). Not all files are included in the example.
#ifndef MAIN_H
#define MAIN_H
#ifdef MAIN_C
#define _EXTERN
#else
#define _EXTERN extern
#endif
#include <htc.h>
_EXTERN unsigned long adc_val;
_EXTERN bit bLogging;
// store a starting timestamp as 64 bits
_EXTERN unsigned long ts_hi;
_EXTERN unsigned long ts_lo;
// more...
#define INIT_MAIN_EXTERNS() dbg_bit=0; ee_address=0
// does compiler define true, false?
#ifndef FALSE
#define TRUE 1 == 1
#define FALSE !TRUE
#endif
typedef struct {
unsigned int tm;
unsigned int data;
} PRecordT;
// compiler is a pain in the butt about const character string arrays
typedef struct {
char str[10];
} ConstStrT;
// CSAFE commands
#define CMD_SET_TIME 1
#define CMD_GET_TIME 2
enum {MSIPower, MSAPower, MSKwh, MSLog, MSMem, MSAbout,
MSLast} ;
void delay20(void);
// ...
void ShowData(int idx);
#undef _EXTERN
#endif // MAIN_HMain C file:
/*
PMETER
o Sums KWX in defineable increments X;
Calculates KWH
20100807
o Total 8192 words used 6355 free 1837
*/
/* Setup chip configuration */
//#device PIC16F886
#define MAIN_C
#include "main.h"
#undef MAIN_C
__CONFIG(DEBUGEN & XT & WDTDIS ...);
#include <math.h>
// …
#include "misc.h"
//#pragma inline (SER_IORx)
#define LED RB4
static char IntroString[] = "Joe's PMeter";
const ConstStrT MenuStrings[] = {
{"Inst Pwr"},
// …
{"About"}
};
char gbuf[17];
//#define DBG_INTS
#ifdef DBG_INTS
#warning DBG_INTS is on
#define INT_NUM(a) n=a
#else
#define INT_NUM(a)
#endif
void interrupt isr(void)
{
unsigned int b,i;
#ifdef DBG_INTS
unsigned int n;
n = 20; //
default to large value
#endif // DBG_INTS
PEIE = 0;
// GIE = 0;
if(TMR1IF)
{
INT_NUM(1);
// ...
//
T1Interrupt();
ms2++;
// ...
// take
an adc reading
if((adc_pend == 0) && (GODONE == 0))
{
adc_pend = 1;
GODONE = 1;
}
}
// ...
};
PEIE = 1;
// GIE = 1;
}
//-----------------------------------------------------
void main( void )
{
unsigned char mask, b;
// ...
static bit btn_used = 0;
OSCCON |=
0x71; // 8 MhZ, internal
SBOREN =
0; // no brownout reset
// more init ...
// port
inits
PORTB=0b00111111;
TRISB=0b11001111;
//0 = Output, 1 = Input
// set up Timer1 so we can have some background timing
T1Val = 65535 -
4000;
//267; //2 mS = 4000, 4 mS = 8000
TMR1GE =
0; // always counting
// ...
// other initialization
SER_IOInit(TRUE); // sets b_use_esc to
desired
INIT_MAIN_EXTERNS();
InitLCD();
//Send Text
lcd_puts(IntroString);
ms50 = 20;
do
{
if(ms50
>= 50)
{
button = btn_scan(); // nb
if(button != BUTTON_NONE)
{
ms50 =
0; // give time to display menu
}
switch (button)
{
case
BUTTON_UP :
MenuState++; // display next
lcd_puts((char *)
MenuStrings[MenuState].str);
break;
case
BUTTON_DOWN :
MenuState--; // display prev
lcd_puts((char *)
MenuStrings[MenuState].str);
break;
case
BUTTON_LEFT : // down
if(MenuState == MSMem)
{
DataIdx--;
//
display mem records
}
break;
case
BUTTON_RIGHT : // up
// ...
break;
case
BUTTON_ENTER :
if(MenuState == MSMem)
{
//
display memory
}
break;
// more
button cases
default :
break;
};
ms50 = 0;
}
if(out_buf.frame.flags & SIO_FULL_FLAG)
{
// Serial input; do something
SIO_OUTBUF_FREE();
}
if(ms2
>= 1)
{
ms2 = 0;
if(ms1000 >=
1000) // every second
{
// do
ones second task...
switch
(MenuState) {
case MSIPower :
ShowPower(InstPower);
break;
// other cases
default :
break;
};
}
}
} while (run != 0);
}
unsigned int CalcPower(unsigned int v)
{
// empirically defined breakpoints 30 88
140 203.5 278.5 342.5 423 to scale current to non linear xformer
unsigned int k;
unsigned int retval;
k = v < 20 ? 0 :
v
< 30 ? 160 :
v
< 88 ? 116 :
v
< 140 ? 102 :
v
< 203 ? 79 :
v
< 278 ? 74 :
v
< 342 ? 69 :
v
< 423 ? 64 : 64;
retval =
(v * k) / 100;
return
retval;
}
// write record of lenth len to next ee location
void ee_write_rec(PRecordT *rec, int len)
{
// ...
}
// more functions