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

ATMEGA USART na przerwaniach się wiesza

DJ.TRoX 11 Cze 2010 08:32 1725 2
REKLAMA
  • #1 8177710
    DJ.TRoX
    Poziom 18  
    Witam forumowiczów,

    Sytuacja wygląda tak, że z jednostki nadrzędnej słane są ramki danych,
    Po każdej ramce jest szczelina czasowa tak aby nasza ATmega zdążyła odpowiedzieć,
    Mamy Atmega16 kwarc 16MHz i transmisje 57600 (w przybliżeniu),
    Gadamy przez RS485 tak, że między ramkami jeszcze przełączam linie bufora,
    Steruje równocześnie buforem wejścia i wyjścia tak, że kiedy nadajemy to nic nie wraca z powrotem,
    Z grubsza działa to tak, że przy inicjacji włączam w UCSRB bity RXCIE, TXEN, RXEN,
    No i z każdym odebranym bajtem zgłasza się przerwanie od RX,
    Kiedy przyjdzie cała ramka, zgodzą się znaczki początku i końca oraz suma kontrolna to przechodzę na odbiór,
    Przełączam linie bufora oraz włączam UDRIE w UCSRB,
    W tym momencie kiedy rejestr wyjściowy UDR będzie pusty (czyli od razu) program skacze do przerwania SIG_UART_DATA,
    Wysyłam sobie całą ramkę a po ostatnim bajcie wyłączam UDRIE oraz włączam TXCIE,
    Kiedy przychodzi przerwanie SIG_UART_TRANS ustawiam linie RS na odbiór i wyłączam TXCIE,

    Wszystko działa dobrze ale krótko,
    Po kilkuset ramkach program się zachowuje tak jak by po kolejnym wysłanym bajcie nie przychodziło przerwanie i nie ma co popędzać programu do przodu,
    Przepełnienie stosu? niby jak?
    Reszta programu działa bez zarzutów mimo, że komunikacja stoi,
    Procedury odbioru i zapisu osobno też działają bez zarzutu,

    Program wygląda tak:

    
    SIGNAL(SIG_UART_RECV){
        char data,cs;
    	unsigned char a;
    
        data=UDR;
        
        if (rx_pos){
            rx_buffer[rx_pos]=data;
            rx_pos++;
    
    		if (rx_pos==3){
    			rx_len=data;
    			if ((rx_len+5)>rs_buffer_len){
    				rx_len=0;
    				rx_pos=0;
    				sbi(rs_status, reciving_error);
    			}
    		}
        }else{
            if (data==master_frame_begin_sign){
                rx_buffer[0]=data;
                rx_pos=1;
            }
        }    
        if ((rx_pos>4) && (rx_pos>=rx_len+5)){
            rx_pos=0;
    		if (rx_buffer[rx_len+4]==frame_end_sign){
    			cs=cs_base_sign;
    			for (a=0; a<rx_len+3; a++){
    				cs^=rx_buffer[a];
    			}
    			if (cs==rx_buffer[rx_len+3]){
    				if ( (rx_buffer[1]==0) && (rx_buffer[2]==2) ){
    					sbi(rs_status, recived_valid_frame);
    					if ( (output_prv[0]==rx_buffer[3]) && (output_prv[1]==rx_buffer[4]) ){
    						output[0]=rx_buffer[3];
    						output[1]=rx_buffer[4];
    					}
    					output_prv[0]=rx_buffer[3];
    					output_prv[1]=rx_buffer[4];
    
    					DIR_W;        //------------------------------------ PRZECHODZIMY NA TRANSMISJE
    					sbi(UCSRB, UDRIE);    // int empty buffer enable					
    				}
    			}else{
    				sbi(rs_status, reciving_error);
    			}
    		}else{
    			sbi(rs_status, reciving_error);
    		}
        }
    }
    
    
    
    SIGNAL(SIG_UART_DATA){
    	unsigned char a,cs;
    	if (tx_pos){
    		UDR=tx_buffer[tx_pos];
    		if (tx_pos>=6){				// last byte in frame --> go to transmiting
    			cbi(UCSRB, UDRIE);		// int tx ready disable
    			sbi(UCSRA, TXC);		// clear transmit int flag
    			sbi(UCSRB, TXCIE); 		// int tx finish enabled
    
    //			while(!(UCSRA&(1<<TXC)));
    //			sbi(UCSRA, TXC);		// clear transmit int flag
    //			DIR_R;
    
    			tx_pos=0;
    		}else{
    			tx_pos++;
    		}
    	}else{
    		UDR=slave_frame_begin_sign;
    		tx_pos=1;
    		tx_buffer[1]=0;
    		tx_buffer[2]=2;
    		tx_buffer[3]=input[0];
    		tx_buffer[4]=input[1];
    		cs=cs_base_sign^slave_frame_begin_sign;
    		for (a=1; a<5; a++){
    			cs^=tx_buffer[a];
    		}
    		tx_buffer[5]=cs;
    		tx_buffer[6]=frame_end_sign;
    	}
    }
    
    
    
    SIGNAL(SIG_UART_TRANS){
    	DIR_R;
    	cbi(UCSRB, TXCIE);
    }
    




    inicjacja USARTA:
    
    	UBRRH=0;
    	UBRRL=34;				// 57.143bps (57.600)
    	UCSRA=0b00000010;		// double speed
    	UCSRB=0b10011000;		// int Rx enabled
    	UCSRC=0b10001110;		// 8bit 2 stop
    




    Jeśli ktoś ma pomysł to z góry dziękuję.
  • REKLAMA
  • #2 8177995
    Konto nie istnieje
    Konto nie istnieje  
REKLAMA