Professional Documents
Culture Documents
6digit Source
6digit Source
6digit Source
* PROJECT:
< LED 6-digit 24 / 12hr Clock >
* MCU:
PIC16F628a @4MHz
* Compiler:
mikroC PRO C ...
* Revision:
0.1b (conforms to hardware revision 0.1b and above)
* Status:
Working & complete pending further "real world" testing ...
Compiler Messages:
Available RAM: 208 [bytes], Available ROM: 2048 [bytes]
Used RAM (bytes): 25 (12%) Free RAM (bytes): 183 (88%)
Used ROM (program words): 660 (32%) Free ROM (program words): 1388 (68%)
Project Linked Successfully clock.mcppi
Linked in 657 ms
Project 'clock.mcppi' completed: 2032 ms
Finished successfully: 12 Apr 2011, 12:18:55 clock.mcppi
*/
//
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
short
short
short
short
short
short
short
short
short
short
unsigned
unsigned
unsigned
unsigned
int
int
int
int
digitSc
hrsOnes
hrsTens
minOnes
minTens
secOnes
secTens
userSet
dgToSet
tScaler
flDgHrs
flDgMin
flDgSec
dBounce
=
=
=
=
=
=
=
=
=
=
0;
2;
1;
0;
0;
0;
0;
0;
0;
0;
//
//
//
//
//
//
//
//
//
//
=
=
=
=
0;
0;
0;
0;
//
//
//
//
//
:: Defines ::
:: Methods ::
/*
Tables containing segment settings corresponding to numbers for displays
*/
void num0()
{
segA = 1;
segB = 1;
segC = 1;
segD = 1;
segE = 1;
segF = 1;
segG = 0;
}
void num1()
{
segA = 0;
segB = 1;
segC = 1;
segD = 0;
segE = 0;
segF = 0;
segG = 0;
}
void num2()
{
segA = 1;
segB = 1;
segC = 0;
segG = 1;
segD = 1;
segE = 1;
segF = 0;
}
void num3()
{
segA = 1;
segB = 1;
segC = 1;
segD = 1;
segE = 0;
segF = 0;
segG = 1;
}
void num4()
{
segA
segD
segE
segF
segG
segB
segC
=
=
=
=
=
=
=
0;
0;
0;
1;
1;
1;
1;
}
void num5()
{
segA = 1;
segB = 0;
segE = 0;
segF = 1;
segG = 1;
segC = 1;
segD = 1;
}
void num6()
{
segA = 1;
segB = 0;
segC = 1;
segD = 1;
segE = 1;
segF = 1;
segG = 1;
}
void num7()
{
segA = 1;
segB = 1;
segC = 1;
segD = 0;
segE = 0;
segF = 0;
segG = 0;
}
void num8()
{
segA = 1;
segB = 1;
segC = 1;
segD = 1;
segE = 1;
segF = 1;
segG = 1;
}
void num9()
{
segA = 1;
segB = 1;
segC = 1;
segD = 0;
segE = 0;
segF = 1;
segG = 1;
}
void blankDigit()
{
segA = 0;
segB = 0;
segC = 0;
segD = 0;
segE = 0;
segF = 0;
segG = 0;
}
void interrupt()
{
/*
Interrupt handler triggered by MCU's TMRO (pre-scaler enabled)
*/
// Inc scaler
tScaler ++;
// 1000mS / 1 sec of time elapsed?
if (tScaler == 121)
{
// Inc seconds if enabled
if (userSet == 0)
{
secOnes ++;
}
// Fine tune adj
delay_us(2);
// Reset scaler
tScaler = 0;
}
// 50uS before re-triggering interrupt
delay_us(50);
// Fine tune adj
delay_us(3);
// Re-enable and bail
TMR0 = 0;
INTCON = 0x20;
}
void setDigit(unsigned short digit)
{
/*
Apply data to current display digit in scope
Structure implements no "ELSE IF" logic enabling for a relatively
good equalization of execution time regardless of program flow. Program
0)
1)
2)
3)
4)
5)
6)
7)
8)
9)
}
flashDigits(unsigned int digits)
{
/*
Counter for flashing digits on / off when user is adjusting them
*/
digits ++; // Inc
// Counter reached targed? -- reset if so ...
if (digits == 5000)
{
digits = 0;
}
// Return current count to calling procedure
return digits;
}
void incCounter()
{
// Current display off ...
blankDigit();
// Clock decade counter (inc to next display)
clkc = 1;
clkc = 0;
}
void multiplexDisplays()
{
/*
1. Procedure applies data to current display digit in scope ...
2. Successive handling of the displays in an multiplexing fashion
Structure implements no "ELSE IF" logic between digit scanning, enabling
for a relatively good equalization of execution time, regardless of
program flow. Program memory is also preserved, and consistent scanning
frequencies are the end results
*/
//
:: Hours Digit 1 ::
if (digitSc == 0)
{
if (flDgHrs < 2500)
{
// Lead zero blanking for 12hr mode ...
if (mode == 0 && hrsTens == 0)
{
blankDigit();
}
else
{
setDigit(hrsTens);
}
}
else
{
blankDigit();
}
}
//
if (digitSc == 1)
{
if (flDgHrs < 2500)
{
setDigit(hrsOnes);
}
else
{
blankDigit();
}
}
:: Hours Digit 2 ::
//
:: Minutes Digit 1 ::
if (digitSc == 2)
{
if (flDgMin < 2500)
{
setDigit(minTens);
}
else
{
blankDigit();
}
}
//
if (digitSc == 3)
{
if (flDgMin < 2500)
{
setDigit(minOnes);
}
else
{
blankDigit();
}
}
:: Minutes Digit 2 ::
//
if (digitSc == 4)
{
if (flDgSec < 2500)
{
setDigit(secTens);
}
else
{
blankDigit();
}
}
:: Seconds Digit 1 ::
//
if (digitSc == 5)
{
if (flDgSec < 2500)
{
setDigit(secOnes);
}
else
{
blankDigit();
}
}
:: Seconds Digit 2 ::
void doTime()
{
/*
Handles the incrementing and control of all time-related variables
in either 12 or 24hr time
1. Seconds
2. Minutes
3. Hours ...
*/
//
:: Seconds ::
if (secOnes == 10)
{
secTens ++; //
secOnes = 0; //
}
if (secTens == 6)
{
minOnes ++; //
secTens = 0; //
}
Inc tens
Reset ones
//
:: Mins ... ::
if (minOnes == 10)
{
minTens ++; //
minOnes = 0; //
}
if (minTens == 6)
{
hrsOnes ++; //
minTens = 0; //
}
//
:: Hours ... ::
if (hrsOnes == 10)
{
hrsTens ++; // Inc / carry tens
hrsOnes = 0; // Reset ones ...
}
// 12 or 24 mode in scope?
if (mode == 0)
{
//
:: (12hr mode) ::
else //
:: (24hr mode) ::
{
// 24 hrs elapsed? -- reset ones & tens ...
if (hrsTens == 2)
{
if (hrsOnes == 4)
{
hrsTens = 0;
hrsOnes = 0;
}
}
}
}
void doUser()
{
/*
Procedure handles the user adjusting the time via the 2
push button tactile switches ...
This proc renders the above proc out of scope until the
user has set all digits
*/
switch (dgToSet)
{
case 1: //
:: Setting Hours ::
}
// Inc ones?
if (Hrsones != 9)
{
hrsOnes ++;
}
else // Inc tens & reset ones
{
hrsTens ++;
hrsOnes =0;
}
}
}
// Call method to flash digits
flDgHrs = flashDigits(flDgHrs);
break;
case 2: //
:: Setting Minutes ::
:: Setting Seconds ::
{
if (cInc == 0)
{
// Debounce switch contacts (ignore port for a short time)
dBounce = 1250;
// Reset tens & ones if exceeded 60
if (secTens == 5)
{
if (secOnes == 9)
{
secTens = 0;
secOnes = 0;
}
}
// Inc ones?
if (secOnes != 9)
{
secOnes ++;
}
else // Inc tens & reset ones
{
secTens ++;
secOnes =0;
}
}
}
// Call method to flash digits
flDgSec = flashDigits(flDgSec);
break;
case 4: // Exit adj time proc ...
userSet = 0;
dgToSet = 0;
break;
}
}
void main()
{
/*
Program entry point ... (as per usual with any C compiler)
*/
// Configuration of ports etc ...
CMCON
TRISA
TRISB
PORTA
PORTB
OPTION_REG
//
=
=
=
=
=
=
7;
0x0C;
0x00;
0x00;
0x00;
0x84;
//
//
//
//
//
//
TMR0
INTCON
OPTION_REG = %10000111
= 96;
= 0xA0;
}
}
else
{
dBounce --; // Dec counter to re-enable key polling
}
// Run clock or user is setting new time:
if (userSet == 0)
{
doTime(); // Update clock ...
}
else
{
doUser(); // User is adjusting the time
}
// Next display digit in scope
incCounter();
}
}