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

[ATmega168][C] wysyłanie stringa/tablicy charów w przerwaniu

esnow 22 Lut 2012 18:46 1677 13
REKLAMA
  • #1 10583367
    esnow
    Poziom 14  
    witam,
    nie mogę sobie poradzić z wysłaniem tablicy charów w przerwaniu.

    Pierwszy bajt wysyłam w pętli głównej programu, następne powinny się wysłać w przerwaniu.

    W putty dostaje krzaczki i co jakiś czas tekst, który wysyłam "test".
    Jak wysyłam bez przerwania wszystko działa poprawnie.
    Co robię źle

    pamiętam o sei();
    i volatile int wsk_do_wyslania = 0;

    
    while(1)
    {
    ...
    	wsk_do_wyslania=0;
    	USART_Tx(buff[0]);
    	wsk_do_wyslania++;
    }
    ...
    
    ISR(USART_TX_vect)
    {
    		UDR0 = buff[wsk_do_wyslania];
    		wsk_do_wyslania++;	
    }
    
    


    Z góry dziękuję za zainteresowanie tematem i pomoc.
  • REKLAMA
  • #2 10584663
    Fredy
    Poziom 27  
    A czemu zerujesz wskaźnik>?

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    ten wskażnik ma wskazywać na początek tekstu.
    Czyli ma być :

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod



    a może to tylko zbieżność nazw, i ten wskażnik to nie jest wskaźnik tak naprawdę, raczej indeks?
  • #3 10584771
    drzasiek
    Specjalista CNC
    Ta pętla
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    wykonuje się cały czas, więc naokrągło zerujesz ten indeks tablicy, który nazwałeś wskaźnikiem.

    Tzn z tego urywka kodu tak wynika, nie wiem czemu nie pokażesz więcej.
  • REKLAMA
  • #4 10584877
    Fredy
    Poziom 27  
    A czy włączyłeś przerwanie od wysłanego znaku?
  • #5 10585270
    esnow
    Poziom 14  
    @Fredy
    1. to indeks.
    2. tak włączyłem

    
    void USART_Init(unsigned int ubrr)
    {	
    	UBRR0H = (unsigned char)(ubrr>>8);		// Set baud rate 
    	UBRR0L = (unsigned char)ubrr;
    	UCSR0B |= (1<<RXEN0)|(1<<TXEN0);		// Enable receiver and transmitter 
    	
    	UCSR0B |= (1<<RXCIE0)|(1<<TXCIE0);		// przerwania 
    	
    	UCSR0C = (1<<UCSZ00)|(1<<UCSZ01);		// 8 bitów danych, 1 bit stopu, brak parzystości 
    }
    
  • #6 10585418
    nsvinc
    Poziom 35  
    1. Najpierw przczepie się do PuTTY - nie jest to najlepszy terminal do prac debuggerskich...
    2. Co dokładnie robi funkcja USART_TX( ) ?
    3. Zdecyduj się na czym chcesz pracować - na indeksie tablicy, czy na wskaźniku?
    4. Nigdy nie rób czegoś takiego jak "pierwszy bajt w pętli głównej a reszta w przerwaniu". Albo wysyłasz wszystko z pętli głównej poll-ując flagi statusu, albo wysyłasz wszystko z przerwania.
    Powinieneś napisać funkcję, która odpowiednio poustawia index/wskaźnik tego, co chcesz wysłać, a następnie wywoła "ręcznie" przerwanie.
  • REKLAMA
  • #7 10585450
    esnow
    Poziom 14  
    @nsvinc
    ad 1. Zawsze dobrze mi się z putty pracowało.
    ad 2. przepisana funkcja z noty katalogowej Atmela:
    
    void USART_Tx(unsigned char data)
    {
    	while (!( UCSR0A & (1<<UDRE0)));		// Wait for empty transmit buffer 
    	UDR0 = data;							// Put data into buffer, sends the data 
    }
    

    ad 3. na indeksie tablicy
    ad 4. tak mi się wydaje, że wyczytałem o tym gdzieś tak na avr freaks. Zrozumiałem, że trzeba wymusić wysłanie pierwszego znaku aby ustwiła się flaga txc od wysłanego znaku, a reszta wyśle się automatycznie. Ludzie pisali również o wysyłaniu korzystając z przerwania od UDRE - od zwolnienia buforu.

    [quote]
    Powinieneś napisać funkcję, która odpowiednio poustawia index/wskaźnik tego, co chcesz wysłać, a następnie wywoła "ręcznie" przerwanie.
    [/qupte]

    Mógłbyś bardziej rozwinąć tą myśl ?
  • REKLAMA
  • #8 10585483
    nsvinc
    Poziom 35  
    Przerwanie według klasycznej myśli mikrokontrolerów powinno mieć możliwość wywołania go poprzez głupie ustawienie flagi. Zamiast TXować pierwszy bajt w pętli głównej, piszesz funkcję typu:
    Kod: text
    Zaloguj się, aby zobaczyć kod

    Funkcję startTX wywołujesz z pętli głównej, i po jej wywołaniu fraza TEST będzie wysyłana forever, według powyższego przykładu. W if-ie zerującym zmienną możesz dać return - to zakończy całkowicie proces wysyłki tego co w tablicy - żeby wysłać ponownie będziesz musiał jeszcze raz wywołać startTX.

    Niestety nie pomogę ci z samym AVR, bo jestem "chłopem małorolnym potępionym fanatykiem ARMów" (pokręć się na forum to będziesz wiedział o co chodzi).
    Ale sądzę, że u ciebie problem nie dotyczy procesora, tylko algorytmu.
  • #9 10586252
    esnow
    Poziom 14  
    UstawFlagePrzerwaniaOdUART_TX();

    jak to w kodzie rozwiązać ?
  • #10 10586316
    tmf
    VIP Zasłużony dla elektroda
    Może tak - funkcje obsługi przerwań to zasadniczo zwykłę funkcję C, i jak zwykłą funkcję można je wywołać w kodzie programu.
  • #11 10587330
    esnow
    Poziom 14  
    ale z tego co rozumiem po przeczytaniu noty katalogowej, flaga w przerwaniu
    ISR() ustawia się sama po wysłaniu znaku (tx complete)

    to co ma się znaleźć w ciele funckji:
    UstawFlagePrzerwaniaOdUART_TX(); ?

    Próbowałem na różne sposoby. jak wysyłam w taki sposób:
    
    	for(int i=0; i<5; i++)
    		USART_Tx(tekst[i]);
    


    to ładnie wszystko leci, znaczek za znaczkiem.

    Natomiast gdy próbuję nadawać w przerwaniu, dane w putty wyświetlają się etapami, tak po 50 lub więcej znaków na raz. Dzieje się to w różnych odstępach czasu, pomimo, że w programie mam delaya 50ms. Takie coś otrzymuje w przerwaniu:
    [ATmega168][C] wysyłanie stringa/tablicy charów w przerwaniu
  • #13 10590471
    esnow
    Poziom 14  
    dziękuję wszystkim za pomoc !

    udało mi się zrobić, że wysyłanie jest w przewianiu ale pierwszy znak muszę "popchnąć w kodzie":

    
    while(1)
    {
    ...
    	USART_Tx(tekst[wsk_do_wyslania]);
    	wsk_do_wyslania++;
    }
    
    
    ISR(USART_TX_vect)
    {
    		if(wsk_do_wyslania == sizeof(tekst))
    		{
    			wsk_do_wyslania=0;
    			return 0;
    		}
    			
    		UDR0 = tekst[wsk_do_wyslania];
    		wsk_do_wyslania++;
    		
    		PORTD ^= _BV(2);  //mruganie diodą
    }
    


    próbowałem ustawić flagę, ale nie wiem dokładnie jak....

    [ATmega168][C] wysyłanie stringa/tablicy charów w przerwaniu [ATmega168][C] wysyłanie stringa/tablicy charów w przerwaniu

    linijka: UCSR0B |= (1<<TXCIE0); uruchamia przrwania

    a próbując ustawić flagę z palca tak: UCSR0A |= (1<<TXC0); nic się nie dzieje...
  • #14 10605198
    esnow
    Poziom 14  
    To jak ustawić ręcznie tą flagę?
REKLAMA