Sčítání jednotlivých sinusovek-Projekt Elektronické varhany

Ahoj vsem. Naprogramoval jsem si tuhle aplikaci (elektronické vyrhany) na PIC16F877A v MPLAB (kompilátor Hitech - C). Potřeboval bych pomoct, nejlépe dodělat problematiku sčítání sinusovek (viz zadání). Zbytek by měl být funkční. Potřebuji to mít do zítra hotové. Děkuji za pomoc.

[code]/*
Zadání:

Po stisku tlačítka „0“ až „9“ bude k výstupu přidán sinusový signál 1,66 V šš, s frekvencí podle následující řady: [264, 297, 330, 352, 396, 440, 495, 528, 594, 660] Hz (noty cdefgahcde).
Pokud bude již generován signál se stejnou frekvencí, odstraní se starý signál (slábnoucí) a nahradí se novým. Při držení tlačítka přidávaný signál drží svoji amplitudu. Při puštění tlačítka bude amplituda přidaného signálu lineárně klesat k nule. Doba poklesu je přesně 2 sekundy. Program
musí využívat časovač a přerušení. Tedy program může současně generovat až 10 frekvencí (teoreticky). Pokud bylo stisknuto jedno tlačítko a následně dojde ke stisknutí jiného tlačítka, jednotlivé amplitudy sinusovek se sečtou. V případě kdy amplituda přesáhne max. možnou mez, může být výsledný signál ořezán.
*/

#include <pic.h>

__CONFIG(HS & WDTDIS & LVPDIS);

//---------------------definice-------------------//
#define Drive RE0
#define LEDs PORTD
#define KBO PORTA
#define KBI PORTB
#define Tlacitko RB4

//-----------------definice globálních proměných a konstant-------------------//
unsigned int TMR1@ ((unsigned)&TMR1L);
unsigned char Frekvence = 0;
unsigned char Stlaceno = 0;
unsigned char Tla[10] = {0,0,0,0,0,0,0,0,0,0};
unsigned char frek] = {180, 160, 144, 135, 120, 108, 96, 90, 80, 72};
unsigned char sin] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char frekCit] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char del] = {3, 3, 3, 3, 3, 3, 3, 3, 3, 3};
unsigned char snizeni] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char stalStlac] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

//---------------definice pole SINUS------------------//
const unsigned char sinus] = {
63,65,66,68,69,71,73,74,76,77,79,80,82,83,85,86,88,89,91,92,93,95,96,
97,99,100,101,102,104,105,106,107,108,109,110,112,113,114,114,115,
116,117,118,119,119,120,121,122,122,123,123,124,124,125,125,125,
126,126,126,127,127,127,127,127,127,127,127,127,127,127,126,126,
126,125,125,125,124,124,123,123,122,122,121,120,119,119,118,117,
116,115,114,114,113,112,110,109,108,107,106,105,104,102,101,100,
99,97,96,95,93,92,91,89,88,86,85,83,82,80,79,77,76,74,73,71,69,68,66,
65,63,62,60,59,57,55,54,52,51,49,48,46,45,43,42,40,39,37,36,35,33,32,
30,29,28,27,25,24,23,22,20,19,18,17,16,15,14,13,12,11,10,9,9,8,7,6,6,5,
4,4,3,3,2,2,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,2,2,3,3,4,4,5,6,6,7,8,
9,9,10,11,12,13,14,15,16,17,18,19,20,22,23,24,25,27,28,29,30,32,33,35,
36,37,39,40,42,43,45,46,48,49,51,52,54,55,57,59,60,62};

//-------------------Funkce Delay chvilku čeká, mohlo by to být i kratší--------------//

void Delay()
{
unsigned char Cas;
while(Cas–)
{

}

}

//------------------Vrací číslo stisknuté klávesy---------------------//

