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

[Atmega8 Asm]Nie można wysłać dwóch liczb pod rząd

tmkd 25 Kwi 2010 00:52 1188 10
  • #1 8000100
    tmkd
    Poziom 11  
    Witam, dziwna rzecz się dzieje w moim programie. W pętli głównej mam ustawione wysyłanie dwóch liczb na przemian. Jednak gdy odbieram je przez rs-a dostaję tylko pierwszą. To jest mój kod
    Pętla głowna
    
    main:
    	ldi tmp,0x2
    	push tmp
    	rcall UART_send
    
    	ldi tmp,0x3
    	push tmp
    	rcall UART_send
    	nop
    	nop
    
    
    rjmp main
    

    Funkcja wysyłająca
    
    UART_send:
     	pop arg1
    	pop arg2
    	pop tmp
    
        loop:
    	sbis UCSRA,UDRE
    	rjmp loop
        out UDR,tmp
    
    
    	push arg2
    	push arg1
    
    RET

    Konfiguracja UART
    
    ldi tmp,0x0   
    push tmp								;UCSRA
    
    ldi tmp,(1<<TXEN)|(1<TXCIE) 			;UCSRB
    push tmp 	
    										;2 bity stopu, 
    ldi tmp,(1<<URSEL)|(1<<USBS)|(3<<UCSZ0)	;UCSRC(UMSEL=0 URSEL=1(zeby nie zmienic UBRRH)
    push tmp
    ;ubrr	
    ldi tmp, 0xC;ubrrl							
    push tmp
    ldi tmp, 0x0;ubrrh
    push tmp
    rcall UART_init
    rjmp main
    
  • #2 8000470
    asembler
    Poziom 32  
    Nie rozumiem dlaczego nie przekażesz bezpośrednio argumentu "temp" do wywoływanej procedury. tylko przekazujesz to przez stos "tracąc" przy tym dwa rejestry i kilka bajtow pamieci tym bardziej ze nie deklarujesz stosu. W ogóle to dziwnie ładujesz rejestry konfiguracyjne komentarzami:-)
  • #3 8000481
    tmkd
    Poziom 11  
    Nie ładuje nic komentarzami. jest przeciez
    
    ldi tmp,(....)|(...) ; komentarz. 
    

    Komentarz się nie ładuje do tmp.
    Stos mam zadeklarowany. Nie wkleiłem tego sory.
    Bezpośrednio czyli tak że mam jeden rejestr na argumenty i procedury zawsze tam ich szukają?
  • #4 8001976
    OlekM
    Poziom 17  
    Włączasz przerwanie od UART'u ustawiając bit TXCIE, więc po każdym wysłaniu znaku procesor skacze do wektora przerwania - który zapewne nie jest wypełniony a to ma skutek (prawie) jak reset.
  • #5 8002003
    asembler
    Poziom 32  
    Pod warunkiem że odblokowane są globalne przerwania, ale tego sie mozemy tylko domyslac. Brak całosci kodu a przynajmniej istotnych fragmentów.
    Usun wszsytkei push i pop i zrób to po ludzku.
  • #6 8003707
    tmkd
    Poziom 11  
    Niestety nie pomogło, poniżej pokażę kod
    główny plik rs.asm
    
    .nolist
    .include "m8def.inc"
    .list
    .def tmp=R16
    .def tmp2=R19
    ;rejestry gdzie laduje argumenty funkcji
    .def arg1=R17
    .def arg2=R18
    .equ TIMER_OFFSET=0x00
    .equ TIMER_PRESCALER=0x2
    .equ TIMER_STOP=0x0
    
    ldi tmp,HIGH(RAMEND)
    out SPH,tmp
    ldi tmp,LOW(RAMEND)
    out SPL,tmp
    ldi tmp,1<<IVCE
    out GICR,tmp
    ldi tmp,1<<IVSEL
    out GICR,tmp
    
    
    ;USART
    rcall UART_init
    rjmp main
    
    ;TIMER0
    rcall TIMER0_init
    
    ;ADC
    rcall ADC_init
    
    main:
    	ldi tmp,0x2
    	push tmp
    	rcall UART_send
    
    	ldi tmp,0x3
    	push tmp
    	rcall UART_send
    	nop
    	nop
    
    
    rjmp main
    
    .include "ADC.inc"
    .include "UART.inc"
    .include "TIMER0.inc"
    
    .org 0xc09
    rjmp TIMER0_OVF
    .org 0xc0d
    rjmp USART_TXC
    .org 0xc0e
    rjmp ADC_COMPLETE
    

    UART
    
    UART_init:
    cli
    	;UCSRA
    	ldi tmp,0x0
    	out UCSRA,tmp
    
    	;UCSRB
    	ldi tmp,(1<<TXEN)
    	out UCSRB,tmp
    
    	;UCSRC
    	ldi tmp,(1<<URSEL)|(1<<USBS)|(3<<UCSZ0)	
    	out UCSRC,tmp
    
    	;UBRRL
    	ldi tmp,0xC
    	out UBRRL,tmp
    	;UBRRH
    	ldi tmp,0x0
    	out UBRRH,tmp
    
    
    
    sei
    RET
    
    
    UART_send:
     	pop arg1
    	pop arg2
    	pop tmp
    
        loop:
    	sbis UCSRA,UDRE
    	rjmp loop
        out UDR,tmp
    
    
    	push arg2
    	push arg1
    
    RET
    
    USART_TXC:
        ldi tmp,0x5
    	push tmp
    	rcall UART_send
    	
    
    RETI
    
    


    Dodano po 31 [minuty]:

    Co ciekawe, w programie który czyta z rs-a gdy co chwila zamykam/otwieram polaczenie to pojawiają się raz jedynki , raz dwójki.
  • #7 8003753
    OlekM
    Poziom 17  
    Proszę spróbować następującej sekwencji uruchamiającej UART. Na symulatorze zachowuje się ona "lepiej". Oryginalna wersja traciła wpis w rejestrze UCSRC.

    
    UART_init:
    cli
       ;UBRRH
       ldi tmp,0x0
       out UBRRH,tmp
    
       ;UBRRL
       ldi tmp,0xC
       out UBRRL,tmp
    
       ;UCSRA
       ldi tmp,0x0
       out UCSRA,tmp
    
       ;UCSRB
       ldi tmp,(1<<TXEN)
       out UCSRB,tmp
    
       ;UCSRC
       ldi tmp,(1<<URSEL)|(1<<USBS)|(3<<UCSZ0)   
       out UCSRC,tmp
    
    sei
    RET 
    
  • #8 8003819
    asembler
    Poziom 32  
    Jak nie usuniesz tych pop i push to nigdy ten program nie ruszy. Ja sie w ogole dziwie ze to dziala choc troche. przeciez stosujac tylko push w petli głownej nastepuej mazanie calej pamieci RAM łacznie ze stosem a to w krótkiej chwili prowadzi program w maliny.
    Ty nie masz pojecia o ASM a jak ci ktos radzi to sobie olewasz.
    Radź sobie sam.
    OLeKM dawanie mu jakichkolwiek dodatkowych programow mija sie z celem gdyz dołaczenie nawet idealnie dzialajacego podprogramu i tak nic nie da poniewaz jeden zle uzyty pop lub push załatwia program na cacy.
  • #9 8003910
    tmkd
    Poziom 11  
    Wczoraj miałem pomieszane pliki i wstawiłem starą wersję z push. Dlaczego następuje mazanie? Przecież to co wstawiłem w mainie i tak zdejmuję w funkcji?
    Co do kolejność OlekM masz rację. Przecież UCSRC i UBRRH mają tą samą przestrzeń adresową, dlatego najpierw UCSRC z URSEL a ptem UBRRH. Ale dopiero po poludniu to sprawdze. Pozdrawiam.
  • #10 8128221
    Maślakmj
    Poziom 13  
    Witam,
    OlkuM, Twój program natomiast traci zawartość UBRRH, więc jeżeli będziemy chcieli zmienić długość ramki, ilość bitów stopu, czy to jest równoznaczne ze zmianą szybkości transmisji ?
    Panie Asembler, z pisaniem programów jest podobnie jak z jazdą autem, wszyscy robią to trochę inaczej i wszystkim wydaje się, że są w tym najlepsi ;)
    pozdrawiam
  • #11 8129178
    OlekM
    Poziom 17  
    Cytat:

    OlkuM, Twój program natomiast traci zawartość UBRRH, więc jeżeli będziemy chcieli zmienić długość ramki, ilość bitów stopu, czy to jest równoznaczne ze zmianą szybkości transmisji ?


    Do niedawna byłem "niemalże pewien", że prędkość transmisji w takim przypadku nie ulegnie zmianie. Aby jednak zweryfikować swoje poglądy napisałem prosty program testowy (ATMEGA8 @ 12MHz):

    
    #include <avr/io.h>
    #include <util/delay.h>
    
    #define BAUD_SINGLE(x) (F_CPU/(16*(x))-1)
    
    void print(char * c)
    {
    	while(*c)
    	{
    		while(!(UCSRA & (1<<UDRE)));
    		UDR = *c++;
    	}
    }
    
    int main(void)
    {
    	UBRRH = 0x00;
    	UBRRL = BAUD_SINGLE(38400);
    	UCSRA = 0x00;
    	UCSRB = (1<<TXEN);
    	while(1)
    	{
    		//zmienimy kilka razy tryb liczenia parzystości
    		_delay_ms(200);
    		UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0) | (1 << UPM1); //even
    		print("even parity\r\n");
    
    		_delay_ms(200);
    		UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0) | (1 << UPM1) | (1 << UPM0); //odd
    		print("odd parity\r\n");
    
    		_delay_ms(200);
    		UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);
    		print("no parity\r\n");
    
    		//przeskok na inną predkość
    		_delay_ms(200);
    		UBRRL = BAUD_SINGLE(57600);
    		print("57600\r\n");
    
    		//i powrót na 38400
    		_delay_ms(200);
    		UBRRL = BAUD_SINGLE(38400);
    		print("38400\r\n");
    	}
    }
    


    Wyniki działania (obserwacja z prędkością 38400bps):
    
    even parity
    odd parity
    no parity
    \0xee\0xbd\0xb1\0x81
    38400
    even parity...
    


    Wnioski są następujące:
    1. mój program odbierający znaki zupełnie zignorował parzystość (próbowałem w kilku trybach, otrzymując identyczne wyniki)
    2. zmiana rejestru UCSRC w przedstawiony sposób nie wpływa na nastawę prędkości
    3. prędkość transmisji można zmieniać także "w biegu" - choć to z pewnością nie jest zalecana praktyka

    Mógłbym podejrzeć na analizatorze stanów logicznych, czy rzeczywiście parzystość się zmienia... ale w sumie celem było udowodnienie, że zapis do UCSRC nie zaburzy rejestru UBRR - co udało się wykazać.

    Co do wygenerowanego kodu asemblera, to kompilator nie robi w nim żadnych trików - oto przykład:

    
      26:	11 24       	eor	r1, r1 ; wyzeruj r1
    ...
      80:	10 bc       	out	0x20, r1	; zapisz 0 do UBRRH (ale nie UCSRC)
      82:	82 e1       	ldi	r24, 0x12	; załaduj 18 do r24
      84:	89 b9       	out	0x09, r24	; przepisz z r24 do UBRRL
      86:	1b b8       	out	0x0b, r1	; zapisz 0 do UCSRA
      88:	88 e0       	ldi	r24, 0x08	; załaduj (1<<TXEN) do r24
      8a:	8a b9       	out	0x0a, r24	; zapisz z r24 do UCSRB
    ...
      9c:	86 e8       	ldi	r24, 0x86	; załaduj (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0) do r24
      9e:	f8 2e       	mov	r15, r24	; przepisz z r24 do r15
    ...
      e2:	f0 bc       	out	0x20, r15	; zapisz z r15 do UCSRC (ale nie UBRRH)
    


    Teraz mogę stwierdzić, że mam pewność co do prawdziwości swojej tezy :-)
REKLAMA