Operácie

Projekt: Hodiny B

Z SensorWiki

Hodiny na orientačný beh

A. Hodiny na orientačný beh.

Veľkoplošný 7-segmentový LED displej treba pripojiť k mikroprocesoru a naprogramovať tak, aby po zapnutí odpočítaval minúty nasledujúce po štarte, pričom posledných 5 sekúnd pred každou celou minútou odpípa. Posledné pípnutie bude dlhšie a bude sprevádzané inkrementovaním čísla na displeji. Pred časom 00 bude displej zobrazovať pripravenosť symbolmi --.

K zapojeniu treba vypracovať dokumentáciu, popis programu, schému zapojenia displeja a riadiacej jednotky. Ako bonus doplňte riadenie intenzity displeja na základe vonkajšieho osvetlenia.

7-segmentLEDdisplayShield.jpg

Literatúra:



Semestrálny projekt
  • Vypracovali:
Bc.Michal Géczy
Bc.Ondrej Kamenský
  • Obsah:
1.Zadanie
2.Schéma zapojenia sedem segmentového displeja
3.Riešenie zadania
4.Záver




1.Zadanie

Naprogramujte procesor Atmega128 so štvornásobným sedemsegmentovým displejom na orientačný beh, tak aby po zapnutí odpočítaval minúty nasledujúce po štarte.

Program musí spĺňať tieto podmienky:

1.Po zapnutí sa na displeji zobrazia znaky " - - - - ", čo bude znamenať pripravenosť.
2.Po zatlačení tlačítka sa spustí počítanie.
3.Posledných 5 sekúnd pred každou celou minútou bude počítanie sprevádzané pípaním a posledné pípnutie bude dlhšie.
4.Po zatlačení tlačidla reset sa hodiny na orientačný beh premažú, zobrazia počiatočne znaky a budú čakať na spustenie.
2.Schéma zapojenia

Na obrázku je vnútorná schéma zapojenia štvornásobného sedemsegmentového displeja. Schéma obsahuje vyobrazenie jednotlivých segmentov, samozrejmosťou je, že sú tu uvedené aj jednotlivé piny, pomocou ktorých je pripojený na procesor Atmega 128. Súčasťou plošného spoja, na ktorom je osadený sedemsegmentový displej, sú dve tlačítka, ale aj bzučiak. Jedno tlačitko slúži na resetovanie procesora, druhé tlačítko budeme v našom prípade používať na spúštanie hodín na orientačný beh.

Schema.jpg

Obrázok č.1 Schéma zapojenia sedemsegmentového displeja

Jednotlivé prepínanie medzi sedemsegmentami sa zabezpečuje pomocou PortB, na ktorý sú napojené nie len jednotlivé sedemsegmenty, ale aj tlačítko slúžiace na spustenie hodín na orientačný beh, bzučiak.


3.Riešenie zadania

V prvom rade si musíme zabezpečiť správne prepínanie medzi sedemsegmentami, aby nedošlo k tomu, že to, čo chceme zobraziť na sedemsegmente A4 sa zobrazí na A3 Sedemsegmenty sú pripojené nasledovne na PortB:

PB.0=A4
PB.1=A3
PB.2=A2
PB.3=A1

Príkaz pmocou ktorého prepíname medzi jednotlivými sedemsegmentami

PORTB = ~(1<<place) & 0b11011111;


Následne musíme zabezpečit správne zobrazenie znakov na sedemsegmentovke. Sedemsegmentovka je ovládaná, resp. na vysvietenie segmentov používame PortD. Najnižší bit PortD zodpovedá segmentu "a",najvyšší bit PortD zodpovedá bodke.

Segment.jpg
Obrázok č.2 Vyobrazenie jednotlivých segmentov displeja

Pre prvý, druhý a štvrtý sedemsegment používame zobrazenie rovnakých znakov, ale pri treťom sedemsegmente musíme použiť ešte aj bodku, ktorá nám bude odeľovať minúty od sekúnd na displeji. Pre celé toto zobrazovanie používame funkciu, ktorú vždy voláme, keď je potrebná. Do funkcie vždy posielame dve premenné. Jedna premenná je miesto, na ktorý sedemsegment chceme zobraziť číslo. Druhá premmená nám hovorí, aký znak chceme zobraziť.

Funkcia pre vypisovanie znakov na displej

#include <avr/io.h>


