Minutka pomocí ATmega32, zobrazení času 80 s pomocí 8mi LED

Ahoj, potřeboval bych poradit jak by se dala naprogramovat co nejjednodušeji Minutka tj. takový program, který bude mít k dispozici 8LEDek pro zobrazení max. hodnoty 80s (1LED = 10s) a libovolný počet tlačítek na ovládání. Jedno tlačítko by sloužilo k samotnému startu minutky, další dvě tlačítka by sloužila k nastavování odčítaného času tj. tlačítko + na přidání 10s a tlačítko - na odčítání 10s. Poslední tlačítko by bylo na vyvolání přerušení, které by přecházelo právě z režimu běhu minutky na režim nastavování a opačně. Předem děkuji za jakékoliv rady.

:arrow_right: administrator: přejmenováno z "Minutka pomocí ATmega32"

Otázka je co myslíš tím jak naprogramovat? Nejjednodušší to bude zřejmě v céčku. :slight_smile: Podle toho, že na takovou věc budeš dávat ATmega32, tak předpokládám že je to školní projekt, a z otázky jak naprogramovat zase, že o tom asi moc vědět nebudeš. Zkus napsat jak zdatný v tom jsi a můžem to postupně nějak splácat.

Tak jsem něco ubastlil, ale stále nevim jak vyřešit samotný běh minutky, jakožto aby se po nastavení např. 4ledek=40s se zhasínaly postupně další ledky směrem dolů.

// Minutka

#include <avr/io.h>
#define F_CPU 14.7456E6
#include<util/delay.h>
#include<avr/interrupt.h>

volatile int a; //globální proměnná nabývá hodnoty 0,1, volatile nutné u přerušení
int LED=0;

ISR(INT2_vect) //vektor přerušení
{
cli(); //globální zakázání přerušení
if(a==0)a=1;
else a=0;
sei(); //globální povolení přerušení
}

int main()
{

a=0; //nastavení proměnné
DDRA=255; //všechny LED na výstup
DDRB=0; //všechny tlačítka na vstup
GICR=(1<<INT2); //nastavení prerušení nastaví 1 na INT2
sei();

while(1)
{
	if(a==0)	//nastavení doby odčítání
	{
		if(PINB==254)		//nastavení času +
			{
				LED++;
				if(LED>8)LED=8;
			}
			else if(PINB==253)	//nastavení času -
			{
				LED--;
				if(LED<0)LED=0;
			}
			PORTA=255;
			PORTA=PORTA<<LED;
			_delay_ms(200);	
	}
	else	//běh minutky						
	{
			
			if(LED>0)	//1led=10s
			{
			//
			//kód běhu
			//
			_delay_ms(5000);		//zpoždění 10s
			_delay_ms(5000);

			}

			else if(LED==0)	//blikání diod na konci programu
			{
				while(1)
				{
					PORTA=0b01010101;
					_delay_ms(500);
					PORTA=0b10101010;
					_delay_ms(500);
				}
						
					
			}
			

	}


}

}

Achjo.
Kdo to ma lustit.
Zde je prepis, priste to taky tak udelej… Pouzij CODE v telu zpravy k definici zdrojoveho kodu

[code]// Minutka

#define F_CPU 14.7456E6

#include <avr/io.h>
#include<util/delay.h>
#include<avr/interrupt.h>

volatile int a; //globální proměnná nabývá hodnoty 0,1, volatile nutné u přerušení
int LED=0;

ISR(INT2_vect) //vektor přerušení
{
cli(); //globální zakázání přerušení
if(a==0)a=1;
else a=0;
sei(); //globální povolení přerušení
}

