-         

Ergebnis 1 bis 3 von 3

Thema: [gelöst]Software UART (AVR305) als inline ASM in GCC

  1. #1
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    22.11.2005
    Ort
    Braunschweig
    Alter
    41
    Beiträge
    685

    [gelöst]Software UART (AVR305) als inline ASM in GCC

    Anzeige

    Moin!
    Ich habe hier ein Phänomen, meine tapfere SW-UART Routine funktioniert 'plötzlich' nicht mehr. Ich habe mal alles rausgeschmissen und nur die senderoutine mit einer Schleife dringelassen, aber irgendwie klappt das alles nicht mehr. -zum Hintergrund muß ich sagen, daß ich vor kurzem auf WinAVR-20080610 und das aktuelle AVR Studio aktualisiert habe, der Code selbst ist unverändert.
    Hier mal mein Programm :
    Code:
    #include <util/delay.h>
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    void txd(uint8_t value)
    {
    	uint8_t bitcnt;
    	uint8_t delay;
    
    	__asm__ __volatile__(
    		"cli\n\t"
    		"ldi	%0,0x0a\n\t"	//;1+8+sb (sb is # of stop bits)
    		"com	%2\n\t"		//;Inverte everything
    		"sec\n\t"			//;Start bit
    
    		"0:brcc 1f\n\t"		//;If carry set
    		"sbi	0x15,5\n\t"	//;send a '0'
    		"rjmp 2f\n\t"		//;else	
    
    		"1:cbi	0x15,5\n\t"	//;send a '1'
    		"nop\n\t"
    
    		"2:rcall 3f\n\t"		//;One bit delay
    		"rcall 3f\n\t"
    
    		"lsr %2\n\t"	                //;Get next bit
    		"dec	%0\n\t"		//;If not all bit sent
    		"brne 0b\n\t"		//;send next
    		"sei\n\t"			//;else
    		"ret\n\t"			//;  return
    
    		"3:ldi	%1,19\n\t"
    		"4:dec	%1\n\t"
    		"brne 4b\n\t"
    		"ret\n\t"
    
    
    		:"=r"(bitcnt),"=r"(delay),"=r"(value):"2"(value));
    
    }
    /*
    BaudRate	Cycles required	b-value		Error %  
    2400		6667	 		(2) 1107  	0
    4800		3333	 		(2) 552  	0
    9600		1667	 		(2) 274  	0
    14400		1111			181			0,2
    19200		833				135			0
    28800		556				89			0,3
    57600		278				42			1
    115200		139				19			1,4
    */
    
    
    
    
    
    int main(void)
    
    {
    	unsigned char cnt;
    		
    	DDRC = (1<<PC5);
    	
    	for (cnt=0;cnt<100;cnt++) txd(10);
    
    	return 0;
    }
    Der Fehler war, daß das Programm immer eine 0 sendete und dann nichts mehr. Als ich dann bei den Operanden am Ende das '):"2"(value)' ergänzte, bekam ich immerhin das korrekte Zeichen, aber nur einmal. Auch mit der Schleife bekomme ich jetzt nur einmal eine 10, danach bleibt das Programm stehen bzw. es kommt ncihts mehr. Bei der Verwendung in meinem ursprünglichen Programm, wo ich den Inhalt eines Arrays senden will, bleibt das Programm zwar nicht stehen, aber der Controller scheint einen Reset zu machen ö.ä., da ich statt des Arrays immer nur den ersten Wert des Arrays bekomme und danach das Programm neu startet, daher vermute ich, daß irgendwas mit den Registern nicht passt, aber ich komm leider einfach nicht dahinter. Vielleicht kann mir einer einen Tipp geben, wieso das jetzt 'auf einmal' nicht mehr funktioniert??
    Vielen Dank schonmal!!

    MfG Volker
    Meine kleine Seite
    http://home.arcor.de/volker.klaffehn
    http://vklaffehn.funpic.de/cms
    neuer Avatar, meine geheime Identität

  2. #2
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Ich kann die Delayroutine zu rcall 3f nicht finden. Das sollte wenigstens eine warnung geben-

  3. #3
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    22.11.2005
    Ort
    Braunschweig
    Alter
    41
    Beiträge
    685
    Moin!
    Na das ist die ab dem '3:'
    Das ganze hat sich aber gerade sowieso erledigt:

    einmal meine softuart.c

    Code:
    #include "softuart.h"
    
    void txd (unsigned char value) 
    { 
       uint8_t bitcnt = 1+8+STOP_BITS; 
       uint8_t delay = bvalue;	//see softuart.h 
    
       value = ~value; 
    
       cli(); 
    
       __asm__ __volatile__( 
          "      sec             ; Start bit           " CR_TAB 
    
          "0:    brcc 1f              ; If carry set   " CR_TAB 
          "      sbi   %[port],%[pad] ; send a '0'     " CR_TAB 
          "      rjmp 2f              ; else           " CR_TAB 
    
          "1:    cbi   %[port],%[pad] ; send a '1'     " CR_TAB 
          "      nop"                                    CR_TAB 
    
          "2:    %~call bit_delay_%=  ; One bit delay  " CR_TAB 
          "      %~call bit_delay_%="                    CR_TAB 
    
          "      lsr   %[value]   ; Get next bit        " CR_TAB 
          "      dec   %[bitcnt] ; If not all bit sent " CR_TAB 
          "      brne 0b         ; send next           " CR_TAB 
          "      rjmp 5f         ; else: done          " CR_TAB 
                                                         CR_TAB 
          "bit_delay_%=:"                                CR_TAB 
          "      mov   __zero_reg__, %[delay]"           CR_TAB 
          "4:    dec   __zero_reg__"                     CR_TAB 
          "      brne 4b"                                CR_TAB 
          "      ret"                                    CR_TAB 
          "5:"                                           CR_TAB 
    
          : [bitcnt] "=r" (bitcnt), [value] "=r" (value) 
          : "1" (value), "0" (bitcnt), [delay] "r" (delay), [port] "M" (_SFR_IO_ADDR(SWUART_PORT)), [pad] "M" (SWUART_PIN) 
       ); 
    
       sei(); 
    }
    und dazu meine softuart.h
    Code:
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    #define CR_TAB "\n\t" 
    #define STOP_BITS 1 
    
    #define bvalue 19	//115200 Baud
    #define SWUART_PORT PORTC	//TX Port
    #define SWUART_PIN	5		//TX Pin
    
    /*
    b-values for 16 MHz
     
    BaudRate   	Cycles required   	b-value		Error %  
    2400      	6667          		(2) 1107    0 
    4800      	3333          		(2) 552     0 
    9600      	1667          		(2) 274     0 
    14400      	1111         		181         0,2 
    19200      	833            		135         0 
    28800      	556            		89         	0,3 
    57600      	278            		42         	1 
    115200      139            		19         	1,4 
    */ 
    
    
    void txd (unsigned char value) ;
    Bei anderen Frequenzen in der AppNote AVR305 nachschauen...
    Dieser Software-UART braucht nichts außer einem freien Pin, praktisch zum debuggen z.B..
    Falls das noch jemand braucht, einfach in der softuart.h Port und Pin sowie Verzögerung für die Baudrate lt. Liste anpassen und los gehts.

    Trotzdem danke!!
    Meine kleine Seite
    http://home.arcor.de/volker.klaffehn
    http://vklaffehn.funpic.de/cms
    neuer Avatar, meine geheime Identität

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •