20 Kasım 2010 Cumartesi

pic16f84a ile osiloskop saat

pic16f84a ile osiloskop saat

Daha önce ilginç saatler başlıklı bir yazı yayınlamıştım, bu uygulamada devamı sayılır. Bir osiloskobun girişlerine gönderilen siyaller ile saat tasarlanmış. Aşağıdaki linkten uygulama dosyalarını indirebilirsiniz. Kaynak site burada.

pic osiloskop saaat devresi dosyalar download

devre şeması:
pic16f84 osiloskop saat devre şeması
Osiloskop saat videosu:




mikro C kaynak kodu:

micro c programı sayfası, 900 kelimeye kadar ücretsiz kullanım. Kodu derlemek için kullanılabilir.

/*
*******************************************************************************
* 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
*
* Author : Bruno Gavand, October 2007
* see more details on http://www.micro-examples.com/
*
*******************************************************************************
*/
#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[i]] ; // get 7 segment encoding

p = &line[sIdx[i]] ; // 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
}
}
}