uC

To forum jest dla wszystkich pasjonatów mikrokontrolerów AVR Atmela. Wymiana doświadczeń i pomoc dla początkujących w pisaniu programów zarówno w C, Asemblerze jak i BASCOM. Zapraszam znawców tematu, aby pomogli wszystkim początkującym!
keruseykaryu

Post autor: keruseykaryu » 14 lis 2011, 21:36

No dobra to muszę poczytać o flagach itp, dla podpowiedzi jakich funkcji użyłbyś w takim programie?
Przede wszystkim ISR(TIMERx_vect) jako przerwania licznika. A klawisze to możesz nawet na przerwaniach z PCINT zrobić. Wtedy wszystko chodzi na przerwaniach.

Awatar użytkownika
Dawid2379
Użytkownik
Posty: 318
Rejestracja: 17 lis 2010, 19:42
Lokalizacja: Kluczbork
Kontakt:

Post autor: Dawid2379 » 15 lis 2011, 14:53

A czytam o tych przerwaniach i ciężko. wiem tyle ze po zliczeniu impulsów licznik zgłasza przerwanie i można skoczyć do innej części programu i wykonać coś innego, można ustawić preskaler, do ilu ma zliczać i takie tam, no ale co, to teoria, nie prz wiem jak przełożyć to na kod tak aby przycisk bądź dwa wykonały jakiekolwiek operacje na bitach i oczywiście się powtarzały np. jeden przycisk odpowiada za miganie LED-ów drugi za szybsze miganie LED-ów, przykłady oparte są zazwyczaj na obsłudze wyświetlaczy 7-seg. itp jakoś nie umiem tego przerobić aby działało tak jak mi się podoba, posiada ktoś jeszcze jakieś kody bądź wie gdzie są proste przykłady do analizy, może jakieś z opisem?

Awatar użytkownika
dondu
Użytkownik
Posty: 211
Rejestracja: 24 maja 2005, 9:47
Lokalizacja: Śląskie
Kontakt:

Post autor: dondu » 20 lis 2011, 18:26

Dawid2379 pisze:A czytam o tych przerwaniach i ciężko
...
posiada ktoś jeszcze jakieś kody bądź wie gdzie są proste przykłady do analizy, może jakieś z opisem?
Zobacz tutaj: http://mikrokontrolery.blogspot.com/201 ... timer.html

Awatar użytkownika
Dawid2379
Użytkownik
Posty: 318
Rejestracja: 17 lis 2010, 19:42
Lokalizacja: Kluczbork
Kontakt:

Post autor: Dawid2379 » 21 lis 2011, 19:24

Hej pytanie odnośnie kodu z linku zauważyłem ze można ustawić licznik aby zaczął liczyć od 6 ok. A czy można ten licznik zatrzymać np przy innej wartości jeśli np przycisk jest wciśnięty?

Awatar użytkownika
Dawid2379
Użytkownik
Posty: 318
Rejestracja: 17 lis 2010, 19:42
Lokalizacja: Kluczbork
Kontakt:

Post autor: Dawid2379 » 23 lis 2011, 20:13

Hej prawie rozwiązałem swój problem w taki oto sposób. Prawie ponieważ wszystko działa tylko mam problem z przyciskiem, nie zawsze się załączają instrukcje w pętlach. Przycisk ma zwiększać zmienna "m" o 1 i w ten sposób maja się wykonywać instrukcje zależnie od wartości "m" , można to jakoś poprawić aby przełączało się po kolei??

Kod: Zaznacz cały

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

int main(void)
{
 

  /* Konfiguracja portów we/wy */
  DDRB = 0xFF;
  PORTB = 0xFF;  
  
  DDRD  = 0x00;
  PORTD = 0x04; 

 /* Definicja zmiennych */
  unsigned char m;
  m = 1;
  
  /* Głóna pętla programu */
   
    while(1)
    {

      
      
         if(!(PIND & 0x04))
	        _delay_ms(80);
            if(!(PIND & 0x04))
			  
              m+=1;

	           if(m==5)
		          m=1;	
	    
		        {  if(m==2)
				      {
					    PORTB = 0xFF;
		              }
	               if(m==3)
                      {
		                PORTB = 0xFE;
	                    _delay_ms(50);
		                PORTB = 0xFC;
		                _delay_ms(50);
		                PORTB = 0xF8;
                        _delay_ms(50);
		                PORTB = 0xF1;
		                _delay_ms(50);
		                PORTB = 0xE3;
		                _delay_ms(50);
		                PORTB = 0xC7;
		                _delay_ms(50);
		                PORTB = 0x8f;
		                _delay_ms(50);
		                PORTB = 0x1F;
		                _delay_ms(50);
		                PORTB = 0x3F;
		                _delay_ms(50);
		                PORTB = 0x7F;
		                _delay_ms(50);
		                PORTB = 0x3F;
                        _delay_ms(50);
		                PORTB = 0x1F;
		                _delay_ms(50);
	               	    PORTB = 0x8F;
		                _delay_ms(50);
		                PORTB = 0xC7;
		                _delay_ms(50);
		                PORTB = 0xE3;
		                _delay_ms(100);
		                PORTB = 0xF1;
		                _delay_ms(50);
		                PORTB = 0xF8;
		                _delay_ms(50);
		                PORTB = 0xFC;
		                _delay_ms(50);

                      } 
         
         
        
	    
	               if(m==4)
                      {
		               PORTB= 0xAA;
		               _delay_ms(200);
		               PORTB= 0x55;
		               _delay_ms(200);
                      } 
		 
		 
	    	} 
         
      
      } 

}

