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

Przerwanie na porcie LPT komputera PC

veldrin 08 Mar 2009 23:28 2943 12
  • #1 6256037
    veldrin
    Poziom 10  
    Witam,
    chciałbym się dowiedzieć czy istnieje możliwość zgłoszenia przerwania na porcie LPT komputera PC za pomocą ATmegi 128.
    Wydaje mi się to mało realne, jako ze połączenie PC<->AVR to kabel ISP.

    Jeżeli jest to niemożliwe, to czy można zgłosić jakiekolwiek inne (niż od RS232) przerwanie w komputerze PC?

    Pozdrawiam i proszę o pomoc
  • Pomocny post
    #2 6256490
    Konto nie istnieje
    Poziom 1  
  • #3 6261393
    rpal
    Poziom 27  
    ja bym sie zastanawial bardziej nad tym jak te przerwanie obsluzyc w PC-cie bo jesli ma sie to dziac pod windowsem to bedzie wyzsza szkola jazdy a watpie abys sie decydowal na prace w zapomnianym srodowiski Msdos. poaza tym skad teraz wziasc np. turbo C aby napisac procedury obslugi?II
  • #4 6261622
    veldrin
    Poziom 10  
    Hmm.. Chcę obsłużyć to pod QNX Neutrino i Windowsem Embedded CE 6. O ile wydaje mi sie, ze QNX da sobie rade, to przyznam bez bicia, ze Windowsa CE nie sprawdziłem (ale raczej tez bez problemu (?))

    Dzięki atom za jasne przedstawienie sprawy ;)
  • Pomocny post
    #5 6264543
    PiRoman2
    Poziom 20  
    W jakiej sytuacji ma być generowane przerwanie?
    Jeżeli LPT ma generować przerwanie po zmianie 1 sygnału to podepnij go pod ACK (10) .
  • #6 6298148
    veldrin
    Poziom 10  
    O! wielkie dzięki PiRoman2.
    Właśnie się zastanawiałem ile kabelków mi wystarczy.
    Nie potrzebuję przesyłać żadnych danych, wystarczy mi byle jaki sygnał, który spowoduje przerwanie.

    A jak gdzie to podłączyć po stronie AVR?
  • #7 6300027
    rpal
    Poziom 27  
    Na miejscu kolegi nie bagatelizowałbym sprawy obsłużenia przerwania portu równoległego i dokładnie upewniłbym się czy system operacyjny którym dysponujesz obsługuje własnie te przerwanie. Z tego co się orientuję na popularnych PC-tach tylko jakaś stara wersja OS-a używała tego. A chcąc użyć przerwania pod Dos-em należało modyfikować wektory przerwań. Prostsze jest obsługiwanie na zasadzie odpytywania czyli ciągłego sprawdzania stanu portu. W typowym PC-cie ACK obsługuje bodajże zbocze narastające.
  • #8 6321327
    veldrin
    Poziom 10  
    System operacyjny na pewno obsluzy przerwanie od LPT. Mam zamiar uzywac QNX Neutrino.

    A co do mojego problemu, wciaz nie znalazlem odpowiedzi :(
  • #9 6343940
    szeryf.rm
    Poziom 22  
    Ja bym zrobił to najprościej. Czyli skoro to ma być przerywanie, to można zrobić to programowo. Przerywanie to coś w rodzaju niezależnego wątku. Więc utwórz sobie wątek, który będzie czekał na sygnał i jak go dostanie to albo prześlesz sygnał do wątku głównego albo wewnątrz wątku czekającego od razu obsłużysz.
  • #10 6353264
    veldrin
    Poziom 10  
    Ale mi chodzi o rozwiązanie problemu "fizycznego" połączenia.
    Tzn jaką minimalną liczbę pinów wtyczki LPT muszę wykorzystać, żeby wywołać przerwanie na komputerze PC i jakie to muszą być linie?
  • #11 6353365
    Konto nie istnieje
    Poziom 1  
  • #12 6384893
    veldrin
    Poziom 10  
    Ok, dzieki i przepraszam za bycie upierdliwym.
    Poczytalem jeszcze dokladnie opis dzialania portu LPT i juz wszystko wiem, co jest mi potrzebne.
    Myslalem, ze ACK dziala w dwie strony i nie wiedzialem jak to obsluzyc i po stronie aVR i po stronie PC (bo odsluguje przerwania z dwoch stron), ale od strony PC do AVR wystarczy mi strobe puscic ;)
  • #13 6432720
    veldrin
    Poziom 10  
    Witam,
    bazując na kilku kodach znalezionych w sieci popełniłem takie oto coś
    #define USART_BAUDRATE   57600
    #define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
    
    #define MAX_INTS 100	// number of interrupts to be done
    
    volatile int counter = 0;    
    volatile int ms_counter = 0; // number of seconds / 10000
    volatile int s_counter = 0;    // number of seconds
    volatile int ms[MAX_INTS];
    volatile unsigned char s[MAX_INTS];
    
    
    void UART_init(void)
    {
       UBRR0H = (unsigned char)(BAUD_PRESCALE >> 8);
       UBRR0L = (unsigned char)BAUD_PRESCALE;
    
       UCSR0A = 0;
       /* Enable receiver and transmitter */
       UCSR0B = (1<<RXEN)|(1<<TXEN);
       /* Set frame format: 8data, 2stop bit */
       UCSR0C = (1<<USBS)|(3<<UCSZ0);
    }
    
    
    
    void USART_Transmit( unsigned char data )
    {
      /* Wait for empty transmit buffer */
      while ( !( UCSR0A & (1<<UDRE0)) )
           ;
      /* Put data into buffer, sends the data */
      UDR0 = data;
    }
    
    
    
    void USART_Transmit_String(char* string){
    	int len;
    	unsigned char i;
    
    	len = strlen(string);	
    	for(i=0; i<len; i++){
    		USART_Transmit(string[i]);
    	}
    }
    
    void USART_Transmit_Measures(){
    		int i = 0;
    		char ms_buf[4]= {0,0,0,0};
    		char s_buf[3] = {0,0,0};
    		
    		for(i = 0; i < MAX_INTS; i++){		
    			itoa(ms[i], ms_buf, 10);
    			itoa(s[i], s_buf, 10);
    
    			USART_Transmit_String(s_buf);
    			USART_Transmit_String("s ");
    		
    			USART_Transmit_String(ms_buf);
    			USART_Transmit_String("ms\r\n");
    		}
    }
    
    int main(void)
    {
      // serial port initialization
      UART_init();
       
      DDRD = 0;
      DDRD |= (1 << 1); // Set PD1 as ACK output
    
      TCCR1B |= (1 << WGM12); // Configure timer 1 for CTC mode
      TIMSK |= (1 << OCIE1A); // Enable CTC interrupt
    		
      PORTD = 0; // int0
      EIMSK |= (1 << 0);	//enable int0
    
      OCR1A   = 1600; // Set CTC compare value to 0,001Hz at 16MHz AVR clock, with a prescaler of 1
      TCCR1B |= ((1 << CS10) | (0 << CS11) | (0 << CS12)); // Set up timer at Fcpu 
    
      USART_Transmit_String ("Welcome on board, sir!\n\r");
    
      sei(); //  Enable global interrupts
    	
      PORTD = (0 << 1); // 
      PORTD = (1 << 1); // send ACK
      PORTD = (0 << 1); //
      
      while(1) {}
    }
    
    ISR(TIMER1_COMPA_vect)
    {
    	if(ms_counter <10000)	 
    		ms_counter ++;
    	else{
    		ms_counter = 0;
    		s_counter ++;
    	}
    }
    
    ISR(INT0_vect)
    {
    		if(counter < MAX_INTS ){
    			ms[counter ] = ms_counter ;
    			s[counter ] = s_counter ;		 	
    			counter ++;
    			USART_Transmit('+');
    		}
    		else{
    			USART_Transmit_Measures();
    			counter = 0;
    			_delay_ms(500);
    		}
    		_delay_ms(10);
    		PORTD = (0 << 1); // 
    		PORTD = (1 << 1); // send ACK
    		PORTD = (0 << 1); //
    
    		ms_counter = 0;
    		s_counter = 0;
    		OCR1A   = 1600;
    } 
    


    Jak widać zależy mi na serii pomiarów czasu obsługi przerwania na porcie LPT. Program obsługi przerwania napisany jest po stronie systemu QNX (po wykryciu przerwania na porcie LPT wysyłany jest sygnał na STROBE [INT0 na AVR] ) i działa.
    Problem polega na tym, że raz na jakiś czas nie jest zgłaszane przerwanie, więc całość (polegająca na interakcji - przerwanie -> odpowiedź) wisi.
    Dodałem nawet opóźnienie pomiędzy obliczeniem czasu reakcji a wywołaniem kolejnego przerwania, ale i to nic nie dało.

    Wydaje mi się, że wina leży po stronie AVR, ponieważ gdy w momencie "zwisu" zresetuję płytkę pomiary znowu ruszają.
    Niestety nie mam pojęcia, co może powodować tak dziwne zachowanie.
REKLAMA