void znak(int number, unsigned char place)

    {


   PORTB = ~(1<<place) & 0b11011111;    // nastavenie sedemsegmentu displaya na ktorom chceme zobrazovat znak
    
	if (number==10) 		//prázdny display
		{    
		PORTD = 0b11111111;
		}

	if (number==11) 		// pomlčka
		{    
		PORTD = 0b10111111;
		}
			if (number==0) 	//0
		{    
		PORTD = 0b11000000;
		}

	if (number==1) 			//1
		{       
		PORTD = 0b11111001;
		}

	if (number==2) 			//2
		{         
		PORTD = 0b10100100;
		}

	if (number==3) 			//3
		{         
		PORTD = 0b10110000;
		}

	if (number==4) 			//4
		{          
		PORTD = 0b10011001;
		}

	if (number==5)			//5 
		{          
		PORTD = 0b10010010;
		}

	if (number==6) 			//6
		{          
		PORTD = 0b10000010;
		}

	if (number==7) 			//7
		{          
		PORTD = 0b11111000;
		}

	if (number==8) 			//8
		{          
		PORTD = 0b10000000;
		}

	if (number==9) 			//9
		{          
		PORTD = 0b10010000;
		}

	if (number==0) 			//0
		{          
		PORTD = 0b11000000;
		}


		
}

void znakmin(int number, unsigned char place)

    {
   PORTB = ~(1<<place) & 0b11011111;

	//tabulka s cislami ale aj s bodkou pre minuty
	if (number==1) 
		{       
		PORTD = 0b01111001;
		}

	if (number==2) 
		{         
		PORTD = 0b00100100;
		}

	if (number==3) 
		{         
		PORTD = 0b00110000;
		}

	if (number==4) 
		{          
		PORTD = 0b00011001;
		}

	if (number==5) 
		{          
		PORTD = 0b00010010;
		}

	if (number==6) 
		{          
		PORTD = 0b00000010;
		}

	if (number==7) 
		{          
		PORTD = 0b01111000;
		}

	if (number==8) 
		{          
		PORTD = 0b00000000;
		}

	if (number==9) 
		{          
		PORTD = 0b00010000;
		}

	if (number==0) 
		{    
		PORTD = 0b01000000;
		}


}

Na počítanie premenných používame cyklus, v ktorom sa inkrementuje základné premenná "sec" s taktom jedna sekunda. Následne je podmienkami zabezpečené zvyšovanie ďaľších premenných "dsec","min","dmin".

Hlavná časť programu

#include <avr/io.h>


void znak(int mumber, int place);

int main (void)
{

// Following two lines are a must for BOOTLOADER
  UCSR0B = 0x00;        // Disable RxD and TxD for UART0
                        // Disable ALL interrupts (Global)
  SREG = SREG & 0x7F;   // same as cli(); but not requiring Interrupts.h


unsigned short i;
unsigned char sec,sekundy, dsec,min,dmin,hod;
	DDRD = 0b11111111;
	DDRB = 0b00101111;
// vynulovanie vsetkych premennych
sec = 0;
dsec = 0;
min = 0;
dmin = 0;
hod = 0;
sekundy = 0;

for (;;)
{
	znak(11,0);   //4 pomlcky na zaciatku
	znak(11,1);
	znak(11,2);
	znak(11,3);

if ( !( PINB & (1<<4) ) ) // caka na stlacenie tlacitka
		{
		for(;;) // nekonecny cyklus
		{

		
		
			for(i=0;i<23526;i++)	// for cyklus prejde za jednu sekundu
			//for(i=0;i<23526;i++)
			{
			
	    	PORTD = 0b11111111;     // prazdny display

	 		znak(sec,0);			//sekundy
	    	PORTD = 0b11111111;
		
			znak (dsec,1);			// desat. sekundy
			PORTD = 0b11111111;	
		
			znakmin (min,2);		//minuty s desatinnou bodkou
			PORTD = 0b11111111;
		
	
			if (dmin>0){			//dminuty, vypisuje iba vtedy ked dmin je>0
				znak (dmin,3);		
				}
			else {
				znak (10,3);
				 }

							 
			PORTD = 0b11111111; 	// prazdny display
			


			}


		sec++;
		sekundy++;

		if (sec ==10)			// ked prekrocime viac ako 10 sek, zvacsi sa dsek o 1
			{
			sec = 0;
			dsec++;
			}
	
		if (dsec ==6)			// ked prekrocime dsek o viac ako 6 tak zvacsi minuty o 1
			{
			dsec = 0;
			min++;
			pip2();
			sekundy = 0;
			}

		if (min ==10)			// ked dosiahneme 10 min zvacsime dmin o 1
			{
			min = 0;
			dmin++;
			}


		if (dmin ==6)
			{
			dmin = 1;
			hod++;
			}		
		
		if ((sekundy > 54) && (sekundy <60))		// od 54 sekundy volame podprogram pipanie do 60 sekundy
				{
				 pip();
		 		}


	    }
	
}
}
}