/*unsigned char GetKey()
{
KBO=0b00011100; // Řádek 0 (123) dej do nuly
Delay(); // Chvilku počkej
switch(KBI&0xE0) // Pokud je hodnota (KBI AND 0xE0) rovna z následujících uvedených
{
case 0b11000000:return 1; // Vrať jako výsledek funkce číslo 1
case 0b10100000:return 2; // Vrať jako výsledek funkce číslo 2
case 0b01100000:return 3; // Vrať jako výsledek funkce číslo 3
}
KBO=0b00101100;
Delay();
switch(KBI&0xE0)
{
case 0b11000000:return 4;
case 0b10100000:return 5;
case 0b01100000:return 6;
}
KBO=0b00110100;
Delay();
switch(KBI&0xE0)
{
case 0b11000000:return 7;
case 0b10100000:return 8;
case 0b01100000:return 9;
}
KBO=0b00111000;
Delay();
switch(KBI&0xE0)
{
case 0b11000000:return 0x81; // Vrať jako výsledek funkce číslo 0x81
case 0b10100000:return 10;
case 0b01100000:return 0x82;
}
return 0; // Pokud jsem se dostali až sem, žádná klávesa nebyla stisknuta, vrať 0
}
*/

unsigned char GetKey()
{
TRISD=0; // PORTD jako výstupní
TRISA=0xC3; // PORTA má výstup RA2-RA5
TRISE0=0; // RE0 je výstupní
RBPU=0; // RB pull-up
KBO=0b00011100; // Řádek 0 (123) dej do nuly
Delay(); // Chvilku počkej
if(!RB5) return 1; //klavesa 1
KBO=0b00101100;
Delay();
if(!RB5) return 2; //klavesa 4
KBO=0b00110100;
Delay();
if(!RB5) return 4; //klavesa 7
KBO=0b00111000;
Delay();
if(!RB5) return 5; //klavesa *
if(!RB4) return 6; //klavesa Tlačitko
return 0; // Pokud jsem se dostali až sem, žádná klávesa nebyla stisknuta, vrati 0
}

//-----------------Obsluha přerušeni---------------------------------//

void interrupt Preruseni(void)
{
unsigned char Vysledek;

ADIF=0;
TMR1ON = 0;
TMR1 -=207-6;

TMR1IF=0; // A vynulovat přerušení, které nastavo od tohoto časovače
TMR1ON = 1;

char vysledek = 0;

if(Tla[0] == 1)
{
	frekCit[0]++;
	
	if(frekCit[0] == frek[0])
	{
		frekCit[0]=0;
		if(stalStlac[0] == 1)
		{
			vysledek = sinus[sin[0]];
		}
		else
		{
			vysledek = ((sinus[sin[0]])/del[0]);
		}
		CCP2Y=(vysledek&1);   					// LSB
		CCP2X=(vysledek&2);  					// další bit
		vysledek>>=2;         					// Tyto bity se už neberou do úvahy, odstranit
		CCPR2L=vysledek;      					// Zbytek do PWM
		if((snizeni[0] >= 4) && (stalStlac[0] != 1))
		{
			del[0] = del[0]+1;
			snizeni[0] = 0;
		}
		snizeni[0] = snizeni[0] + 1;

		if(del[0] == 128)
		{
			Tla[0] = 0;
			del[0] = 3;
		}

		sin[0] = sin[0]+1;
		if(sin[0] == 256)
		{
			sin[0]=0;		
		}
		stalStlac[0] = 0;
	}
}

if(Tla[1] == 1)
{
	frekCit[1]++;

	if(frekCit[1] == frek[1])
	{
		frekCit[1]=0;
	
		if(stalStlac[1] == 1)
		{
			vysledek = sinus[sin[1]];
		}
		else
		{
			vysledek = ((sinus[sin[1]])/del[1]);
		}
		CCP2Y=(vysledek&1);   					// LSB
		CCP2X=(vysledek&2);  					// další bit
		vysledek>>=2;         					// Tyto bity se už neberou do úvahy, odstranit
		CCPR2L=vysledek;      					// Zbytek do PWM
		if((snizeni[1] >= 4) && (stalStlac[1] != 1) )
		{
			del[1] = del[1] + 1;
			snizeni[1] = 0;
			
		}
		snizeni[1] = snizeni[1] + 1;

		if(del[1] == 128)
		{
			Tla[1] = 0;
			del[1] = 3;
		}

		sin[1]++;
		if(sin[1] == 256)
		{
			sin[1]=0;		
		}
		stalStlac[1] = 0;
	}
}

if(Tla[2] == 1)
{
	frekCit[2]++;

	if(frekCit[2] == frek[2])
	{
		frekCit[2]=0;
	
		if(stalStlac[2] == 1)
		{
			vysledek = sinus[sin[2]];
		}
		else
		{
			vysledek = ((sinus[sin[2]])/del[2]);
		}
		CCP2Y=(vysledek&1);   					// LSB
		CCP2X=(vysledek&2);  					// další bit
		vysledek>>=2;         					// Tyto bity se už neberou do úvahy, odstranit
		CCPR2L=vysledek;      					// Zbytek do PWM
		if((snizeni[2] >= 5) && (stalStlac[2] != 1) )
		{
			del[2] = del[2] + 1;
			snizeni[2] = 0;
			
		}
		snizeni[2] = snizeni[2] +1;

		if(del[2] == 128)
		{
			Tla[2] = 0;
			del[2] = 3;
		}

		sin[2]++;
		if(sin[2] == 256)
		{
			sin[2]=0;		
		}
		stalStlac[2] = 0;
	}
}
if(Tla[3] == 1)
{
	frekCit[3]++;

	if(frekCit[3] == frek[3])
	{
		frekCit[3]=0;
	
		if(stalStlac[3] == 1)
		{
			vysledek = sinus[sin[3]];
		}
		else
		{
			vysledek = ((sinus[sin[3]])/del[3]);
		}
		CCP2Y=(vysledek&1);   					// LSB
		CCP2X=(vysledek&2);  					// další bit
		vysledek>>=2;         					// Tyto bity se už neberou do úvahy, odstranit
		CCPR2L=vysledek;      					// Zbytek do PWM
		if((snizeni[3] >= 5) && (stalStlac[3] != 1) )
		{
			del[3] = del[3] + 1;
			snizeni[3] = 0;
			
		}
		snizeni[3] = snizeni[3] +1;

		if(del[3] == 128)
		{
			Tla[3] = 0;
			del[3] = 3;
		}

		sin[3]++;
		if(sin[3] == 256)
		{
			sin[3]=0;		
		}
		stalStlac[3] = 0;
	}
}
if(Tla[4] == 1)
{
	frekCit[4]++;

	if(frekCit[4] == frek[4])
	{
		frekCit[4]=0;
	
		if(stalStlac[4] == 1)
		{
			vysledek = sinus[sin[4]];
		}
		else
		{
			vysledek = ((sinus[sin[4]])/del[4]);
		}
		CCP2Y=(vysledek&1);   					// LSB
		CCP2X=(vysledek&2);  					// další bit
		vysledek>>=2;         					// Tyto bity se už neberou do úvahy, odstranit
		CCPR2L=vysledek;      					// Zbytek do PWM
		if((snizeni[4] >= 6) && (stalStlac[4] != 1) )
		{
			del[4] = del[4] + 1;
			snizeni[4] = 0;
			
		}
		snizeni[4] = snizeni[4] +1;

		if(del[4] == 128)
		{
			Tla[2] = 0;
			del[4] = 3;
		}

		sin[4]++;
		if(sin[4] == 256)
		{
			sin[4]=0;		
		}
		stalStlac[4] = 0;
	
	}
	
}
if(Tla[5] == 1)
{
	frekCit[5]++;
	

	if(frekCit[5] == frek[5])
	{
		frekCit[5]=0;
	
		if(stalStlac[5] == 1)
		{
			vysledek = sinus[sin[5]];
		}
		else
		{
			vysledek = ((sinus[sin[5]])/del[5]);
		}
		CCP2Y=(vysledek&1);   					// LSB
		CCP2X=(vysledek&2);  					// další bit
		vysledek>>=2;         					// Tyto bity se už neberou do úvahy, odstranit
		CCPR2L=vysledek;      					// Zbytek do PWM
		if((snizeni[5] >= 7) && (stalStlac[5] != 1) )
		{
			del[5] = del[5]+1;
			snizeni[5] = 0;
			
		}
		snizeni[5] = snizeni[5] +1;

		if(del[5] == 128)
		{
			Tla[5] = 0;
			del[5] = 3;
		}

		sin[5]++;
		if(sin[5] == 256)
		{
			sin[5]=0;		
		}
		stalStlac[5] = 0;
	}
	
}
if(Tla[6] == 1)
{
	frekCit[6]++;

	if(frekCit[6] == frek[6])
	{
		frekCit[6]=0;
	
		if(stalStlac[6] == 1)
		{
			vysledek = sinus[sin[6]];
		}
		else
		{
			vysledek = ((sinus[sin[6]])/del[6]);
		}
		CCP2Y=(vysledek&1);   					// LSB
		CCP2X=(vysledek&2);  					// další bit
		vysledek>>=2;         					// Tyto bity se už neberou do úvahy, odstranit
		CCPR2L=vysledek;      					// Zbytek do PWM
		if((snizeni[6] >= 8) && (stalStlac[6] != 1) )
		{
			del[6] = del[6]+1;
			snizeni[6] = 0;
			
		}
		snizeni[6] = snizeni[6] +1;

		if(del[6] == 128)
		{
			Tla[6] = 0;
			del[6] = 3;
		}

		sin[6]++;
		if(sin[6] == 256)
		{
			sin[6]=0;		
		}
		stalStlac[6] = 0;
	}

}
if(Tla[7] == 1)
{
	frekCit[7]++;

	if(frekCit[7] == frek[7])
	{
		frekCit[7]=0;
	
		if(stalStlac[7] == 1)
		{
			vysledek = sinus[sin[7]];
		}
		else
		{
			vysledek = ((sinus[sin[7]])/del[7]);
		}
		CCP2Y=(vysledek&1);   					// LSB
		CCP2X=(vysledek&2);  					// další bit
		vysledek>>=2;         					// Tyto bity se už neberou do úvahy, odstranit
		CCPR2L=vysledek;      					// Zbytek do PWM
		if((snizeni[7] >= 8) && (stalStlac[7] != 1) )
		{
			del[7] = del[7]+1;
			snizeni[7] = 0;
			
		}
		snizeni[7] = snizeni[7] +1;

		if(del[7] == 128)
		{
			Tla[7] = 0;
			del[7] = 3;
		}

		sin[7]++;
		if(sin[7] == 256)
		{
			sin[7]=0;		
		}
		stalStlac[7] = 0;
	}
	
}
if(Tla[8] == 1)
{
	frekCit[8]++;
	

	if(frekCit[8] == frek[8])
	{
		frekCit[8]=0;
	
		if(stalStlac[8] == 1)
		{
			vysledek = sinus[sin[8]];
		}
		else
		{
			vysledek = ((sinus[sin[8]])/del[8]);
		}
		CCP2Y=(vysledek&1);   					// LSB
		CCP2X=(vysledek&2);  					// další bit
		vysledek>>=2;         					// Tyto bity se už neberou do úvahy, odstranit
		CCPR2L=vysledek;      					// Zbytek do PWM
		if((snizeni[8] >= 9) && (stalStlac[8] != 1) )
		{
			del[8] = del[8]+1;
			snizeni[8] = 0;	
		}
		snizeni[8] = snizeni[8] +1;

		if(del[8] == 128)
		{
			Tla[8] = 0;
			del[8] = 3;
		}

		sin[8]++;
		if(sin[8] >256)
		{
			sin[8]=0;		
		}
		stalStlac[8] = 0;
	}
	
}
if(Tla[9] == 1)
{
	frekCit[9]++;

	if(frekCit[9] == frek[9])
	{
		frekCit[9]=0;
	
		if(stalStlac[9] == 1)
		{
			vysledek = sinus[sin[9]];
		}
		else
		{
			vysledek = ((sinus[sin[9]])/del[9]);
		}
		CCP2Y=(vysledek&1);   					// LSB
		CCP2X=(vysledek&2);  					// další bit
		vysledek>>=2;         					// Tyto bity se už neberou do úvahy, odstranit
		CCPR2L=vysledek;      					// Zbytek do PWM
		if((snizeni[9] >= 10) && (stalStlac[9] != 1) )
		{
			del[9] = del[9]+1;
			snizeni[9] = 0;	
		}
		snizeni[9] = snizeni[9] +1;

		if(del[9] == 128)
		{
			Tla[9] = 0;
			del[9] = 3;
		}

		sin[9]++;
		if(sin[9] == 256)
		{
			sin[9]=0;		
		}
		stalStlac[9] = 0;
	}
}

}

//--------------------samotný program------------------------//
void main(void)
{
ADCON1=0b01001110; // AN0 = Analog, ostatní digital
TRISC1=0; // RC1 je výstupní
TRISC2=0;
RC2=1;
TRISE0=0;
TRISD=0;
PORTD=0;
TRISB=0b11111000;
PORTB=0b00000111;
RBPU=0; // RB pull-up
//TRISA=0xC3; // PORTA má výstup RA2-RA5

PR2=0x3F; // Bude pouze 8 bitový PWM (FF by byl 10 bitový)
CCPR2L=0x80; // Počáteční hodnota, nepodstatné, stejně se hned změní v přerušení
// T2CON=0b00000100; // Zapnout časovač 2
CCP2CON=0b00001111; // CCP2 bude jako PWM
// T1CON=0b00000001; // Spustit časovac 1
INTCON=0b11000000; // Povolit přerušení globalni
PIE1=0b00000001; // Povolit přerušení od časovače 1
T2CON=0b00000100; // Zapnout časovač 2
T1CON=0b00000001; // Spustit časovac 1, preddelicka 1:1

while(1)
{
	Stlaceno = GetKey();		//zavola funkci na zjisteni tlacitka a pak cislo tlacitka prepise do promene Tlacitko
	//while(GetKey());			//opatreni proti stalemu stisku tlacitka
	//Stlaceno = 1;
	if(Stlaceno == 0)
	{
		Tla[0] = 1;
		stalStlac[0] = 1;
	}
	if(Stlaceno == 1)
	{
		Tla[1] = 1;
		stalStlac[1] = 1;
	}
	if(Stlaceno == 2)
	{
		Tla[2] = 1;
		stalStlac[2] = 1;
	}
	if(Stlaceno == 3)
	{
		Tla[3] = 1;
		stalStlac[3] = 1;
	}
	if(Stlaceno == 4)
	{
		Tla[4] = 1;
		stalStlac[4] = 1;
	}
	if(Stlaceno == 5)
	{
		Tla[5] = 1;
		stalStlac[5] = 1;
	}
	if(Stlaceno == 6)
	{
		Tla[6] = 1;
		stalStlac[6] = 1;
	}
	if(Stlaceno == 7)
	{
		Tla[7] = 1;
		stalStlac[7] = 1;
	}
	if(Stlaceno == 8)
	{
		Tla[8] = 1;
		stalStlac[8] = 1;
	}
	if(Stlaceno == 9)
	{
		Tla[9] = 1;
		stalStlac[9] = 1;
	}
}

}[/code]

