PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Probleme bei C->Basic Frequenzmesser



EDatabaseError
22.09.2006, 14:17
Ich habe folgenden C Code:

/*
Jesper Hansen <jesperh@telia.com>

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.

*/



/*

Simple Digital Guitar Tuner
---------------------------
version 1.0 2001-02-12 jesper



PIN assignements on the 2323

PB0 High LED

PB1 Input pin

PB2 Low Led

*/


#include <io.h>
#include <signal.h>




#define F_CPU 11059200 // CPU clock frequency
#define PRESCALER 64 // CPU prescaler value



#define BASE_FREQUENCY (F_CPU/PRESCALER) // counter frequency

#define TUNING_FORK_A 440.0 // "base" A
#define NOTE_DIFF 1.05946309436 // the 12'th root of 2


#define E_STRING 164.81 // top string (1)
#define A_STRING 220.00
#define D_STRING 293.66
#define G_STRING 391.99
#define B_STRING 493.88
#define EH_STRING 659.26 // bottom string (6)


// The guitar note span
// # # # # # # # # # #
//EF G A BC D EF G A BC D E
//1 2 3 4 * 5 6
//

unsigned int Center_Count[] =
{
BASE_FREQUENCY/EH_STRING, // High E
BASE_FREQUENCY/B_STRING, // B
BASE_FREQUENCY/G_STRING, // G
BASE_FREQUENCY/D_STRING, // D
BASE_FREQUENCY/A_STRING, // A
BASE_FREQUENCY/E_STRING, // Low E
};

unsigned int Transition_Count[] =
{
BASE_FREQUENCY/(B_STRING+(EH_STRING-B_STRING)/2), // E to B
BASE_FREQUENCY/(G_STRING+(B_STRING-G_STRING)/2), // B to G
BASE_FREQUENCY/(D_STRING+(G_STRING-D_STRING)/2), // G to D
BASE_FREQUENCY/(A_STRING+(D_STRING-A_STRING)/2), // D to A
BASE_FREQUENCY/(E_STRING+(A_STRING-E_STRING)/2), // A to E
};




volatile unsigned char count_hi; // overflow accumulator

//
//timer 0 overflow interrupt
//
SIGNAL(SIG_OVERFLOW0)
{
count_hi++; // increment overflow count
}


//----------------------------------------------------------------------------
// Main Lupe
//----------------------------------------------------------------------------


int main(void)
{
unsigned int i;
unsigned int count;


//------------------------------
// Initialize
//------------------------------

cbi(DDRB, 1); // PB1 is input
cbi(PORTB, 1); // no pullups active


sbi(DDRB, 0); // PB0 is ouput, High LED
sbi(DDRB, 2); // PB2 is ouput, Low LED


outp(0x03,TCCR0); // set prescaler to f/64 (172.8 kHz @ 11.0592 MHz)

sbi(TIMSK,TOIE0); // enable interrupt on timer overflow
asm volatile ("sei"); // global interrupt enable



//----------------------------------------------------------------------------
// Let things loose
//----------------------------------------------------------------------------


while (1) // loop forever
{
count = 0; // clear sample count
loop_until_bit_is_set(PINB,1); // wait for something to happen

// got a high edge
// start sampling

outp(0,TCNT0); // clear counter
count_hi = 0; // clear hi count


// sample loop

for (i=0;i<32;i++)
{
while (bit_is_set(PINB,1)) // ignore hi->lo edge transitions
if (count_hi > 80) // skip if no edge is seen within
break; // a reasonable time

while (bit_is_clear(PINB,1)) // wait for lo->hi edge
if (count_hi > 80) // skip if no edge is seen within
break; // a reasonable time

count += (count_hi << 8) + inp(TCNT0); // get counter value
outp(0,TCNT0); // clear counter

if (count_hi > 80) // skip if counter has accumulated a
break; // too high value

count_hi = 0; // clear hi count
}




// initially turn off both leds
sbi(PORTB,0);
sbi(PORTB,2);

if (count_hi <= 80) // if count is reasonable
{

count = count >> 5; // average accumulated count by dividing with 32

// now we have to find the correct string

// go through transition frequencies

for (i=0;i<sizeof(Transition_Count)/sizeof(Transition_Count[0]);i++)
{
if (count < Transition_Count[i]) // stop if lower than this transition count
break;
}

// i now holds the string index

// check the count for a match, allowing
// 1 extra count "hysteresis" to avoid too
// much LED flickering

if (count-1 <= Center_Count[i]) // if count <= this string count
cbi(PORTB,0); // light "Too High" LED

if (count+1 >= Center_Count[i]) // if count >= this string count
cbi(PORTB,2); // light "Too Low" LED
}
}


}



Er ist für ein Gitarrenstimmgerät.

Ich benötigen das gleiche Prinzip für einen einfachen Frequenzmesser, der mir die Frequenz per RS232 sendet.


$regfile = "m32def.dat"
$crystal = 11059200

Dim I As Integer
Dim Count As Integer
Dim Count_hi As Byte

Config Pinb.1 = Input
Portb = &B00000000

Config Timer0 = Timer , Prescale = 64
On Timer0 Ttimer0isr
Enable Timer0

Enable Interrupts

Do
Count = 0
Do
If Pinb.1 = 1 Then Exit Do
Loop
Count_hi = 0

For I = 0 To 31

While Pinb.1 = 1
If Count_hi > 80 Then Exit While
Wend

While Pinb.1 = 0
If Count_hi > 80 Then Exit While
Wend

Count = Count_hi + Timer0
Timer0 = 0

Next I
Loop

Ttimer0isr:
Timer0 = 172800
Incr Count_hi
Return




Leider haben mir meine MicrocontrollerC kentnisse um den rest rauszufriemeln.

Da dies ein (IMHO) sehr interessantes projekt ist wäre es sehr hilfreich wenn ihr mir helfen könntet.

Der dazugehörige schaltplan: http://www.myplace.nu/avr/gtuner/index.htm

Mfg
Tobi