📄 main.c
字号:
/*********************************************
Project : RPM counter
Version : 1.0
Date : 19-08-2004
Author : Jan Thogersen
Email : jan@future-design.dk
Company :
Comments: The project here measures the time
between two pulses and calculates
the RPM from a average of several
measurements.
The project uses a 16 bit timer to
measure the time between pulses,
however, to extend the RPM range
the 16 bit hardware timer is extended
with an extra software layer. The end
product is a 32 bit timer. Which makes
the measurement very accurate and with
a large range. To minimize the software
footprint the timer is running in
Indput Capture mode. So the essential
of this project is done 100% in hardware.
Chip type : AT90S2313
Clock frequency : 8,000000 MHz
Memory model : Tiny
Internal SRAM size : 128
External SRAM size : 0
Data Stack size : 32
*********************************************/
#include <90s2313.h>
// Here is the definition of which port pin is used for which LED in the matrix.
// The following defines is the ROW in the matrix.
// These values can be changed to fit the PCB layout.
#define A 4
#define B 128
#define C 32
#define D 2
#define E 1
#define F 16
#define G 64
#define Dod 8
// The following defines is the COL in the matrix.
// These values can be changed to fit the PCB layout.
#define COL_A 0x1C
#define COL_B 0x2C
#define COL_C 0x34
#define COL_D 0x38
// Definition of the 7 segment numbers
// A
// -----
// F | G | B
// |----|
// E | | C
// -----o
// D Dod
const unsigned char kucDigi[] = {
(A+B+C+D+E+F), // 0
(B+C), // 1
(A+B+G+E+D), // 2
(A+B+C+D+G), // 3
(B+C+F+G), // 4
(A+C+D+F+G), // 5
(A+C+D+E+F+G), // 6
(A+B+C), // 7
(A+B+C+D+E+F+G), // 8
(A+B+C+D+F+G), // 9
(0) // blank
};
const unsigned char kucCOLUMS[] = {COL_A, COL_B, COL_C, COL_D};
#define NumMeasures 2 // The output is a average of the X readings
unsigned char ucLEDS[4], ucLED_POS;
unsigned char ucCiffer[4];
unsigned int uiTempDigi, uiOutput;
unsigned long ulMeasuredTime;
unsigned char ucOutputOutOfRange;
unsigned long ulMeasured[NumMeasures];
unsigned char ucMeasuredPos;
// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
// Place your code here
// Here is the 7 segment matrix scanner.
TCNT0=0xF0; // This value can be changes to scan faster or slower.
PORTD = kucCOLUMS[ucLED_POS];
PORTB = ucLEDS[ucLED_POS];
ucLED_POS++;
if (ucLED_POS == 4) ucLED_POS = 0;
}
// Timer 1 overflow interrupt service routine
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
// Place your code here
// When we receive a Timer overflood interrupt
// then we add 1 to the high 16 bit of the
// ulMeasuredTime. Why?
// The timer is 16 bit. Thats not enough so we add
// another 16 bit, however this time in software.
// The end product is a 32 bit unsigned long ulMeasuredTime.
// The low 16 bit is for the hardware value from the timer, the
// high 16 bit is for the software timer part.
// So a the overflood we simply add 1 to the software part.
// Later when we have the Input Capture Interrupt we can complete
// the process by adding the hardware value from the timer
// to the low 16 bit of the ulMeasuredTime.
ulMeasuredTime += 0x10000;
// The ucOutputOutOfRange is a variable used to
// verify that we have an input or not. It's a form
// of timeout. When there is a overflood like now, then
// we decrease the value by one.
// If the value reaches zero, then we make the
// assumption that there is no signal.
if (ucOutputOutOfRange > 0) ucOutputOutOfRange--;
}
// Timer 1 input capture interrupt service routine
interrupt [TIM1_CAPT] void timer1_capt_isr(void)
{
// Place your code here
if (ucOutputOutOfRange < 16) ucOutputOutOfRange+=4;
// Place the hardware timer value into the 32 bit accumulation.
ulMeasuredTime += ICR1;
TCNT1 = 0;
// The output is based on an average, so we save the measurements.
// This is not the best way to do it. I know that. But it was fast to code
// And I had enough RAM to do it. But a waste I know.
ulMeasured[ucMeasuredPos] = ulMeasuredTime;
ucMeasuredPos++;
if (ucMeasuredPos >= NumMeasures) ucMeasuredPos = 0;
ulMeasuredTime = 0;
}
// Declare your global variables here
char cTempCnt;
unsigned long ulSum;
void main(void)
{
// Declare your local variables here
// Input/Output Ports initialization
// Port B initialization
// Func0=Out Func1=Out Func2=Out Func3=Out Func4=Out Func5=Out Func6=Out Func7=Out
// State0=1 State1=1 State2=1 State3=1 State4=1 State5=1 State6=1 State7=1
PORTB=0xFF;
DDRB=0xFF;
// Port D initialization
// Func0=Out Func1=Out Func2=Out Func3=Out Func4=In Func5=In Func6=In
// State0=1 State1=1 State2=1 State3=1 State4=T State5=T State6=T
PORTD=0x3C;
DDRD=0x3C;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 31,250 kHz
TCCR0=0x04;
TCNT0=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 125,000 kHz
// Mode: Normal top=FFFFh
// OC1 output: Discon.
// Noise Canceler: On
// Input Capture on Faling Edge
TCCR1A=0x00;
TCCR1B=0x83;
TCNT1H=0x00;
TCNT1L=0x00;
OCR1H=0x00;
OCR1L=0x00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
GIMSK=0x00;
MCUCR=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x8A;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
// Analog Comparator Output: Off
ACSR=0x80;
// Global enable interrupts
#asm("sei")
uiOutput = 0;
while (1) {
ulSum = 0;
// Calculate the average
for (cTempCnt = 0; cTempCnt < NumMeasures; cTempCnt++) ulSum += ulMeasured[cTempCnt];
uiOutput = (long)ulSum / NumMeasures;
// Calculate the RPM from the average time between pulses.
uiTempDigi = (long)(125000*60*NumMeasures) / ulSum;
// Place your code here
if (ucOutputOutOfRange > 4) { // > 4 then Ok Else to many overfloads...
// Check if the RPM is higner than we can show in the display else show "out of range" in the display.
if (uiTempDigi < 10000) {
// A simple binary to BCD converter.
for (cTempCnt = 4;cTempCnt > 0;cTempCnt--) {
ucCiffer[4 - cTempCnt] = (uiTempDigi % 10);
uiTempDigi = uiTempDigi / 10;
}
// Swap a leading zero with "blank"
for (cTempCnt = 3;(ucCiffer[cTempCnt] == 0) && (cTempCnt > 0);cTempCnt--) {
ucCiffer[cTempCnt] = 0x0A;
}
// convert the BCD calue to port values.
for (cTempCnt = 0;cTempCnt < 4;cTempCnt++)
ucLEDS[cTempCnt] = ~kucDigi[ucCiffer[cTempCnt]];
// Flash the comma in the last digi if there is a signal input
if (PIND.6 == 0) ucLEDS[0] &= ~(Dod);
} else {
// Show out of range in display
if (PIND.6 == 0) ucLEDS[0] = ~(A+D+E+F+Dod);
else ucLEDS[0] = ~(A+D+E+F);
ucLEDS[1] = 0xFF;
ucLEDS[2] = 0xFF;
ucLEDS[3] = ~(A+B+C+D);
}
} else {
// If we had to many overfloods (No signal) then we show that in the display
// so it is visible for the user that there is no signal.
if (PIND.6 == 0) ucLEDS[0] = ~(G+Dod);
else ucLEDS[0] = ~(G);
ucLEDS[1] = ~G;
ucLEDS[2] = ~G;
ucLEDS[3] = ~G;
}
};
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -