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

ATmega88 WinAVR GCC Problem z funkcją w innym pliku

darek1632 02 Lis 2010 14:11 1868 13
  • #1 8692825
    darek1632
    Poziom 15  
    Witam, mam taki problem jeśli definiuje funkcje GetKey pliku KPD.c nie mam do niej dostępu mimo jej deklaracji KPD.h oraz dołączeniu pliku KPD.c. Do innych funkcji w tym pliku mam dostęp np. KPD_GetKey. Próbowałem definiować jako extern ale nic nie pomogło. Problem rozwiązuje zdefiniowanie jej w pliku main.c jednakże, chciałbym ją mieć w pliku KPD.c. Kompilator nie wyrzuca żadnych warningów.
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/signal.h>
    #include <stdlib.h>
    #include <string.h>
    #include <inttypes.h>
    #include <avr/eeprom.h>
    #include <avr/pgmspace.h>
    
    #include "KPD.h"
    #include "UART.h"
    #include "HD44780.h"
    
    unsigned char GetKey ( void )
    {
    unsigned char c,Key;
    
    do
     {    
        Key = KPD_GetKey();    
        if ( Key != 0xFF ) 
    	   {
    	   c = Key;
           break;
           }       	
        else {}	
     } while(1);
    return c;
    }
    
    void main( void )
    {
    ........
    }
    
  • #2 8693083
    tmf
    VIP Zasłużony dla elektroda
    Pokaż te nieprawidłowe definicje. Sprawdź, czy się nie pomyliłeś i prototyp nie jest różny od deklaracji. Druga rzecz to czy plik KPD.h się prawidłowo inkluduje? Generalnie jeśli prototyp masz w pliku nagłówkowym, a deklarację w źródłowym i podajesz je linkerowi to powinno być ok.
  • #4 8693754
    darek1632
    Poziom 15  
    Pokazuje pliki:

    KPD.h

    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/signal.h>   
    
    unsigned char KPD_KeyPressed;
    unsigned char KPD_LastKey;
    unsigned char KPD_ScanRow;
    unsigned char KPD_KeyDown; 
    
    
    #define CODE_MAX_LENGTH     8
    #define CODE_ACCESS_LENGTH  4
    #define CODE_ADMIN_LENGTH   8
    #define BUFSIZE             20  
    
    
    void  KPD_Init(void);
    unsigned char KPD_GetKey(void);
    unsigned char GetKey (void);
    SIGNAL(PCINT1_vect);
    SIGNAL(TIMER2_OVF_vect);
    


    KPD.c

    
    #include "KPD.h"
    #include "HD44780.h"
    #include <avr\pgmspace.h>
    
    unsigned char KPD_KeyPressed;
    unsigned char KPD_LastKey;
    unsigned char KPD_ScanRow;
    unsigned char KPD_KeyDown;
    
    
    
    prog_char KPD_Array[4][4] = { {'1','2','3','A'},{'4','5','6','B'},{'7','8','9','C'},{'s','0','d','D'} };
     
    void  KPD_Init(void)
    {
      TCCR2B = 0;                         // stop timer/counter
    
      KPD_KeyPressed = 0;
      KPD_LastKey = 0;
      KPD_ScanRow = 0;
      KPD_KeyDown = 0;
    
      DDRB |= (1 << PINB2);               // set pin A0 as output (X1)
      DDRB |= (1 << PINB3);               // set pin A1 as output (X2)
      DDRB |= (1 << PINB4);               // set pin A2 as output (X3)
      DDRB |= (1 << PINB5);               // set pin A3 as output (X4)
      PORTB |= (1 << PINB2);              // set pin A0 high
      PORTB |= (1 << PINB3);              // set pin A1 high
      PORTB |= (1 << PINB4);              // set pin A2 high
      PORTB |= (1 << PINB5);              // set pin A3 high
    
      DDRC &= ~(1 << PINC0);              // set pin B0 to input (Y1)
      DDRC &= ~(1 << PINC1);              // set pin B1 to input (Y2)
      DDRC &= ~(1 << PINC2);              // set pin B2 to input (Y3)
      PORTC |= (1 << PINC0);              // enable pull-up
      PORTC |= (1 << PINC1);              // enable pull-up
      PORTC |= (1 << PINC2);              // enable pull-up
    
      PCMSK1 |= (1 << PCINT8);            // enable pin change int 8
      PCMSK1 |= (1 << PCINT9);            // enable pin change int 9
      PCMSK1 |= (1 << PCINT10);           // enable pin change int 10
    
      PCICR  |= (1 << PCIE1);              // enable pin change ints
      PCIFR |= (1 << PCIF1);               // clear flag
    
      TCNT2 = 0;                          // clear counter
      TIMSK2 = (1 << TOIE2);              // enable overflow interrupt
      TCCR2A = 0;                         // normal mode and normal port operation on all t/c pins
      TCCR2B = (1<<CS22);                 // normal mode, TOP = 0xFF, TOVF on MAX, CLK/8
                                          // => overflow each 2 ms @ 1 MHz
      sei();                              // enable all interrupts
    }
    
    unsigned char KPD_GetKey(void)
    {
      if (KPD_KeyPressed)
      {
        KPD_KeyPressed = 0;
        return (KPD_LastKey);
      }
      else
        return (0XFF);
    }
    
    unsigned char GetKey ( void )
    {
    unsigned char c,Key;
    
    do
     {    
        Key = KPD_GetKey();    
        if ( Key != 0xFF ) 
    	   {
    	   c = Key;
           break;
           }       	
        else {}	
     } while(1);
    return c;
    }
    
    // executed when SREG:I = 1 and GIMSK:PCIE1 = 1. GIFR:PCIF1 cleared upon entry.
    SIGNAL(PCINT1_vect)
    {
      
      unsigned char column;         
      PCICR &= ~(1 << PCIE1);            // disable pin change int for de-bounce
      _delay_ms(40);                                      
      PCICR /*GIMSK*/ |= (1 << PCIE1);   // enable pin change ints
      column = (~PINC) & 0x07;
    
      switch (column)
      {
        case  0x00: KPD_KeyDown = 0;
                    break;
        case  0x01: KPD_LastKey = pgm_read_byte(&KPD_Array[KPD_ScanRow][0]);//pgm_read_byte(&STALA);        
                    if (!KPD_KeyDown)
                      KPD_KeyPressed = 1;               // must release key before press recorded
                    KPD_KeyDown = 1;
                    break;
        case  0x02: KPD_LastKey = pgm_read_byte(&KPD_Array[KPD_ScanRow][1]);
                    if (!KPD_KeyDown)
                      KPD_KeyPressed = 1;               // must release key before press recorded
                    KPD_KeyDown = 1;
                    break;
        case  0x04: KPD_LastKey = pgm_read_byte(&KPD_Array[KPD_ScanRow][2]);
                    if (!KPD_KeyDown)
                      KPD_KeyPressed = 1;               // must release key before press recorded
                    KPD_KeyDown = 1;
                    break;
        case  0x08: KPD_LastKey = pgm_read_byte(&KPD_Array[KPD_ScanRow][3]);
                    if (!KPD_KeyDown)
                      KPD_KeyPressed = 1;               // must release key before press recorded
                    KPD_KeyDown = 1;
                    break;
        default:    KPD_LastKey = 0;
                    KPD_KeyPressed = 0;
      }
    }
    
    SIGNAL(TIMER2_OVF_vect)
    {
      
      if (!KPD_KeyDown)
      {
        PORTB |= (1 << (KPD_ScanRow+2));        // set pin high
        if (++KPD_ScanRow > 3)
          KPD_ScanRow = 0;
        PORTB &= ~(1 << (KPD_ScanRow+2));       // set pin low
      }
      
      
    }
    
  • #5 8693806
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Deklarując zmienne w pliku nagłówkowym prosisz się o problemy. Zapewne zostaną one "stworzone" w każdym pliku który dołącza ten nagłówek, co zaowocuje na pewno problemami. Jeśli zmienne globalne danego modułu chcesz exportować tak aby można było używać ich w innych modułach, to deklarowane mogą być TYLKO w module macierzystym, a w nagłówku deklaracje należy poprzedzić słówkiem "extern".

    Nie ma najmniejszej potrzeby deklarować wcześniej funkcji przerwań, bo tak czy siak nigdzie ich nie wywołujesz, ani nie wykorzystujesz ich jako wskaźników.

    I ponownie proponuję zadowolić się małymi literkami przy nazwach plików.

    4\/3!!
  • #6 8694369
    darek1632
    Poziom 15  
    Poprawiłem te niedociągnięcia o których Freddie wspomniałeś. Niestety to nie rozwiązało problemu z dostępem do funkcji GetKey.
  • #7 8694583
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Powiem tak... Wrzuciłem taki projekt u siebie, dodałem brakujący nagłówek <util/delay.h>, zakomentowałem rzeczy których kompilator nie mógł znaleźć (jakieś rejestry i nagłówki których nie mam) i... bezproblemowo znajduje funkcje...

    4\/3!!
  • #8 8694935
    darek1632
    Poziom 15  
    U mnie też kompiluje prawidłowo ale chodzi o to, że nie mogę wejść w tą funkcje z uruchomionym programem na procku. Kiedy umieszcze ją w pliku main ( tak jak w pierwszym poście ) działa OK.
  • #10 8695204
    darek1632
    Poziom 15  
    Mam cos takiego:
    
    int main( void )
    {
     
      KPD_Init();                    //Inicjalizacja urządzeń
      uart_init ( MYUBRR );
      LCD_Initalize();
      
      DDRB |= (1 << PINB1);
      DDRC |= (1 << PINC3);
      DDRC |= (1 << PINC4);
      
      PRZEKAZNIKOFF();
      LEDOFF();
      
      sei();                          //Włączenie przerwań
    
      Beep(625);
      _delay_ms(200);
      Beep(0);
      
      LCD_Clear();
      LCD_WriteText_P("WITAJ podaj PIN:");
      
      unsigned char i,ch;
      
      for(i=0;i<4;i++)
      {
      ch = GetKey();         //Tu program nie idzie dalej mimo naciśnięcia klawisza
      LCD_GoTo(i+6,1);
      LCD_WriteData( ch );
      Beep(625);
      _delay_ms(150);
      Beep(0);
      }
      _delay_ms(500);
      PRZEKAZNIKON();
      
        for( ; ; )  
    	
        {
    	
        LEDON();
    	_delay_ms(500);
    	LEDOFF();
    	_delay_ms(500);
        } 
      
    }
    

    Po funkcji GetKey na LCD wypisuje mi znaki więc jeśli tego nie robi rozumiem, że program nie wejdzie w tą funkcje.
  • #11 8695237
    Freddie Chopin
    Specjalista - Mikrokontrolery
    I jak umieścisz tą funkcję w obok funkcji main() to wtedy działa prawidłowo?

    EDIT: Tak w ogóle, to ja już wiem jakie jest rozwiązanie tej zagadki... Jest nim - jak zwykle zresztą - magiczne zaklęcie dla kompilatora: "volatile".

    Na następny raz jak chcesz szybkiej pomocy, to proponuję pisać konkretnie i jasno z czym jest problem, bo tak to napisałeś wszystko, że nic nie wiadomo. No i gwarantuję Ci, że mikrokontroler "wchodzi" w tą funkcję, tyle że z niej już nigdy nie wychodzi. Dlaczego? Patrz poprzedni akapit.

    4\/3!!
  • #12 8695245
    darek1632
    Poziom 15  
    Dokładnie tak
  • #14 8695444
    darek1632
    Poziom 15  
    Dzięki Freddie
    Zmieniłem zmienne na typ volatile:
    
    volatile unsigned char KPD_KeyPressed;
    volatile unsigned char KPD_LastKey;
    volatile unsigned char KPD_ScanRow;
    volatile unsigned char KPD_KeyDown;
    

    Problem rozwiązany
    Pozdrawiam.
REKLAMA