counter



/*
Jesper Hansen

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.



Project: CounterMeasures


40 MHz Frequency Counter
------------------------

CPU : At90S2313

Date: 2001-03-02

Author : Jesper Hansen





Current consumption about 40-45 mA.

Measures to > 50 MHz


*/


#include
#include
#include


// PORT D bits

// al counter control bits active low

#define CLEAR PD6
#define OE_H PD5
#define OE_L PD4

// PD3..0 is lower data bus


// PORT B

// PB7..4 is high data bus
// PB3 is OC1 output
// PB2..0 is 74HC138 select bits for display common



// constants/macros
#define F_CPU 4000000 // 4MHz processor
#define CYCLES_PER_US ((F_CPU+500000)/1000000) // cpu cycles per microsecond


// display data

#define SEG_a 0x01
#define SEG_b 0x02
#define SEG_c 0x04
#define SEG_d 0x08
#define SEG_e 0x10
#define SEG_f 0x20
#define SEG_g 0x40
#define SEG_dot 0x80


unsigned char digits[] = {
(SEG_a|SEG_b|SEG_c|SEG_d|SEG_e|SEG_f), // 0
(SEG_b|SEG_c), // 1
(SEG_a|SEG_b|SEG_d|SEG_e|SEG_g), // 2
(SEG_a|SEG_b|SEG_c|SEG_d|SEG_g), // 3
(SEG_b|SEG_c|SEG_c|SEG_f|SEG_g), // 4
(SEG_a|SEG_c|SEG_d|SEG_f|SEG_g), // 5
(SEG_a|SEG_c|SEG_d|SEG_e|SEG_f|SEG_g), // 6
(SEG_a|SEG_b|SEG_c), // 7
(SEG_a|SEG_b|SEG_c|SEG_d|SEG_e|SEG_f|SEG_g), // 8
(SEG_a|SEG_b|SEG_c|SEG_d|SEG_f|SEG_g), // 9

(SEG_a), // mode 0 indicator (Hz)
(SEG_g), // mode 1 indicator (kHz)
(SEG_d), // mode 2 indicator (MHz)
};


/****************************************************************************/


// timer 0 interrupt handles multiplex and refresh of the displays
// timer is clocked at 62500 Hz

#define TI0_L (256-125) // 500 Hz -> 2 mS

volatile unsigned char active_led = 0;

volatile unsigned long led_value = 0; // four BCD nibbles
volatile unsigned char decimal_point = 0;
volatile unsigned char mode_setting = 0;



SIGNAL(SIG_OVERFLOW0) //timer 0 overflow
{
unsigned char a,b;

// reload timer
outp(TI0_L, TCNT0);

// all displays off by setting all commons high
outp(inp(PORTB) | 0x07, PORTB);

if (active_led == 5)
{
b = digits[10 + mode_setting];
}
else
{
a = led_value >> (( 4 - active_led ) * 4);

b = digits[a & 0x0f];

if (decimal_point == (4 - active_led) )
b |= SEG_dot;
}

a = b & 0xf0; // hi part
b = b & 0x0f; // lo part

// set digit data on port
outp( (inp(PORTB) & 0x0f) | a, PORTB); // high part
outp( (inp(PORTD) & 0xf0) | b, PORTD); // low part

// set common
outp( (inp(PORTB) & 0xf8) | active_led, PORTB);

active_led = (active_led+1) % 6;
}





/****************************************************************************/
/* helpers ****************************************************************/
/****************************************************************************/


void delay(unsigned short us)
{
unsigned short delay_loops;
register unsigned short i;

delay_loops = (us+3)/5*CYCLES_PER_US; // +3 for rounding up (dirty)

// one loop takes 5 cpu cycles
for (i=0; i < delay_loops; i++) {};
}


//
// read 16 bit counter value
//
unsigned int read_counters(void)
{
unsigned int counter_value;

// stop display refresh while reading counters
cli();

// turn off all segments
outp(inp(PORTB) | 0x07, PORTB);

// set high B port to input
outp(0x0f,DDRB);

// set low D port to input
outp(0xf0,DDRD);


// activate OE_H
cbi(PORTD,OE_H);
asm volatile("nop");
sbi(PORTD,OE_H); // one pulse to latch count
asm volatile("nop");
cbi(PORTD,OE_H);
asm volatile("nop");

// read hi
counter_value = (inp(PINB) & 0xf0);
// read lo
counter_value |= (inp(PIND) & 0x0f);
// deactivate OE_H
sbi(PORTD,OE_H);


counter_value <<= 8;


// activate OE_L
cbi(PORTD,OE_L);
asm volatile("nop");
sbi(PORTD,OE_L); // one pulse to latch count
asm volatile("nop");
cbi(PORTD,OE_L);
asm volatile("nop");

// read hi
counter_value |= (inp(PINB) & 0xf0);
// read lo
counter_value |= (inp(PIND) & 0x0f);
// deactivate OE_L
sbi(PORTD,OE_L);


// set B port back to output
outp(0xff,DDRB);

// set D port back to output
outp(0xff,DDRD);

// re-enable display refresh
sei();
return counter_value;
}