Awatar użytkownika
Dawid2379
Użytkownik
Posty: 318
Rejestracja: 17 lis 2010, 19:42
Lokalizacja: Kluczbork
Kontakt:

Post autor: Dawid2379 » 23 lis 2011, 20:15

Wydaje mi się ze kiedy wykonuje się dana instrukcja i wciskając w tym momencie przycisk uC nie bada stanu przycisku, przez co zmienna nie zwiększa się o 1. ?

keruseykaryu

Post autor: keruseykaryu » 23 lis 2011, 21:36

Jak ci ma program badać przyciski i być z nimi na bieżąco jak ciągle ląduje gdzieś w delayu?

Awatar użytkownika
Dawid2379
Użytkownik
Posty: 318
Rejestracja: 17 lis 2010, 19:42
Lokalizacja: Kluczbork
Kontakt:

Post autor: Dawid2379 » 23 lis 2011, 21:38

No właśnie o tym pisałem wyżej, to co można z tym zrobić?

keruseykaryu

Post autor: keruseykaryu » 24 lis 2011, 6:50

O przerwaniach też pisałem już wyżej.

Awatar użytkownika
Dawid2379
Użytkownik
Posty: 318
Rejestracja: 17 lis 2010, 19:42
Lokalizacja: Kluczbork
Kontakt:

Post autor: Dawid2379 » 24 lis 2011, 20:15

Pisałeś, pisałeś, ale ja przyznam chciałem uciec od przerwań... teraz ten kod mi działa, muszę zmienić trochę bo trzymam przycisk 1s aby przełączało. A w ogóle co Wy na to?

Kod: Zaznacz cały

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

volatile uint8_t m;


int main(void)
{
 

  /* Konfiguracja portów we/wy */
  DDRB = 0xFF;
  PORTB = 0xFF;  
  
  DDRD  = 0x10;
  PORTD = 0x04; 
  
  m = 1;

TCCR1B |= (1 << WGM12); // Ustawia timer w tryb CTC
OCR1A = 15625; // Ustawia wartość pożądaną na 1Hz dla preskalera 64
TCCR1B |= ((1 << CS10) | (1 << CS11)); // Ustawia timer z preskalerem Fcpu/64
TIMSK |= (1 << OCIE1A); // Zezwolenie na przerwania dla CTC
sei(); // Zezwolenie globalne na przerwania


  /* Głóna pętla programu */
   
    while(1)
    {

      
      
         
	    
		        {  if(m==2)
				      {
					    PORTB = 0xFF;
		              }
	               if(m==3)
                      {
		                PORTB = 0xFE;
	                    _delay_ms(50);
		                PORTB = 0xFC;
		                _delay_ms(50);
		                PORTB = 0xF8;
                        _delay_ms(50);
		                PORTB = 0xF1;
		                _delay_ms(50);
		                PORTB = 0xE3;
		                _delay_ms(50);
		                PORTB = 0xC7;
		                _delay_ms(50);
		                PORTB = 0x8f;
		                _delay_ms(50);
		                PORTB = 0x1F;
		                _delay_ms(50);
		                PORTB = 0x3F;
		                _delay_ms(50);
		                PORTB = 0x7F;
		                _delay_ms(50);
		                PORTB = 0x3F;
                        _delay_ms(50);
		                PORTB = 0x1F;
		                _delay_ms(50);
	               	    PORTB = 0x8F;
		                _delay_ms(50);
		                PORTB = 0xC7;
		                _delay_ms(50);
		                PORTB = 0xE3;
		                _delay_ms(100);
		                PORTB = 0xF1;
		                _delay_ms(50);
		                PORTB = 0xF8;
		                _delay_ms(50);
		                PORTB = 0xFC;
		                _delay_ms(50);

                      } 
         
         
        
	    
	               if(m==4)
                      {
		               PORTB= 0xAA;
		               _delay_ms(200);
		               PORTB= 0x55;
		               _delay_ms(200);
                      } 
		 
		 
	    	} 
         
      
      } 

}



ISR(TIMER1_COMPA_vect)
{  
  {
  
  PORTD ^= (1 << PIN4); // zmiana stanu diody Led
  if(!(PIND & 0x04))
   { 
       m++;
     if(m==5)
	   m = 1;
    
   } 
  }  
}  


keruseykaryu

Post autor: keruseykaryu » 25 lis 2011, 6:31

Tylko, że w tym programie, aż się prosi o przerwania. Przynajmniej te z licznika do samodzielnego generowania efektu w tle.