:arrow_right: administrator: přejmenováno z "Sčítání jednotlivých sinusovek"

:arrow_right: administrator: příspěvek byl upraven
Příště prosím použij náhled, pro ujištění, že vložený text nenaruší strukturu webu.
jirka.c (14 KB)

Hodil si sem obrovsky kus kodu, tak aj ja ti sem hodim velky kus kodu, ale tento bude funkcny. Bez vaznejsich komentarov. Nie je to stavebny navod, schema sa mi k tomu nechce kreslit.
Je to program pre elektronicke varhaby, bezi to na dsPIC33Fj128GP802, ma to 36 kusov dotykovych senzorov, teda 3 oktavy, vie to robit zvuk varhanov aj perkusny zvuk. Ak ti to nejak pomoze, tak tu je.

Ak to potrebujes mat zajtra hotove - to uz zajtra koncertujes? :smiley:
main.c (12.5 KB)

hm jake jednoduche za 1hod si mal napisane ? :smiley: :smiley: :smiley: ozaj nejaky zvukovy prejav alebo videjko toho zazraku y sa nenaslo ?

Atlan: ak sa to pytas mna, tak to samozrejme nebolo hotove za jednu hodinu - je to stary projekt, robim na nom priebezne cca pol roka, najviac prace je tam s mechanickym “dokoncenim” - teda krabica, konektory a vsetky tie veci, ved to pozna kazdy kto robi elektroniku.
Zvuk to ma pomerne jednoduchy, podoba sa to na syntaky zo sedemdesiatych rokov, je to pomerne poucvatelne.
Ked to budem mat hotove, urcite sa to objavi niekde v ramci slovenskych webov okolo elektroniky/MCU.

Dekuji ti Jaromire za tvuj zdrojak. Nakonec se mi situace trochu zmenila a musim to dodelat nejpozdeji do stredy. Tak snad to zprovoznim.