Zrychlování frekvence

Takže, můžu použít ten druhý čítač i pro řešení těch zákmitů tlačítka, tak i na ty hodnoty pro ocr. Postupně chci rozšířit ten program o další funkce. Mám to jen jako koníčka a bohužel na bádání není tolik času.

Edit: Mě šlo o to jestli pro ty tlačitka můžu použít to druhé přerušení aby to mezi sobou nějak nekolidovalo, když tam zároveň generuju ten čas 1s pro první čítač

Ten druhý čítač se dá použít libovolně, protože má stálou periodu, takže víš, jak často přerušení nastane. Ten čítač, co generuje PWM signál můžeš použít také, ale tam perioda kolísá, což je v praxi minimálně nešikovné. Nebo snad máš představu, že když potřebuješ časovat třeba 30 různých událostí, tak že musíš najít kontroler, který má alespoň 30 časovačů ? Na většinu stačí jeden časovač s pevnou periodou a od něj pak odvozuješ vše ostatní. Načasované události bys stejně neměl zpracovávat v přerušení. Tam jen nastavíš příznaky a akce na základě těchto příznaků provádíš až v hlavním programu.

Díky za vysvětlenou, tak si s tím zase pohraju a uvidím co mě zase nedá spát.

Ještě se zeptám jak funguje ten příkaz: ZakmitTlacitka1 <<= 1; nějak to tam nemůžu pochopit, každopádně bez něj to nefunguje.

Bitový posun o 1 bit doleva.

Spíš jak to funguje, zas ta logika mi dává zabrat.
Když zmáčknu tlačítko začne mi přičítat po 1 do ZakmitTlacitka1, takže mám hodtotu 0b00000001 příjde další přerušení jednička se posune o bit doleva a přičtě další jedničku. Mám teda hodnotu 0b000000011 a až tam je hodnota 0xff tlačítko stisknuto. Takže v tomhle případě bude tlačítko sepnuté za 8ms.

A má to nějakou výhodu ten bitovej posun s kombinací každého 10 přerušení, než tam dát natvrdo každe 80 přerušení?

Potřebuješ vědět, že je tlačítko trvale sepnuté a není to zákmit. Proto potřebuješ opakovanou kontrolu a teprve když je tlačítko pokaždé zaznamenané jako sepnuté, můžeš jeho stav uznat jako ustálený a sepnutý. Těch způsobů, jak eliminovat zákmity je samozřejmě spousta. Já používám tenhle.

Dame na tlacitko RC clen a nebudeme uP obtazovat rieseim matematickej ulohy ohladom rusenia, hlavne ked nam ide o obycajne stlacenie tlacitka. A v pripade nasadenia do prevadzky tam beztak ten rc clen pribude aby to vobec fungovalo. Tal ze vuries hardver a potom do dolat softverom. A nie opacne ako softverovy inzimieri.

Tak zase mám problém a nemůžu ho vyřešit,mám testovací program frekvence 1hz. Po zmáčknutí tlačítka se rozbliká ledka: 500ms je zhaslá a 500ms svítí a tak dokola. Po puštění tlačítka přestane blikat. Jenže, když znovu zmáčknu tlačítko, tak ta první perioda jako by začiná tam kde skončila předchozí a já potřebuju aby vždycky začala buď log0(500ms) nebo log1(500) po zmáčknutí tlačítka a né navazovala.

#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdbool.h>

volatile uint16_t frekvence=62499; //1hz
volatile uint8_t ZakmitTlacitka1,Tlacitko1_stisknute;

ISR (TIMER1_COMPA_vect)
{	
OCR1A=frekvence;				  		
}

ISR (TIMER2_COMP_vect)
{	
	
ZakmitTlacitka1 <<= 1;	
				
	if((PINC & (1 << PC5)) == 0 )
		{        
        ZakmitTlacitka1++;
        }  		
		
	if (ZakmitTlacitka1 == 0xFF)
		{
		Tlacitko1_stisknute = true;	
		}
	else	
		{
		Tlacitko1_stisknute = false;					
		}
	
}


int main(void)
{

DDRB |= (1 << PB1);
DDRD = 0xff; 
DDRC = 0b00000000; 
PORTC |= (1 << PC5);


	TCCR1B |= (1 << WGM12) | (1 << CS11);
    TIMSK |= (1 << OCIE1A);
	OCR1A=frekvence;	
	
	                      
	TIMSK |= (1 << OCIE2);                   
	TCCR2 |= (1 << WGM21) | (1 << CS21); 
	OCR2   = 249;     


	sei(); 
	
	  while(1)
	  {		
	  
	  	if(Tlacitko1_stisknute==true)
		{  
		
		 TCCR1A |= (1 << COM1A0);										
		}
        
		else
		{
	    TCCR1A &=~(1 << COM1A0);	 			
		}	
	 				
	
	  }	
	
	
	return 0;
}

