logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[atmega16] wysylanie sygnalow z przyciskow

BluePower 17 Sty 2010 21:17 1064 4
REKLAMA
  • #1 7551470
    BluePower
    Poziom 10  
    Witajcie.

    Zlutowałem układ jak pokazuje rysunek poniżej:
    [atmega16] wysylanie sygnalow z przyciskow

    Napisałem i zaprogramowałem atmega
    #define F_CPU 1000000UL
    #include <avr/io.h>
    #include <inttypes.h>
    #include <util/delay.h>
    #include <stdlib.h>
    #include "hd44780.h"
    
    #define KEY_1 (1<<0)
    #define KEY_2 (1<<1)
    #define KEY_3 (1<<2)
    
    // deklaracja funkcji w programie
    void intro(void);
    int liczba(void);
    int klawiatura(void);
    
    int main(void)
    {
    
    	volatile int suma = 0;	//trzeba osiagnac 33
    	volatile int osob = 0;	//kto gra? 1=bot, 2=osoby
    	volatile int start = 0;	//if(osob==1) then kto zaczyna? 1=bot, 2=osoba
    	char str[2];			//przechowywanie itoa(rand()%3,str,10)
    	volatile int los = 0;	//wpisana lub wylosowana liczba
    
    	DDRC &= ~KEY_1; PORTC |= KEY_1;
    	DDRC &= ~KEY_2; PORTC |= KEY_2;
    	DDRC &= ~KEY_3; PORTC |= KEY_3;
    
    	LCD_Initalize();
    	LCD_Clear();
    
    	intro();
    
    	while( osob==0 )
    	{
    		if ( !(PINC&KEY_1) ) {
    			LCD_Clear();
    			_delay_ms(20); 
    			LCD_WriteText( "Gra z komputerem" );
    			LCD_GoTo(0,1); LCD_WriteText( "1-komp  2-osoba" );
    			while( osob==0 || osob==3 ) osob=klawiatura();
    			if ( osob==1 ) {
    				_delay_ms(20); 
    				LCD_Clear();
    				LCD_WriteText( "Kto zaczyna?" );
    				LCD_GoTo(0,1); LCD_WriteText( "1-komp  2-osoba" );
    				while( start==0 || start==3 ) start=klawiatura();
    				break;
    			}
    			else if ( !(PINC&KEY_2) ) {
    				_delay_ms(20); 
    				break;
    			}
    		}
    	}
    	
    	int i = 0;
    	LCD_Clear();
    	while(suma<33)
    	{
    		los = 0;
    		LCD_GoTo(0,0); LCD_WriteText( "Suma=" );
    		LCD_GoTo(5,0); LCD_WriteText( itoa(suma,str,10) );
    		if ( osob==1 )
    		{
    			if ( start==1 )
    			{
    				if(suma==29)
    	                los = 3;
    	            else if(suma==30)
    	                los = 2;
    	            else if(suma==31)
    	                los = 1;
    				while( los==0 ) los=liczba();
    				LCD_GoTo(10,0); LCD_WriteText("Ko=");
    				LCD_WriteText( itoa(los,str,10) );
    				start = 2;
    			}
    			else
    			{
    				LCD_GoTo(0,1); LCD_WriteText("Podaj liczbe...");
    				while( los==0 ) los = klawiatura();
    				start = 1;
    			}
    			suma += los;
    			i++;
    		}
    		else
    		{
    			if ( i==0 ) start = 1;
    
    			if ( start==1 )
    			{
    				LCD_GoTo(0,1); LCD_WriteText("Osoba1 liczba...");
    				while( los==0 ) los = klawiatura();
    				LCD_GoTo(10,0); LCD_WriteText("O1=");
    				LCD_WriteText( itoa(los,str,10) );
    				start = 2;
    			}
    			else
    			{
    				LCD_GoTo(0,1); LCD_WriteText("Osoba2 liczba...");
    				while( los==0 ) los = klawiatura();
    				LCD_GoTo(10,0); LCD_WriteText("O2=");
    				LCD_WriteText( itoa(los,str,10) );
    				start = 1;
    			}
    			suma += los;
    			i++;
    		}
    	}
    	LCD_Clear();
    	if( osob==1 )
    	{
    		if( start==2 ) LCD_WriteText("WYGRAL czlowiek");
    		else LCD_WriteText("WYGRAL komputer");
    	}
    	else
    	{
    		if( start==2 ) LCD_WriteText("WYGRALA osoba2");
    		else LCD_WriteText("WYGRALA osoba1");
    	}
    
    return 0;
    }
    
    void intro(void)
    {
    	LCD_GoTo(1,0); LCD_WriteData(126);
    	LCD_GoTo(2,0); LCD_WriteData(126);
    	LCD_GoTo(5,0); LCD_WriteText( "Gra 33" );
    	LCD_GoTo(13,0); LCD_WriteData(127);
    	LCD_GoTo(14,0); LCD_WriteData(127);
    	LCD_GoTo(0,1); LCD_WriteText( "Szymon & Mariusz" );
    }
    
    int liczba(void)
    {
    	return 1+rand()%3;
    }
    
    int klawiatura(void)
    {
    	int klawisz = 0;
    	while( !(PINC&KEY_1) );
    	while( !(PINC&KEY_2) );
    	while( !(PINC&KEY_3) );
    	while( (PINC&KEY_1) && (PINC&KEY_2) && (PINC&KEY_3) )
    	{
    		if ( !(PINC&KEY_1) ) {
    			klawisz = 1;
    			while(!( PINC&KEY_1 ));
    			break;
    		}
    		else if ( !(PINC&KEY_2) ) {
    			klawisz = 2;
    			while(!( PINC&KEY_2 ));
    			break;
    		}
    		else if ( !(PINC&KEY_3) ) {
    			klawisz = 3;
    			while(!( PINC&KEY_3 ));
    			break;
    		}
    	}
    	
    	return klawisz;
    }


    I wszystko działa gdyby nie to, że nie raz niektóre przyciski muszę kilka razy wcisnąć zanim złapie sygnał.
    Myślę, że nie wynika to z błędu hardwerowego (uszkodzenia przycisków), a tego, że procesor poprzez bardzo nieoptymalne pętle while( !(PINC&KEY_1) ); czeka na zwolnienie sygnału z przycisków, które w niektórych wypadkach trwa i trwa... .
    Były by to do zniesienia gdyby za 2 razem zawsze przechodziło, ale nie raz kilkanaście sekund trzeba czekać aż zaskoczy :/

    Jak tego uniknąć w jak najprostszy sposób?
    Nie chcę bawić się z przerwaniami - nie znam ich, a także musiałbym przylutować przyciski. Do tego mam tylko 2 wejścia przerwań, a muszę obsłużyć 3 przyciski. Więc wolę ten temat zostawić. Tym bardziej, że termin projektu zbliża się nieubłaganie :P
  • REKLAMA
  • #2 7551732
    karol123
    Poziom 16  
    Jakbyś sam napisał ten program to byś wiedział
  • REKLAMA
  • #3 7551889
    BluePower
    Poziom 10  
    Sam napisałem ten program. Za dużej filozofii w nim nie ma - raptem parę if()'ów. Udowodnić swojego autorstwa nie zamierzam, bo nie jesteście moimi wykładowcami :) mi wystarczy własne przekonanie o tym.
    Chyba, że macie jakieś mocne dowody (np. wyniki wyszukiwania Google), które ewidentnie wskażą, że nie jest mój :] Możecie szukać, bo prawda będzie po mojej stronie.

    Inna sprawa, że jestem całkowicie zielony w programowaniu mikrokontrolerów, dlatego według Was zadaje takie podstawowe pytania, które mogą wskazywać na brak autorskich praw do programu.
    Ale to wynika tylko z tego, że nie znam się na tym, a nie że kopiuje czyjeś rozwiązania.


    Może ktoś będzie bardziej uczynny i podpowie jak poprawić program/układ?
  • REKLAMA
  • #4 7564631
    asembler
    Poziom 32  
    Czytanie przyciskow zawsze robie w przerwaniu i wtedy takie sytuacje nie mają prawa miec miejsca.
  • #5 7564825
    Krauser
    Poziom 26  
    1. Z funkcji
    int klawiatura(void)
    usuń
    
       while( !(PINC&KEY_1) );
       while( !(PINC&KEY_2) );
       while( !(PINC&KEY_3) ); 

    Poza tym
          if ( !(PINC&KEY_1) ) {
             klawisz = 1;
             while(!( PINC&KEY_1 )) _delay_ms(20);
             break;
          } 

    dodaj opóźnienia w celu eliminacji drgań styków.

    2. Użycie volatile jest niepotrzebne. Przecież to zmienne lokalne. A nawet jak by były globalne to i tak nie mogą się zmienić w każdym momencie bo nie używasz przerwań.

    3. Po co
    DDRC &= ~KEY_1; PORTC |= KEY_1;
    domyślnie wszystkie linie mikrokontrolera to wejścia pływające. Skoro masz zewnętrzne rezystory nie musisz nic robić. To nie używane linie portów powinieneś podciągnąć wewnętrznym rezystorem. Wejścia pływające zwiększą pobór prądu bo będą się same przełączać.
REKLAMA