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

AVR-GCC przekazywanie zmiennej przez wartość (?) ;/

bitches_brew 06 Gru 2008 13:53 1421 1
REKLAMA
  • #1 5824273
    bitches_brew
    Poziom 10  
    Witam!
    Napisałem program który moim zdaniem powinien działać tak samo, a nie działa. Byłbym wdzięczny gdyby ktoś mógł rzucić na to okiem...

    Program służy do obsługi serw bez użycia timerów. Dla ATMega16.

    1 przypadek, działający:
    
    #define F_CPU            1000000ul
    #define SBI(port,bit) (port)|= (1 << (bit))
    #define CBI(port,bit) (port) &= ~(1 << (bit))
    #include <util/delay.h>
    #include <avr/io.h>
    
    void powtarzaj_15(int ile){
      volatile long unsigned int i;
      for(i=0;(i<ile);i++){
        SBI(PORTD,PD7);
        _delay_us(1500);
        CBI(PORTD,PD7);
        _delay_us(18500);
      }
    }
    
    int main(void){
    
      SBI(DDRD,PD7);
      while(1){
        powtarzaj_15(25);
      }
      return 0;
    }

    Serwo ładnie ustawia 90 st.

    W tym przypadku jednak już nie działa:
    #define F_CPU            1000000ul
    #define SBI(port,bit) (port)|= (1 << (bit))
    #define CBI(port,bit) (port) &= ~(1 << (bit))
    #include <util/delay.h>
    #include <avr/io.h>
    
    void powtarzaj(int ile,int wyp,int res){
      volatile long unsigned int i;
      for(i=0;(i<ile);i++){
        SBI(PORTD,PD7);
        _delay_us(wyp);
        CBI(PORTD,PD7);
        _delay_us(res);
      }
    }
    
    int main(void){
    
      SBI(DDRD,PD7);
      while(1){
        powtarzaj(25,1500,18500);
      }
      return 0;
    }
    

    tym razem serwo wychyla się maksymalnie w jedną stronę ;/

    Dodam tylko, że do testów podłączyłem diodę do PD7. W pierwszym przypadku blado się świeciła. Natomiast w drugim mruga tak, że jest to widoczne dla oka.
    Ponadto w pierwszym przypadku program wgrywa się na ATMegę kilka sekund... w drugim kilkadziesiąt.

    pozdrawiam

    Regulamin, punkty 8.3 i 11.2. Temat poprawiłem.
    Przeniosłem z "Programowanie ogólne"

    Pozdrawiam,
    Dr.Vee
  • REKLAMA
  • #2 5824522
    BoskiDialer
    Poziom 34  
    Problem był już poruszany wiele razy w dziale "Mikrokontrolery Ogólne": _delay_us to makro, nie funkcja. Wymagane jest, aby parametr był liczbą stałą, w przeciwnym przypadku zostanie wkompilowana biblioteka liczb zmiennoprzecinkowych, a same opóźnienia będą nieporównywalnie dłuższe.

    Jeśli chcesz mieć opóźnienie zmienne do zegara 1MHz, możesz skorzystać z funkcji:
    static void _delay_us_var(unsigned int waitus) __attribute__((always_inline)); 
    static void _delay_us_var(unsigned int waitus) 
    { 
       asm volatile( 
          "_loop_%=:"   "nt" 
          "sbiw %0, 4"   "nt" 
          "brsh _loop_%=" 
       ::"w"(waitus) 
       ); 
    }
    Powinna działać.

    Optymalizacja WinAVR
REKLAMA