V tejto časti programu je taktiež vidieť na začiatku ošetrenie, kde po zapnutí hodín na orietačný beh posielame pre zobrazenie na displej " - - - - ". Samozrejme pred tým vynulujeme všetky premenné, aby hodiny začali počítať čas od nuly. Po vynulovaní premenných a zobrazenia pomlčiek program čaká na stlačenie tlačítka pre počítanie. Potom vstúpi do nekonečného cyklu, v ktorom voláme vždy len funkcie pre zobrazenie na displej, ale aj bzučiak. V nekonečnom cykle sa nachádza cyklus, ktorý zabezpečuje takt počítania jednej sekundy. Takt jednej sekundy je zabezpečený tak, že pomocou programu AVR studia sme si zmerali, že aký dlhý čas trvá jeden cyklus, a zmerali sme aj výpočet jednotlivých premmených. Pomocou získaných hodnôt sme vypočítali koľko krát musí prebehnúť cyklus aby bol zabezpečený takt jedna sekunda.

Výpočet dĺžky cyklu: X*42,5us + 6us = 1s X=23526

Pomocou premenej X dokážeme počítanie a zobrazovanie premenných zrýchliť ale aj spomaliť.

V posledných piatich sekundách voláme podprogram, ktorý zabezpečuje spustenie pípania.

Podprogram pípania

#include <avr/io.h>

//funkcia pre kratke pipanie
void pip(void)

{
unsigned int pom;
pom = 0;
   PORTB = PORTB | 0b00100000;       //zapnutie bzuciaka       
   TCCR1A = 0b00000000;              // T/C1 in timer mode
   TCCR1B = 0b00000101;              // prescale ck
   TCNT1 = 57722;                  // start value of T/C1 Low+High bytes
   TIFR1 = 0x01;                    //(1<<TOV1);   if a 1 is written to a TOV1 bit
                                    //             - the TOV1 bit will be cleared


 while (pom<8000){
 	pom++;

      if ( (TIFR1 & 0x01) == 0x01)   // If the overflow flag is set
      {
	  	pom++;
        PORTB = PORTB ^ 0b00100000;  // Toggle the 
        TCNT1 = 57722;                  // start value of T/C1 Low+High bytes
        TIFR1 = 0x01;                // Clear the overflow flag
       }
      else
        asm("nop"); 
	}


                      
}

//funkcia pre dlhe pipanie
void pip2(void)

{
unsigned int pom;
pom = 0;
   PORTB = PORTB | 0b00100000;		//zapnutie byuciaka	              
   TCCR1A = 0b00000000;              // T/C1 in timer mode
   TCCR1B = 0b00000101;              // prescale ck
   TCNT1 = 49910;
   TIFR1 = 0x01;                    //(1<<TOV1);   if a 1 is written to a TOV1 bit
                                    //             - the TOV1 bit will be cleared


 while (pom<60000){
 	pom++;

      if ( (TIFR1 & 0x01) == 0x01)   // If the overflow flag is set
      {
	  	pom++;
        PORTB = PORTB ^ 0b00100000;  // Toggle the 
        TCNT1 = 49910;
		TIFR1 = 0x01;                // Clear the overflow flag
       }
      else
        asm("nop"); 
	}


                  
}
4.Záver

Podstatou riešenia semestrálneho projektu s predmetu Distribuované vnorené počítačové systémy Hodiny na orientačný beh bolo správne naprogramovanie procesora ATmega 128 so sedemsegmentovým displayom. Jednotlivé podmienky, ktoré sú zahrnuté v zadaní projektu sme splnili.

K vypracovanému projektu prikladáme aj zdrojové súbory:

Súbor:Projekt.c,Súbor:Pip.c ,Súbor:Znaky.c