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

WinAvr nie kompiluje - błąd fdevopen w projekcie z ATMega8

Xaveri 01 Lut 2008 11:28 3708 10
REKLAMA
  • #1 4758208
    Xaveri
    Poziom 17  
    Posty: 460
    Pomógł: 13
    Ocena: 77
    Witam,
    Jest sobie termostat do laminatora oparty o ATMega8 - dzieło ze strony:
    http://thomaspfeifer.net/laminator_temperatur_regelung.htm

    Ponieważ zrobiłem swoją wersję tego urządzenia wzbogaconą o dodatkowe funkcje, muszę zmodyfikować program, a z programowaniem w C nie miałem dotąd za wiele wspólnego...
    Na początek postanowiłem sprawdzić działanie swojego kompilatora [WinAvr] i okazuje się, że wywala on błąd na linii:
    
    fdevopen (uart_putchar, NULL, 0);
    

    Cały kod programu zamieszczam poniżej...
    Co mu nie pasuje ?

    
    #include <avr/io.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    #define F_CPU 8000000UL  // 8 MHz
    #define SOLLWERT 150 //<= gibt die Solltemperatur (ADC-Wert) an, TODO: Autom. Umrechnung von °C
    #define BAUD_RATE 9600
    
    #include <util/delay.h>
    
    void adcinit();
    int getadc(uint8_t channel);
    void waitms(int ms);
    
    
    
    int uart_putchar (char c)
    //############################################################################
    {
      if (c == '\n')
        uart_putchar('\r');
      //Warten solange bis Zeichen gesendet wurde
      loop_until_bit_is_set(UCSRA, UDRE);
      //Ausgabe des Zeichens
      UDR = c;
      return (0);
    }
    
    void UART_Init (void) {
      //Enable TXEN im Register UCR TX-Data Enable
      UCSRB=(1 << TXEN);
      //Teiler wird gesetzt
      UBRRL=(F_CPU / (BAUD_RATE * 16L) - 1);
    
      //öffnet einen Kanal für printf (STDOUT)
      fdevopen (uart_putchar, NULL, 0);
    }
    
    int convert2degree(int value) {
      static const float c1=19.5;
      static const float v1=275;  //ADC-Wert=264 @ 20°C
    
      static const float c2=202;
      static const float v2=154;  //ADC-Wert=165 @ 202°C
    
    
      float m=((c1-c2)/(v1-v2));
      return((int)((m*(float)value)+(-m*v1)+c1));
      //return((int)((-m*v1)+c1));
    }
    
    
    
    
    int main (void) {
      int val;
      int pwm;
      int pwm_ctr=0;
    
      adcinit();
      UART_Init();
    
      DDRC  = 0b00000000;
    
      DDRB  = 0b00000000;
      PORTB = 0b00000000;
    
      DDRD  = 0b11100000;  // 1=Output, 0=Input
    
    
      PORTD = 0b11100000;  //on
    
    
      printf("ok\n");
    
      while (1==1) {
        waitms(100);
    
        val=getadc(0);
        printf("%d %d %d %d\n",pwm,pwm_ctr,val,convert2degree(val)); //debug
        //printf("%d \n",convert2degree(val));
    
        pwm_ctr++;
        if (pwm_ctr>=10) pwm_ctr=0;
    
        pwm=val-SOLLWERT;
        if (pwm<0) pwm=0;
    
        if (pwm<pwm_ctr || val<100 || val>1000) { //pwm, detect Sensor contakt break/short
          PORTD = 0b01000000;  //off
        } else {
          PORTD = 0b11100000;  //on
        }
    
      }
    
    }
    
    void adcinit() {
      // Activate ADC with Prescaler 16 --> 1Mhz/16 = 62.5kHz
      //ADCSRA = _BV(ADEN) | _BV(ADPS2);
      ADCSRA = _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1);
      ADMUX=  0;
    }
    
    int getadc(uint8_t channel) {
      // Select pin ADC0 using MUX
      ADMUX = channel | _BV(REFS0) | _BV(REFS1);
    
      //Start conversion
      ADCSRA |= _BV(ADSC);
    
      // wait until converstion completed
      while (ADCSRA & _BV(ADSC) ) {}
    
        // get converted value
      return(ADCW);
    }
    
    void waitms(int ms) {
      int i;
      for (i=0;i<ms;i++) _delay_ms(1);
    }
    
  • REKLAMA
  • #2 4758301
    MinisterQ
    Poziom 18  
    Posty: 316
    Pomógł: 17
    Ocena: 16
    Nie napisałeś jaki konkretnie błąd wywala kompilator...
    Możliwe są dwa scenariusze:
    fdevopen (uart_putchar, NULL, 0); to funkcja lub makro, do którego kompilator musi się odwołać. A żeby się do tego odwołać, musi mieć... do czego. Sprawdź w jakim pliku nagłówkowym avr jest zadeklarowana ta funkcja bądź makro, i dołącz tą definicję do Twojego źródła.
    Ewentualnie przekazujesz nieprawidłową ilość parametrów, bądź nieprawidłowe typy.
  • #3 4758407
    Xaveri
    Poziom 17  
    Posty: 460
    Pomógł: 13
    Ocena: 77
    Rzeczywiście nie podałem komunikatów...
    Już to nadrabiam:

    
    Laminator.c:66: warning: passing argument 1 of 'fdevopen' from incompatible pointer type
    Laminator.c:66: error: too many arguments to function 'fdevopen'
    
  • REKLAMA
  • #4 4758680
    MinisterQ
    Poziom 18  
    Posty: 316
    Pomógł: 17
    Ocena: 16
    Xaveri napisał:
    Rzeczywiście nie podałem komunikatów...
    Już to nadrabiam:

    
    Laminator.c:66: warning: passing argument 1 of 'fdevopen' from incompatible pointer type
    Laminator.c:66: error: too many arguments to function 'fdevopen'
    


    No i wszystko jasne.
    Funkcja fdevopen oczekuje mniejszej ilości argumentów niż Ty jej zapodajesz, dodatkowo pierwszy z nich jest argumentem nieodpowiedniego typu.
    Znajdź definicję tej funkcji w inkludach, i zobacz sobie jakich parametrów oczekuje.
  • REKLAMA
  • #5 4758893
    Xaveri
    Poziom 17  
    Posty: 460
    Pomógł: 13
    Ocena: 77
    To nie jest mój program. Ten Niemiec dołącza plik hex więc jemu się to jakoś kompilowało.

    Co do funkcji fdevopen to znalazłem...
    
    	fdevopen (int(*put)(char, FILE *), int(*get)(FILE *))
    


    Po usunięciu zera z linii:
    
      fdevopen (uart_putchar, NULL, 0);
    


    kompiluje się z ostrzeżeniem:
    
    Laminator.c:66: warning: passing argument 1 of 'fdevopen' from incompatible pointer type
    


    Niekompatybilny wskaźnik - o co chodzi?
  • REKLAMA
  • Pomocny post
    #6 4759028
    MinisterQ
    Poziom 18  
    Posty: 316
    Pomógł: 17
    Ocena: 16
    Xaveri napisał:

    Niekompatybilny wskaźnik - o co chodzi?


    Chodzi o funkcję
    
    int uart_putchar (char c) 
    


    Wedle definicji funkcji:
    
    	fdevopen (int(*put)(char, FILE *), int(*get)(FILE *))
    


    fdevopen oczekuje jako pierwszego argumentu wskaźnika na funkcję, która przyjmuje dwa parametry. Twoje uart_putchar() które zapodajesz jako parametr dla fdevopen() przyjmuje jeden parametr.
    By to poprawić najprościej, wystarczy zmienić definicję uart_putchar() na taką:

    
    int uart_putchar (char c, FILE *f) 
    


    Do tego zmienić w źródle wywołania uart_putchar(), podając drugi parametr jako NULL, i powinno śmigać bez warningów.
    Można zamiast tego zrobić rzutowanie przy wywołaniu fdevopen() na odpowiedni typ, jakiego wymaga ta funkcja.
  • #7 4759197
    Xaveri
    Poziom 17  
    Posty: 460
    Pomógł: 13
    Ocena: 77
    Dzięki! Zadziałało...

    Teraz spróbuję napisać kawałek kodu, który na naciśnięcie przycisku będzie zmieniał docelową temperaturę.
    Teraz jest nastawa 202°C. a ma być 160°C i po jednokrotnym naciśnięciu przycisku zmieniać się na 200°C. Kolejne naciśnięcie oznacza powrót do 160°C...

    Na początek zrobię zapalanie leda a potem już powinno być z górki...

    No i klops - WinAvr chce nawiasu, ale jak mu go wstawiam to dalej jest źle:
    
    	if (PORTD.2 == (0)); {
    	PORTD.7 = (1);
    	} else {
    	PORTD.7 = (0);
    	}
    


    powoduje błędy:
    Laminator.c:126: error: expected ')' before numeric constant
    Laminator.c:127: error: expected ';' before numeric constant
    Laminator.c:128: error: expected expression before 'else'
  • #8 4759330
    MinisterQ
    Poziom 18  
    Posty: 316
    Pomógł: 17
    Ocena: 16
    Xaveri napisał:

    
    	if (PORTD.2 == (0)); {
    	PORTD.7 = (1);
    	} else {
    	PORTD.7 = (0);
    	}
    



    Usuń średnik po if (PORTD.2 == (0)); <--
    Podstawy! ;)
  • #9 4759456
    Xaveri
    Poziom 17  
    Posty: 460
    Pomógł: 13
    Ocena: 77
    
    #include <avr/io.h>
    //#include <stdio.h>
    //#include <stdlib.h>
    
    #define F_CPU 8000000UL  // 8 MHz
    
    #include <util/delay.h>
    
    int main (void) {
    
      DDRD  = 0b11100000;  // 1=Output, 0=Input
      PORTD = 0b11100100;  //on
    
      while (1==1) {
      waitms(50);
      
       if (PORTD.2 == (0)) {
       PORTD.7 = (1);
       } else {
       PORTD.7 = (0);
       } 
    
    }
    
    void waitms(int ms) {
      int i;
      for (i=0;i<ms;i++) _delay_ms(1);
    }
    }
    


    Błędy:
    Laminator.c:15: warning: implicit declaration of function 'waitms'
    Laminator.c:17: error: expected ')' before numeric constant
    Laminator.c:18: error: expected ';' before numeric constant
    Laminator.c:20: error: expected ';' before numeric constant
  • #10 4759792
    Wicked
    Poziom 18  
    Posty: 174
    Pomógł: 11
    Ocena: 6
    Po 1:
    funkcję void waitms(int ms) musisz zadeklarować, czyli na samej górze napisać prototyp funkcji:

    
    void waitms(int ms);
    

    po 2 w funkcji waitms masz o jedną klamrę za dużo.
  • #11 4760811
    Xaveri
    Poziom 17  
    Posty: 460
    Pomógł: 13
    Ocena: 77
    Jasne... tego nie zauważyłem :/.
    Zwalczyłem całą część mechaniczną i będę mógł powalczyć spokojnie z oprogramowaniem... czas nauczyć się C, bo Bascom już znam całkiem dobrze...

    Poradziłem sobie z tym problemem. Próbuję zdobyć kurs, który ukazywał się w EdW od maja 2005. Zamykam temat...

Podsumowanie tematu

✨ Problem dotyczył błędu kompilacji w projekcie termostatu do laminatora opartego na mikrokontrolerze ATMega8, kompilowanym za pomocą WinAvr. Błąd pojawiał się przy wywołaniu funkcji fdevopen z trzema argumentami, podczas gdy jej definicja w bibliotece AVR oczekuje dwóch parametrów: wskaźnika na funkcję putchar przyjmującą dwa argumenty (char i FILE*) oraz wskaźnika na funkcję getchar. Funkcja uart_putchar była zdefiniowana z jednym parametrem, co powodowało niezgodność typów i ostrzeżenia kompilatora. Rozwiązaniem było zmodyfikowanie prototypu uart_putchar na przyjmujący dwa parametry (char c, FILE *f) oraz dostosowanie wywołań tej funkcji, co pozwoliło na poprawną kompilację. Dodatkowo pojawiły się błędy składniowe w kodzie związane z niepoprawnym użyciem średnika po instrukcji if oraz brakiem prototypu funkcji waitms i nadmiarową klamrą w jej definicji. Po poprawkach kod kompilował się poprawnie. Autor planował dalsze modyfikacje oprogramowania, m.in. implementację zmiany nastawy temperatury na podstawie przycisku.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA