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

[c][atmega8] Błąd przy wyświetlaniu na LCD,instrukcja switch

peterrrm 02 Gru 2009 20:01 2016 5
REKLAMA
  • #1 7337484
    peterrrm
    Poziom 14  
    Witam ,
    Mam pewien problem nie rozumie dlaczego poniższy kod nie działa prawidłowo:
    				while(!esc)   //jesli nacisniete ESC to wychodzi
    					{
    					LCD_Clear();
    					LCD_WriteText("ok-zamknij");
    					LCD_GoTo(0,1);
    					LCD_WriteText("v-otworz");
    					_delay_ms(100);
    					while(ok)
    						{
    						_delay_ms(400);
    						zamykanie_on;
    						LCD_Clear();
    						LCD_WriteText("zamykanie");
    						}
    					
    					while(v)
    						{
    						otwieranie_on;
    						LCD_Clear();
    						LCD_WriteText("otwieranie");
    						_delay_ms(100);
    						}
    						
    					zamykanie_off;
    					otwieranie_off;
    					}
    				break;
    				}

    Gdy w while(V) znajduje się obsługa LCD to nie działa przetwarzanie ADC w całym programie. Jeśli natomiast usunę :
    LCD_Clear() oraz LCD_WriteText("otwieranie");
    ADC działa normalnie w całym programie. Co Ciekawe w tym kawałku kodu nie wywołuje przetwarzania ani nic z nim związanego.
    Dobrze jest również wtedy jeśli bym usunął:
    LCD_Clear() oraz LCD_WriteText("zamykanie");
    po prostu nie może być jednocześnie w while(v) i while(ok) , obsługa LCD. Ale nie rozumie dlaczego i jak w takim razie wyświetlać w danym momencie to co chcę?


    Przycisk "Pisownia" został użyty.

    Post był raportowany.
    Popraw błędy i interpunkcję. Użyj przycisku PISOWNIA -->REGULAMIN pkt 15.
    Początek zdania? Zaczynamy wielką literą.
    Następnym razem będzie UPOMNIENIE. [hefid]
  • REKLAMA
  • #2 7337665
    tmf
    VIP Zasłużony dla elektroda
    Jesli nie pokazesz calego kodu to potrzebna bedzie szklana kula.
    esc, ok i v jak sie domyslam modyfikujesz w jakims przerwaniu albo w tych funkcjach zamykanie_on i otwieranie_on? Jesli w przerwaniach to pamietales o volatile? ADC dziala na przerwaniach?
  • REKLAMA
  • #3 7338154
    peterrrm
    Poziom 14  
    Oto cały kod:
    #include <avr/io.h>
    #include <inttypes.h>
    #include <bity.h>
    #include <util/delay.h>
    #include <hd44780.c>
    #include <stdlib.h>
    #include <avr/interrupt.h>
    
    
    #define esc (!(PIND&0x08))  //sprawdzenie pinu "ESC" czy wcisniety
    #define ok (!(PIND&0x10)) //sprawdzenie pinu "OK" czy wcisniety
    #define v (!(PINC&0x20)) //sprawdzenie pinu "V" czy wcisniety
    #define pompa_on PORTD|=(1<<2)  //zalaczenie pompy
    #define pompa_off PORTD&=0xfb   //wylaczenie pompy
    #define zamykanie_on PORTD|=(1<<1) ,PORTD&=0xfe //zalaczenie zamykania zaworu
    #define zamykanie_off PORTD&=0xfd   //wylaczenie zamykania zaworu
    #define otwieranie_on PORTD|=(1<<0) ,PORTD&=0xfd //zalaczenie otwierania zaworu
    #define otwieranie_off PORTD&=0xfe   //wylaczenie otwierania zaworu
    
    
    
    double konwersja;		// Zmienna do przechowywania wyniku pomiaru
    char buffer_n[5];    	    // Bufor do przechowywania wyniku konwersji z "double" na ASCII
    double tem=0;  //zmienna dla wyniku pomiaru cisnienia   
    int a=0;  //zmienna dla petli przy wyswietlaniu napisu
    char buffer[5];
    
    void Inicjalizacja(void)   //funkcja inicjalizacji LCD i przetwornika ADC
    {
    // Inicjalizacja LCD  
    	LCD_Initalize();		// Inicjalizacja wyswietlacza
    	LCD_Clear();		
    // Wybranie wewnętrznego żródła napięcia odniesienia	
    	ADMUX |= _BV(REFS0);		
    	ADMUX |= _BV(REFS1);		
    // Zezwolenie na konwersję	
    	ADCSRA |= _BV(ADEN);		
    // Wybranie częstotliwości dla taktowania przetwornika  (1/8 częstotliwosci zegara kontrolera) 
    	ADCSRA |= _BV(ADPS0);	 
    	//ADCSRA |= _BV(ADPS1);	//	
    }
    
    
    char pomiar(void)  //funkcja dokonująca pomiaru 
    {	int i;
    	tem=0; 
    	for(i=0;i<80;i++)                  //petla pomiarowa
    		{
    		ADCSRA |= _BV(ADSC);         // Rozpoczęcie przetwarzania
    		
    		while(bit_is_set(ADCSRA,ADSC))	// Oczekiwanie na zakończenie przetwarzania
    		{};	
    		konwersja=(double)ADCW;			     // Zapisanie  wyniku konwersji do zmiennej "konwersja"									
    		tem=tem+(double)konwersja*1.570454-400;	
    	_delay_ms(1);
    		}
    	tem=tem/80;    //wyliczenie sredniej wartosci	
    	dtostrf(tem, 1,0,buffer_n);// Konwersja liczby double  do asci
    	return buffer_n;  //funkcja zwraca buffer_n czyli wartosc cisnia w kodzie ASCI
    }
    
    
    
    int main(void)
    {
    	DDRC|=(1<<4)|(1<<3); // ustawienie pin 3 i 4 portu C jako wyjscie
    	DDRD|=(1<<0)|(1<<1)|(1<<2)|(1<<6);	// ustawienie pin 0 ,1,2 portu D jako wyjscie
    	
    	
    	//domyslnie wszystkie wejscia
    	PORTC|=(1<<5);  //podciagniecie wejscia pin 5 portu C do VCC  
    	PORTD|=(1<<3)|(1<<4);  //podciagniecie wejscia pin 3 i 4 portu D do VCC
    	
    	Inicjalizacja();  // Inicjalizacja ADC i LCD
    	
    
    	for(a=0;a<16;a++)
    	{
    	LCD_GoTo(a,1);
    	LCD_WriteText("Witaj");
    	_delay_ms(5);
    	LCD_GoTo(0,1);
    	LCD_WriteText("                ");
    	LCD_GoTo(0,0);
    	}
    	
    	
    	
    	
    	a=1; // a=1 dla prawidlowego dzialania menu
    	
    	while(1)
    	{
    
    		
    		if(v) a=a+1;  //menu wyboru opcji
    		if(a>4) a=0;
    		switch(a)  
    			{
    				case 1 : 
    				{
    				LCD_Clear();
    				LCD_WriteText("Wybierz opcje");
    				LCD_GoTo(0,1);
    				LCD_WriteText("Tryb automat.");
    				break;
    				}
    				case 2 : 
    				{
    				LCD_Clear();
    				LCD_WriteText("Wybierz opcje");
    				LCD_GoTo(0,1);
    				LCD_WriteText("Pomiar cis.");
    				break;
    				}
    				case 3 : 
    				{
    				LCD_Clear();
    				LCD_WriteText("Wybierz opcje");
    				LCD_GoTo(0,1);
    				LCD_WriteText("Praca pompy");
    				break;
    				}
    				case 4 : 
    				{
    				LCD_Clear();
    				LCD_WriteText("Wybierz opcje");
    				LCD_GoTo(0,1);
    				LCD_WriteText("Praca zaworu");
    				break;
    				}
    			}
    		_delay_ms(300);
    		
    		
    		if(ok)  // po wcisnieciu ok wejscie do menu
    		{
    			switch(a)  
    			{
    				case 1 : 
    				{
    					while(a!=4)  //jesli a rozne od 4 to wykonuje petle po skonczeniu ustawia a=4
    					{
    						LCD_Clear();
    						LCD_WriteText("proba 1h");
    						_delay_ms(1000);
    						a=4;
    					}
    				break;
    					
    				}
    				case 2 : 
    				{
    					while(!esc)   //jesli nacisniete ESC to wychodzi
    					{
    						LCD_Clear();
    						LCD_WriteText("Pomiar cis.");
    						LCD_GoTo(0,1);
    						LCD_WriteText("P=");
    						LCD_WriteText(pomiar());
    						LCD_WriteText("mbar");
    						_delay_ms(100);
    					}
    				break;
    				}
    				case 3 : 
    				{
    				while(!esc)   //jesli nacisniete ESC to wychodzi
    					{
    					LCD_Clear();
    					LCD_WriteText("Praca pompy");
    					LCD_GoTo(0,1);
    					LCD_WriteText("V-wlacz pompe");
    					_delay_ms(100);
    						while(v)
    							{
    							pompa_on;
    							LCD_WriteText("                "); //zamiast: LCD_Clear() ,zapobiega to migotaniu LCDeka
    	LCD_GoTo(0,0);
    							LCD_WriteText("Praca pompy");
    							LCD_GoTo(0,1);
    							LCD_WriteText("P=");
    							LCD_WriteText(pomiar());
    							LCD_WriteText("mbar");
    							_delay_ms(100);
    							}
    					pompa_off;
    					}
    				break;
    				}
    				case 4 : 
    				{
    				while(!esc)   //jesli nacisniete ESC to wychodzi
    					{
    					LCD_Clear();
    					LCD_WriteText("ok-zamknij");
    					LCD_GoTo(0,1);
    					LCD_WriteText("v-otworz");
    					_delay_ms(100);
    					while(ok)
    						{
    						_delay_ms(400);
    						zamykanie_on;
    						LCD_Clear();
    						LCD_WriteText("zamykanie");
    						}
    					
    					while(v)
    						{
    						otwieranie_on;
    						LCD_Clear();
    						LCD_WriteText("otwieranie");
    						_delay_ms(100);
    						}
    						
    					zamykanie_off;
    					otwieranie_off;
    					}
    				break;
    				}
    			}
    		}
    	}
    	return 0;
    	
    }
    
    
    
    	
    
    
    
    
    
    
    
    
    
    
    
    


    ok,esc,v - to przyciski. Ani przyciski ani ADC nie są obsługiwane w przerwaniach. Jeśli wyrzucę pierwsze switch(a) a resztę zostawię bez zmian to wtedy też działa dobrze.
  • REKLAMA
  • Pomocny post
    #4 7338453
    tmf
    VIP Zasłużony dla elektroda
    Pewnie bledow masz wiele, ale zacznijmy od poczatku:
       dtostrf(tem, 1,0,buffer_n);// Konwersja liczby double  do asci
       return buffer_n;  //funkcja zwraca buffer_n czyli wartosc cisnia w kodzie ASCI 


    dtostrf nie sprawdza dlugosci bufora, ktory u ciebie wynosi 5 bajtow, w tym musisz miec miejsce na znak konca strungu. Czyli 4 bajty zostaja, konwertujesz typ double, ktory moze zawierac liczby o dlugosci wiekszej niz 4 znaki (9999), wiec funkcja ta nadpisuje to co jest za buforem.
    Poza tym powinienes o ile juz musisz (bo po co skoro definiujesz bufor jako zmienna globalna) zwracac wskaznik na bufor.
    Po case klamry nie sa potrzebne, a umieszczenie w nich break nie zadziala tak jak myslisz. To tak na szybko, zapewne to ci nie zlikwiduje bledu, ale popraw kod, pomyslimy co dalej.
  • REKLAMA
  • #5 7342203
    peterrrm
    Poziom 14  
    Dziękuje bardzo za pomoc!

    Po zamianach ADC działa:)

    Jeśli mogę prosić to wyjaśnij trochę więcej o co z tym chodzi:
    Cytat:
    dtostrf nie sprawdza dlugosci bufora, ktory u ciebie wynosi 5 bajtow, w tym musisz miec miejsce na znak konca strungu. Czyli 4....


    Dziękuje jeszcze raz i pozdrawiam
  • #6 7343110
    tmf
    VIP Zasłużony dla elektroda
    Funkcja ta konwertuje zmienna typu double (ten typ na AVR nie jest supportowany, jest to rownowazne z typem float) na string, do bufora, ktorego adres podajesz jako jeden z parametrow. Bufor musi byc na tyle duzy, zeby pomiescic maksymalna konwertowana liczbe + jeden bajt na znak konczacy string (0). Jesli masz bufor o dl. np. 5 bajtow a sprobujesz skonwertowac liczbe 12345 to w efekcie zmienna, ktora w pamieci jest alokowana za buforem zostanie nadpisana (do konwersji potrzebujesz 5 bajtow na kolejne cyfry + 1 na znak konca). W efekcie to co sie stanie zalezy od tego co tam dalej w pamieci jest - czasami zadziala, czasami nadpisze kolejna zmienna, czasami ta zmienna nadpisze np. znak konca tekstu w buforze i jak sprobujesz go przetworzyc to program sie albo wykrzaczy, albo wyswietli dziwne znaki.
REKLAMA