|
All periods superimposed
*
***************************************************************
****************
* PICOCLOCK : PIC Oscilloscope CLOCK
***************************************************************
****************
*
* This program shows how to display a digital clock on an oscilloscope
* with a PIC and only 4 resistors.
*
* Circuit schematics :
*
* ------------+
* RA0 +----------------> to oscilloscope X trigger input
* |
* RA1 +----------------> pull-up, button to ground : minutes adjustment
* RA2 +----------------> pull-up, button to ground : hours adjustment
* PIC | ____
* RB1 +----|____|-----+---------> to oscilloscope Y input
* | 680 |
* | +-+
* | | | 330
* | +-+
* | ____ |
* RB0 +----|____|-----+
* | 680 |
* ------------+ +-+
* | | 680
* +-+
* |
* -----
* --- GND
* -
*
* Oscilloscope setup :
* set timebase to 0.1 ms, V/div = 1 V
* select external trigger.
*
* source code for mikro C compiler V7.0.0.3
* feel free to use this code at your own risks
* and don't bother me if you get addicted watching this clock.
*
* target : PIC16 or PIC18, 16 Mhz crystal
* HS clock, no watchdog.
*
* tested with PIC16F84A and PIC16F877A
*
*
*
*
***************************************************************
****************
*/
#define TRIGGER PORTA.F0 // this output is to be connected to
oscilloscope trigger input
#define KEY PORTA & 0b110 // input keys mask
#define KEY_MIN_UP PORTA & 0b010 // minute adjust button
#define KEY_HH_UP PORTA & 0b100 // hour adjust button
/*
* 2 bits R2R DAC gives 4 output levels :
*/
#define HIGH PORTB = 0b11 // uper line
#define MID PORTB = 0b10 // middle line
#define LOW PORTB = 0b01 // lower line
#define ZERO PORTB = 0b00 // lowest line
#define MAX_SCALER 15625 // number of timer 0 overflow per second @
16 Mhz = 16000000 / 4 / 256
#define MAX_DIGIT 6 // number of digits to be displayed
#define SLOTS (MAX_DIGIT * 3 + 4) // number of time slots : 2 for header,
3 per digits, 2 for trailer
/*
* 10 digits 7 segment encoding + blank
*/
const unsigned char septSeg[11] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d,
0x07, 0x7f, 0x6f, 0x00 } ;
/*
* slot index for digit start
*/
const unsigned char sIdx[] = {1, 4, 8, 11, 15, 18} ;
unsigned char display[MAX_DIGIT] ; // digit to be displayed
/*
* time slot encoded line flags :
* bit 0 is upper line
* bit 1 is middle line
* bit 2 is lower line
* (if no line flag is set, spot is redirected to lowest line)
* bit 6 is lower vertical bar
* bit 7 is upper vertical bar
*/
unsigned char line[SLOTS] ;
unsigned char dIdx = 0 ; // time slot counter
unsigned char fIdx = 0 ; // frame counter
unsigned int scaler = 0 ; // RTC scaler
unsigned char ss = 0, mn = 0, hh = 0 ; // RTC
/*
* around 10 micro-second delay
*/
void delay10us()
{
Delay_us(10) ;
}
/*
* ISR
*/
void interrupt(void)
{
if(INTCON.T0IF) // if timer 0 overflow
{
scaler++ ; // increment scaler
if(scaler > MAX_SCALER) // one second has expired ?
{
scaler = 0 ; // clear scaler
ss++ ; // next second
if(ss == 60) // last second in minute ?
{
ss = 0 ; // clear second
mn++ ; // next minute
if(mn == 60) // last minute in hour ?
{
mn = 0 ; // clear minute
hh++ ; // next hour
if(hh == 24) // last hour in day ?
{
hh = 0 ; // clear hour
}
}
}
}
if(line[dIdx].F6 && line[dIdx].F7) // if full vertical bar
{
LOW, HIGH, LOW, HIGH ;
LOW, HIGH, LOW, HIGH ;
LOW, HIGH, LOW, HIGH ;
LOW, HIGH, LOW, HIGH ;
LOW, HIGH, LOW, HIGH ;
LOW, HIGH, LOW, HIGH ;
LOW, HIGH, LOW, HIGH ;
LOW, HIGH, LOW, HIGH ;
}
else if(line[dIdx].F6) // if lower vertical bar
{
MID, LOW, MID, LOW ;
MID, LOW, MID, LOW ;
MID, LOW, MID, LOW ;
MID, LOW, MID, LOW ;
MID, LOW, MID, LOW ;
MID, LOW, MID, LOW ;
MID, LOW, MID, LOW ;
MID, LOW, MID, LOW ;
}
else if(line[dIdx].F7) // if upper vertical bar
{
MID, HIGH, MID, HIGH ;
MID, HIGH, MID, HIGH ;
MID, HIGH, MID, HIGH ;
MID, HIGH, MID, HIGH ;
MID, HIGH, MID, HIGH ;
MID, HIGH, MID, HIGH ;
MID, HIGH, MID, HIGH ;
MID, HIGH, MID, HIGH ;
}
if(dIdx == 7) // hour : minute separator
{
LOW, Delay10us() ;
MID, Delay10us() ;
}
else if(dIdx == 14) // minute : second separator
{
if(scaler < MAX_SCALER / 2) // blink 0.5 Hz
{
LOW, Delay10us() ;
MID, Delay10us() ;
}
}
switch(fIdx) // depending on frame index
{
case 0: // upper line
if(line[dIdx] & 1)
{
HIGH ;
}
else
{
ZERO ;
}
break ;
case 1: // middle line
if(line[dIdx] & 2)
{
MID ;
}
else
{
ZERO ;
}
break ;
case 2: // lower line
if(line[dIdx] & 4)
{
LOW ;
}
else
{
ZERO ;
}
break ;
}
dIdx++ ; // next slot
if(dIdx == SLOTS) // last slot ?
{
dIdx = 0 ; // clear slot
TRIGGER = 1 ; // triggers the scope
fIdx++ ; // next frame
if(fIdx == 3) // last frame ?
{
fIdx = 0 ; // clear frame
}
TRIGGER = 0 ; // end trigger
}
INTCON.T0IF = 0 ; // clear timer 0 overflow
}
}
/*
* main entry
*/
void main()
{
#ifdef P16F877A
/*
* set PORTA as digital I/O
*/
ADCON1 = 7 ;
CMCON = 7 ;
#endif
TRISA = 0b110 ; // PORTA direction register
PORTA = 0 ;
TRISB = 0 ; // PORTB is output
PORTB = 0 ;
/*
* clear buffers
*/
memset(&line, 0, sizeof(line)) ;
memset(display, 0, sizeof(display)) ;
OPTION_REG = 0b11011000 ; // timer 0 prescaler is 1:1
INTCON = 0b10100000 ; // start interrupts
for(;;) // main loop
{
unsigned char i ;
if(KEY) // is a button pressed ?
{
if(KEY_MIN_UP) // adjust minutes
{
ss = 0 ;
mn++ ;
}
else if(KEY_HH_UP) // adjust hours
{
ss = 0 ;
hh++ ;
}
mn %= 60 ; // prevent minute overflow
hh %= 24 ; // prevent hours overflow
Delay_ms(100) ; // debounce
}
/*
* prepare display buffer
*/
display[5] = ss % 10 ; // seconds
display[4] = ss / 10 ;
display[3] = mn % 10 ; // minutes
display[2] = mn / 10 ;
display[1] = hh % 10 ; // hours
display[0] = (hh > 9) ? hh / 10 : 10 ; // blank first digit if zero
/*
* prepare time slot flags
*/
for(i = 0 ; i < MAX_DIGIT ; i++) // for each digit
{
unsigned char s ;
unsigned char *p ;
s = septSeg[display] ; // get 7 segment encoding
p = &line[sIdx] ; // get pointer to time slot, left part of
the digit
(*p).F0 = s.F0 ; // a segment
(*p).F1 = s.F6 ; // g segment
(*p).F2 = s.F3 ; // d segment
(*p).F6 = s.F4 ; // e segment
(*p).F7 = s.F5 ; // f segment
p++ ; // next slot, center part of the digit
(*p).F0 = s.F0 ; // a segment (continuation)
(*p).F1 = s.F6 ; // g segment (continuation)
(*p).F2 = s.F3 ; // d segment (continuation)
p++ ; // next slot, right part of the digit
(*p).F6 = s.F2 ; // b segment
(*p).F7 = s.F1 ; // c segment
}
}
}
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
|