Awatar użytkownika
Dawid2379
Użytkownik
Posty: 318
Rejestracja: 17 lis 2010, 19:42
Lokalizacja: Kluczbork
Kontakt:

Post autor: Dawid2379 » 25 lis 2011, 18:51

No tak.. zewnętrzne, rozwiązałem to tak, działa fajnie i jest ok z tym ze momentami przycisk zawodzi tzn coś musi być z drganiami styków, za szybko zmienia się zmienna "m", czasem przeskakuje o 1 za dużo, ale juz mnie efekt zadowala.

Kod: Zaznacz cały

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

volatile uint8_t m;


int main(void)
{
 
  
  DDRB = 0xFF; // Port B wyjscie//
  PORTB = 0xFF;  //stan niski po wlaczeniu zasilania//
  
  DDRD  = 0x10; //jedno wyjscie dla sprawdzenia dzialania przerwania//
  PORTD = 0x04; //podciagniecie rezystora do + i wlaczona dioda na poczatek//
 
  m = 0; //wartos poczatkowa zmiennej 'm'//

  MCUCR |= (1<<ISC10);  // konfiguracja przerwania od INT0, reakcja na zbocze opadajace
  GIMSK |= (1<<INT0);	// zezwolenie na przerwanie od INT0//
  sei();				// włączenie przerwań//


  /* Głóna pętla programu */
   
    while(1)
    {

            {
      
		           if(m==0)
				      {
					    PORTB = 0xFF;
		              }
	               if(m==1)
                      {
		                PORTB = 0xFE;
	                    _delay_ms(50);
		                PORTB = 0xFC;
		                _delay_ms(50);
		                PORTB = 0xF8;
                        _delay_ms(50);
		                PORTB = 0xF1;
		                _delay_ms(50);
		                PORTB = 0xE3;
		                _delay_ms(50);
		                PORTB = 0xC7;
		                _delay_ms(50);
		                PORTB = 0x8f;
		                _delay_ms(50);
		                PORTB = 0x1F;
		                _delay_ms(50);
		                PORTB = 0x3F;
		                _delay_ms(50);
		                PORTB = 0x7F;
		                _delay_ms(50);
		                PORTB = 0x3F;
                        _delay_ms(50);
		                PORTB = 0x1F;
		                _delay_ms(50);
	               	    PORTB = 0x8F;
		                _delay_ms(50);
		                PORTB = 0xC7;
		                _delay_ms(50);
		                PORTB = 0xE3;
		                _delay_ms(100);
		                PORTB = 0xF1;
		                _delay_ms(50);
		                PORTB = 0xF8;
		                _delay_ms(50);
		                PORTB = 0xFC;
		                _delay_ms(50);

                      } 
	               if(m==2)
                      {
		               PORTB= 0xAA;
		               _delay_ms(200);
		               PORTB= 0x55;
		               _delay_ms(200);
                      } 
		           if(m==3)
                      {
		               PORTB= 0xFF;
                      } 
			  } 
         
      } 

}

ISR(INT0_vect) //obsluga przerwania//
{  
   
  PORTD ^= (1 << PIN4); // zmiana stanu diody kontrolnej//

  
  _delay_ms(100); // eliminacja drgan?????//
    
       m++;
     if(m==4)// jesli m=4 przypisz spowrotem 0//
	   m = 0; 
}  

 

keruseykaryu

Post autor: keruseykaryu » 26 lis 2011, 7:02

Dalej robisz to "od zada". Przemiatanie efektu na przerwaniach, klawiatura normalnie w pętli.
I nigdy, przenigdy takich kwiatków jak _delay_ms(100) w przerwaniu. Za taki kod niejeden by ci powiedział "do widzenia".

Awatar użytkownika
dondu
Użytkownik
Posty: 211
Rejestracja: 24 maja 2005, 9:47
Lokalizacja: Śląskie
Kontakt:

Post autor: dondu » 26 lis 2011, 19:57

Tak jak wspomina kolega:
keruseykaryu pisze:I nigdy, przenigdy takich kwiatków jak _delay_ms(100) w przerwaniu.
dlatego, że: http://mikrokontrolery.blogspot.com/201 ... wania.html

Awatar użytkownika
Dawid2379
Użytkownik
Posty: 318
Rejestracja: 17 lis 2010, 19:42
Lokalizacja: Kluczbork
Kontakt:

Post autor: Dawid2379 » 27 lis 2011, 20:46

Ok, nigdy _delay_ w przerwaniu. Ale pomijając to, co jest głównie wadą mojego kodu? I jeśli chodzi o przewijanie efektu w przerwaniu czy tak to miałoby by wyglądać:
1. muszę pozbyć się co jasne _delay_ms, wiec potrzebuje jakiejś zmiennej? dzięki której po kolei wykonują się zmiany na wyjściach
2. dwa efekty świetlne wiec dwa przerwania? czy można w jednym?
3. przycisk w głównej pętli, tu nie wiem co miałoby przełączać poszczególne efekty?
Proszę o małą pomoc:)

ODPOWIEDZ