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

[Mega32][AVR-GCC]Przerwanie z UART, które się nie wykonuje

Zumo 26 Paź 2009 20:09 2411 3
  • #1 7178541
    Zumo
    Poziom 21  
    Witam.
    Od dłuższego czasu "walczę" z przerwaniem, które nie chce się za nic wykonać. Zrobiłem już wszystko co potrafiłem, ale niestety brak reakcji.
    Chodzi tu o układ z obsługą dysku twardego, który połączony jest z komputerem za pomocą MAX232 (RS-232). Procesor to Atmega32 z wewnętrznym oscylatorem 8MHz.
    Pętla "echo" działa. Dane wracają.
    Może ktoś bardziej obeznany mógłby powiedzieć co jest nie tak? (W AVR-GCC jestem początkujący).
    Załączam kod: (To jest wersja testowa - jak zacznie działać to zrobię "porządek". Wyciąłem to co nie potrzebne.)
    #include <avr/io.h>
    #include <string.h>
    #include <stdio.h>
    #include "fat.h"
    #include "ata.h"
    #include "fattime.h"
    #include <avr/pgmspace.h>
    #include <avr/interrupt.h>
    
    
    void mcuInit		(void);
    void dir_serial		(unsigned long cluster);
    void print_hd_info	(void);
    int  uart_putc	(char c);
    int  uart_getc	(void);
    unsigned char odebrano=0;
    unsigned char bufor[32];
    	TFILE *farq;
    	struct direntry *de;
    	char path[12];
    	int ok; //Flaga - zezwolenie na odczyt z dysku
    	char d; 
    	unsigned char c;
    	
    
    ISR(SIG_UART_RECV)
    { 
       c = UDR;
       printf_P(PSTR("int")); // To się nie wyświetla
       UARTReceiveString();   
    } 
    
    void UARTReceiveString(void)
    {
    unsigned char i=0;
    
    do
    {
    
    if ((bufor[i] = c) == '\n') ReadHDD(); printf_P(PSTR("WORK")); break; //dodaje odebrane znaki do tablicy, jesli odbierze '\n' to przerywa petle, wychodzi z funkcji i uruchamia odczyt pliku.
    
    i++;
    
    }while (i < 32); // zeby nie przepelnic bufora
    
    }
    
    void ReadHDD(void)
    {	
    	if (ok) {
    	if (farq = fatFopen(bufor)) {
    	printf_P(PSTR("\r\nReading file...\r\n"));
    	while(!fatFeof(farq))
    	{
    		printf_P(PSTR("%c"), fatFgetc(farq));
    	}
    	fatFclose(farq);
    	} else { printf_P(PSTR("Nie mozna otworzyc")); }
    } else {
    printf_P(PSTR("ok=0 - nie mozna"));
    }
    }
    
    
    int main(void)
    {
    
    	
    
    	
    
    	// UART SET
    	UCSRA=0x02;
    	UBRRL = 0x10;       // ustawienie UBRRL
    	UBRRH = 0x00; // ustawienie UBRRH 
    	UCSRC = (1<<URSEL)|(3<<UCSZ0);
    	UCSRB= (1 << RXCIE)|(1<< RXEN)|(1<<TXEN)|(0<<TXCIE);
    	//END
    	
    	mcuInit();							// start ATMega32
    	fdevopen(uart_putc,uart_getc, 0);	// configure printf to send data to serial port
    	sei(); // Zezwol na przerwania
    	ok=0;
    	printf_P(PSTR("ODCZYT PLIKOW\r\n"));
    	
    	ataInit();	// Start ATA
    	fatInit();	// Start FAT
    	
    	fatCddir("pliki");
    	printf_P(PSTR("PLIKI\r\n"));
    	dir_serial(fatGetCurDirCluster());
    	printf_P(PSTR("Podaj nazwe pliku (np. plik.txt) do odczytania\r\n"));
    	ok=1; // Flaga oznaczajaca gotowosc do odczytu pliku
    	
    
    	
    	while(1);
    }
    //Definicje wycięte, aby zoptymalizować długość posta.
    
    //Definicja "print_serial()"
    //Definicja "print_hd_info()"
    
    
    //*
    // Function: uart_putc
    // Parameters: char to send
    // Returns: 0
    //
    // Description: send a character to UART and return 0 for compatibility reasons
    //*
    int uart_putc(char d)
    {
        loop_until_bit_is_set(UCSRA, UDRE);
     	UDR = d;
       return 0;
    }
    
    
    //*
    // Function: uart_getc
    // Parameters: none
    // Returns: the character read from UART
    //
    // Description: get a character from UART and return it, return -1 if the UART
    //              was empty
    //*
    
    int uart_getc(void)
    {
    	if (bit_is_set(UCSRA, RXC) == 0)
    	return -1;
    	return UDR;
    }
    
    
    //*
    // Function: mcuInit
    // Parameters: none
    // Returns: none
    //
    // Description: Initialize the ATMega32
    //*
    void mcuInit(void)
    {
    	// Input/Output Ports initialization
    	PORTA=0xFF;// Port A initialization
    	DDRA=0xDF;
    
    	PORTB=0x00;// Port B initialization
    	DDRB=0x00;
    
    	PORTC=0x00;// Port C initialization
    	DDRC=0xFF;
    
    	PORTD=0x00;// Port D initialization
    	DDRD=0x00;
    
    }
    

    Dziękuję za pomoc i za chęci również :)
  • #2 7178614
    mieczotronix
    Poziom 16  
    moim zdaniem, to może nawet i się wywołuje to przerwanie, tylko że nie ma czasu się dokończyć.
    Nie powinno się raczej wywoływać procedur, a zwłaszcza kobylastych z procedur obsługi przerwań, tym bardziej, że to jakiś szybki baudrate (UBRRL==10) a printf nie wiadomo ile się wykonuje. Może masz taką sytuację, że zanim procesor skończy obsługe przerwania (printf, obsługa stosu), to wywołuje się kolejne i tak dalej. Proc się wtedy zawiesza albo resetuje. Nie wiem jak kobylasty jest twój printf, ale jak ze środka woła inne procedury, to procesor będzie miał co robić i się może nie wyrobić. Nie mam akurat pod ręką dataszitu żeby sprawdzić ustawienie portów, ale zakładam że to 10x sprawdziłeś.
    ajajaj!
    Piszę z laptopa i mało widzę, ale teraz zobaczyłem że twoja procedura ISR wywołuje UART-receive string, która z kolei wywołuje HDD read, i pritnfa i to w pętli. To nie będzie działać, bo jak nadejdzie kolejny znak, to znowu się wywoła ISR, odłoży to co aktualnie proc robił na stos i rozpocznie znowu UARt-receive... i tak dalej. czaisz?
  • #3 7178740
    Dr.Vee
    VIP Zasłużony dla elektroda
    Nie czytasz ostrzeżeń kompilatora!
    Dobrze, że jakikolwiek printf działa w tym kodzie...

    Powinno być:
    int uart_getc(FILE* unused);
    int uart_putc(int c, FILE* unused);
    
    int main(void)
    {
        // Poniższe alokują pamięć dynamicznie!
        stdin = fdevopen(NULL, uart_getc, _FDEV_SETUP_READ);
        stdout = fdevopen(uart_putc, NULL, _FDEV_SETUP_WRITE);
    }

    Ewentualnie:
    // strumień alokowany i inicjalizowany statycznie
    FILE uart_str = FDEV_SETUP_STREAM(uart_putc, uart_getc, _FDEV_SETUP_RW);
    
    int main(void)
    {
        // oba są równoważne, bo RW
        stdin = &uart_str;
        stdout = &uart_str;
    }


    Poczytaj dokumentację do avr-libc

    Pozdrawiam,
    Dr.Vee
  • #4 7181830
    Zumo
    Poziom 21  
    Dr.Vee napisał:
    Dobrze, że jakikolwiek printf działa w tym kodzie...

    Te printf'y to w kodzie przykładowym były więc to nie ja dopisywałem.
    A z tymi fragmentami kodów będę próbował.
    Co do długości kodu w przerwaniu - wiem o tym i poprawię to, jak będę miał pewność, że przerwanie się wykonuje.

    Dodano:
    Witam ponownie
    Dopisałem do obsługi przerwania kod, który będzie mi ustalał flagę, gdy przerwanie się wykona.
    W instrukcji main wstawiłem pętlę, i instrukcję warunkową która powinna wydrukować "+" gdy przerwanie się wykona.
    Efekt działania jest taki:
    Kod na początku wykonuje się poprawnie, następnie wysyła ileś tych plusów a potem przestaje reagować....
    Już nie wiem co zrobić, żeby to działało.
    UART set:
    (mam ustawienia w terminalu 57600 b/s parzystość: brak, 8 bitów danych i jeden stopu)
    
    UCSRA=0x02;
    	UBRRL = 0x10;       // ustawienie UBRRL
    	UBRRH = 0x00; // ustawienie UBRRH 
    	UCSRB = _BV(RXEN) | _BV(TXEN) | _BV(RXCIE);
    	UCSRC = _BV(URSEL) | _BV(UCSZ0) | _BV(UCSZ1);
    

    Przerwanie:
    
    ISR(SIG_UART_RECV)
    { 
       c = UDR;
       prze = 1;
       //UARTReceiveString();   
    } 
    

    Drukowanie plusów:
    
    	while(1) {
    	if (prze=1) {
    	uart_putc(0x2B);
    	prze=0;
    	}
    	}
    
REKLAMA