int main()
{
a=0; //nastavení proměnné
DDRA=255; //všechny LED na výstup
DDRB=0; //všechny tlačítka na vstup
GICR=(1<<INT2); //nastavení prerušení nastaví 1 na INT2
sei();
while(1)
{
if(a==0) //nastavení doby odčítání
{
if(PINB==254) //nastavení času +
{
LED++;
if(LED>8)LED=8;
}
else if(PINB==253) //nastavení času -
{
LED–;
if(LED<0) LED=0;
}
PORTA=255;
PORTA=PORTA<<LED;
_delay_ms(200);
}
else //běh minutky
{

		if(LED>0)	//1led=10s 
		{ 
		// 
		//kód běhu 
		// 
		_delay_ms(5000);	 //zpoždění 10s 
		_delay_ms(5000); 
		} 
		else if(LED==0)	//blikání diod na konci programu 
		{ 
			while(1) 
			{ 
				PORTA=0b01010101; 
				_delay_ms(500); 
				PORTA=0b10101010; 
				_delay_ms(500); 
			} 
		} 
	} 
} 

}[/code]

  1. Pokud pouzijes v promenne a pouze 0 a 1 staci definovat jako volatile unsigned char
  2. Preruseni INT2 netrva tak dlouho aby si ho musel zakazovat a mezi programatory zakazovat v preruseni preruseni neni koser
  3. _delay_ms(5000) nebude fungovat, myslim ze nejvetsi doba je 1200 ms, ale mozna se mylim.
  4. Kod behu minutky
    Vzhledem jak mas ten program napsany, pouzil bych obycejny for cyklus, kde ve vnitrni smycce bude zpozdeni 1 sekunda a zaroven osetreni spravneho sviceni led, ve for cyklu bych pracoval s promennou LED, kterou bych vynasobil *10

Ale jinak super zacatek, je do slusne udelane…

S tim cyklem přes for souhlasim, ale stále mám problém vyřešit to správné svícení LED. A ktomu kódu určitě je 100% špatně, jelikož při každé dekrementaci LED-- všechny diody zhasnou (PORTA=255). Jako tip bych viděl, že by se to posunulo o LED (PORTA=PORTA<<LED;) jen při prvním průběhu cyklem a poté už po uplynutí dané doby posunulo jen o PORTA=PORTA<<1. A ještě jsem přesně nepochopil, jak by si tu proměnou LED násobil 10*, ale zřejmě si myslel, že bych nedělal zpoždění rovnou 10s ale jen 1s.

for(LED;LED>0;LED--) { PORTA=255; PORTA=PORTA<<LED; }

PORTA = (0xFF <<(8-LED));  //Nastavit počáteční stav

for (unsigned char a = 0; a < LED ; a++) 
    {
    _delay_ms(5000) ;
    _delay_ms(5000) ;
    PORTA  <<= 1;      // a pak jen posouvat 
    }

Funkce _delay_ms by měla zvládnout zhruba 6,5s.

Děkuji za radu. Mohu se jenom zeptat. V tom kódu kde vlastně nastavím PORTA = (0xFF) což je jasný, že si zhasnu všechny diody, ale jak je tam ten bitovej pusun(8-LED), tak to mi dá např. při zadání času 50s=5LED (8-5) což jestli se nemýlim jsou 3, takže se mi z pravé strany nasunou 3 nuly (svítí 3LEDky zprava). Ted k tomu co bych chtěl je, aby se nasunuly ne ty 3LEDky jak jsem popsal výše, ale aby se mi nasunulo 5 nul zprava, aby mi jich svítilo vlastně 5 zprava a postupně zhasínaly, což už udělá posun PORTA <<= 1;.

Napadlo mě jedině tohle, ale určitě se to dá řešit elegantněji. Vždycky po posunu, když se nasune na LEDku první zleva nula, tak tam hned hodit na to místo 1 (PORTA += 128; neboli 0b10000000;)

[code]
PORTA = (0xFF <<(LED)); //Nastavit počáteční stav

			for (unsigned char a = 0; a < (LED-1) ; a++)
			{

				PORTA =PORTA >> 1 ;      // a pak jen posouvat
				PORTA += 128  ;
			} [/code]

Chyba v logice… tedy té mojí.
Neuvědomil jsem si, že LEDky spínáš procesorem k zemi.
Takže tvé řešení je správné.

A nevznikne tam nějaká prodleva tím, že to vždy posune o jednu pozici doprava a než se tam vloží na to poslední místo ta 1 ?? Jde mi o to, aby nevniklo to, že ta poslední LEDka vždy na chviličku zhasne a zas se rozsvítí. Nemám u sebe kit s programátorem, takže to nemohu otestovat.

Prodleva tam sice vznikne, ale okem absolutně nezjistitelná.
A kdyby jsi chtěl mít 100% jistotu, tak použij toto:

PORTA = (PORTA >> 1) | 0x80;