Tak se podívej do datasheetu, co tím nastavením COM1A0 děláš.
Při stisknutí tlačítka (ideálně při hraně) zapneš časovač - nic víc, nic míň.
Po puštění tlačítka toho musíš udělat víc - zastavit časovač, vynulovat jeho hodnotu a v případě, že je LEDka v jiném, než výchozím stavu, ji přepnout. V žádném případě nesmíš měnit nastavení režimu čítače, jako to děláš teď.

Takže TCCR1A |= (1 << COM1A0);mám nechat jak je. A v datashetu jsem našel
CS12=0 CS11=0 CS10=0 No clock source (Timer/counter stopped) je to ono?
Ty čítače časovače mi teda dávají zabrat.

Přesně - na COM1Ax po prvotním nastavení už nesahej.
Po zastavení hodin musíš čítač ještě vynulovat.
A taky přepnout LEDku do výchozího stavu.

A já na to koukal abych nastavil tu děličku. Jen jsem nějak nebral v potaz co to dělá, když jsou ty bity CS všechny v nule. Tak mi pořád nebylo jasný jak mám ten čítač zastavit.

Tak musím být zase za blbce, ale nějak mi nejde přepnout ta ledka. Jsem myslel, že napíšu normálně
PORTB &=~(1 << PB1); Jsem vyzkoušel nějaké kombinace to dát do podmínky a ta mrcha, když zůstane svítít ne a ne zhasnout.

Na zkoušku jsem si to naprogramoval a nasypal do procesoru, takže vím, že to jde. Kontrola PINu, abys věděl, jestli přepnout nebo ne a pak případně přepnout. Ale ne tak, jak jsi to napsal Ty, to samozřejmě nefunguje.

Podívej se do datasheetu na sekci “Compare Match Output Unit” (u mně v datasheetu kapitola 16.8.) a ze zapojení Ti bude jasné, že proč Ti to nefunguje a proč nastavením registru PORT ničeho nedosáhneš. Nicméně, když se podíváš na obrázek schématu a přečteš si pozorně popis bitů u TCCR1A, určite najdeš řešení.

Pro ATmega8 tady mám 3 datasheety, tak kouknu i do ostatních, jestli je to ve stejné kapitole.

Edit: Není. Ve dvou datasheetech je to obrázek 36, ale bez kapitoly, ve třetím je to kapitola 16.8, obrázek 16-5. Název sekce/odstavce se ale ve všech shoduje, schéma také.

Jsem vymyslel něco takového, jen s tím TCCR1B &=~(1 << CS11); TCNT1=0; to nefunguje. Podmínka, že to proveď až PB1 bude v nule je opět na nic. Tak nevím zda jdu takhle spravnou cestou.

while(1)
{

	  	if(Tlacitko1_stisknute==true)
		{  	
		 TCCR1B |= (1 << CS11);
		TCCR1A |= (1 << COM1A0);	
		TCCR1A &=~ (1 << COM1A1);						
		}
        
		else 
		{					
			TCCR1A &=~ (1 << COM1A0);
			TCCR1A |= (1 << COM1A1);								
			//TCCR1B &=~(1 << CS11);
			//TCNT1=0;				
				
		 } 
		
				 				
	 
	  }	
	
	
	return 0;
}

Špatně - už jsem Ti psal, abys na COM1Ax po prvotním nastavení už nesahal.

Edit : Podmínka, že to proveď až PB1 bude v nule, je správná cesta.

Tak už jsem to vymyslel, že to funguje, ale bohužel sahám na to COM1Ax, tak už jsem v koncích zase.

Prostuduj si podle datasheetu tohle :

while(1)
{
	  	if(Tlacitko1_stisknute==true)
		{  	
			 TCCR1B |= (1<<CS11);
		}
		else 
		{
			TCCR1B &= ~((1<<CS12)|(1<<CS11)|(1<<CS10));
			TCNT1 = 0;
			if (OCR_LED_PIN == 1) TCCR1A |= (1<<FOC1A);
		 } 
	}	
}

Teď jsem to vymyslel takhle a funguje to

while(1)
{

	  	if(Tlacitko1_stisknute==true)
		{  	
		 TCCR1B |= (1 << CS11);
							
		}
        
		else 
		{					
		
			
			if((PINB & (1 << PB1)) == 0 )
			{
			TCCR1B &=~(1 << CS11);
			TCNT1=0;
			}		
				
				
				
			
		 } 
		
				 				
	 
	  }