//
// do a capture
//
void capture(unsigned int compare)
{

cbi(PORTD,CLEAR); // clear external counters
asm volatile("nop");
sbi(PORTD,CLEAR); // remove clear

outp(0,TCNT1H); // clear timer
outp(0,TCNT1L);

outp(compare >> 8,OCR1H); // set the compare1 register to the
outp(compare,OCR1L); // required value

outp(0x40,TCCR1A); // set OC1 bit to toggle on compare

sbi(TIFR,OCF1A); // clear overflov/compare flags

if (compare == 15625)
outp(0x0C,TCCR1B); // start with fClk/256 (15625 Hz) and compare clear
else
outp(0x0A,TCCR1B); // start with fClk/8 (500 kHz) and compare clear

while ( ! (unsigned char) ( inp(TIFR) & BV(OCF1A)) ); // wait for bit
sbi(TIFR,OCF1A); // clear flags

// counter input now enabled
// for the specified time

while ( ! (unsigned char) ( inp(TIFR) & BV(OCF1A)) ); // wait again for bit

outp(0,TCCR1B); // stop timer

// counter input disabled
}



/****************************************************************************/
/* main *******************************************************************/
/****************************************************************************/

int main(void)
{
int i,j;
unsigned char dp,ms;
unsigned long lv;
unsigned int count;

// set all PORTB as outputs
outp(0xff,DDRB);

// set all bits hi
outp(0xff,PORTB);


// set all PORTD as outputs
outp(0xff,DDRD);

// set all bits hi
outp(0xff,PORTD);


// setup timer 0

outp(0x03, TCCR0); // prescaler f/64 tPeriod = 1/62500 Hz -> 16 uS


// enable timer 0 interrupt
sbi(TIMSK, TOIE0);

// start things running
sei();


/*
compare values at fclk/8 (500 kHz, 2 uS) :

500 = 1 mS
5000 = 10 mS
50000 = 100 mS

at fclk/256 (15.625 kHz, 64 uS) :

15625 = 1 S

*/


// first make sure the OC1 pin is in a controlled state
// we want it to be HIGH initially

// There's no way to set/clear it directly, but it can be forced to
// a defined state by a compare match, se by setting a low compare value
// and start the timer, it can be forced into set state


outp(0,TCNT1H); // clear timer
outp(0,TCNT1L);

outp(0,OCR1H); // set compare to 200
outp(200,OCR1L);

outp(0xC0,TCCR1A); // set OC1 bit to set on compare

// start timer and wait for one compare match
outp(0x01,TCCR1B); // start with fClk/1 (4 MHz)
while ( ! (unsigned char) ( inp(TIFR) & BV(OCF1A)) ); // wait for bit
sbi(TIFR,OCF1A); // clear flags

outp(0,TCCR1B); // stop timer

// compare bit no HI, start
// doing some useful work


while (1)
{
// try a capture at min gate
capture(500); // 1 mS
// get the data
count = read_counters();
dp = 3; // decimal point
ms = 2; // indicate MHz

if (count < 4096) // less than 4.096 MHz
{
// try a capture at next gate value
capture(5000); // 10 mS
// get the data
count = read_counters();
dp = 4; // decimal point
ms = 2; // indicate MHz

if (count < 4096) // less than 409.6 kHz
{
// try a capture at next gate value
capture(50000); // 100 mS
// get the data
count = read_counters();
dp = 3; // decimal point
ms = 1; // indicate kHz

if (count < 4096) // less than 40.96 kHz
{
// try a capture at next gate value
capture(15625); // 1 S
// get the data
count = read_counters();
dp = 0; // decimal point
ms = 0; // indicate Hz
}
}
}

// convert BINARY counter_value (int) to BCD in led_value (long)
lv = 0;
for (j=0;j<8;j++)
{
i = count % 10;
lv >>= 4;
lv |= ((unsigned long)i << 28);
count /= 10;
}

// set display variables
decimal_point = dp;
mode_setting = ms;
led_value = lv;

} // loop

}





Wyszukiwarka

Podobne podstrony:
circuit counter
x 087 2 accounting zeroing counter
counter binary+it summary
68 be bytopic counteroffers1
counter stats
White Collar S02E13 Countermeasures HDTV XviD FQM 2
G78 Circular Pocket Milling CounterClockwise
Counter1Frame (2)
Fogelin, Robert J David Lewis on indicative and counterfactual conditionals
Half Life Counter Strike Poradnik GRY OnLine
Rack plate rack countertop
CounterMonitor
Strict Counterpoint and Tonal Theory
transference countertransference issues with adolescents

więcej podobnych podstron