- Akku Tests und Balkonkraftwerk Speicher         
Seite 2 von 2 ErsteErste 12
Ergebnis 11 bis 17 von 17

Thema: Portierung von Software-UART auf ATTiny26

  1. #11
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Anzeige

    LiFePo4 Akku selber bauen - Video
    Zitat Zitat von vklaffehn
    Und Assembler deswegen, weil das Timing ja ziemlich kritisch ist.
    Genau dafür gibt es Timer. Wenn (andere) IRQs aktiv sind kannst du mit ner Zählschleife eh nix anfangen...
    Disclaimer: none. Sue me.

  2. #12
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    22.11.2005
    Ort
    Braunschweig
    Alter
    47
    Beiträge
    685
    Hallo!
    Die Timer sind leider schon anderweitig belegt, und die USI-Schnittstelle auch, sonst wäre das ganze ja viiiel zu einfach Die Routine soll ja auch nur gelegentlich ein einzelnes Byte rüberschicken, da kann ich ja kurz meine IRQ's stoppen, das ist bei denen nicht ganz so kritisch. Ich werd jetzt mal ein wenig rumprogrammieren, meld mich bei bedarf wieder!

  3. #13
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    22.11.2005
    Ort
    Braunschweig
    Alter
    47
    Beiträge
    685
    Moin, schönen Valentinstag!
    Es geht!!! Nach viel grübeln ist mir aufgefallen, daß ich, wenn ich keinen RS232-Treiber nehme, ich die Signale schon Softwaremäßig invertieren muß.... (Jaa, ich weiß, man sollte nicht direkt mit TTL an RS232, aber meine kleinen Picaxe machen das auch alle und es funktioniert) Die Routine funktioniert, selbst wenn ich den ATTiny26 mit dem internen PLL auf 16MHz takte (lt. Datenblatt S.32), sauber bei 115200 baud. Mit Treiber muß man halt wieder 'sbi' und 'cbi' vertauschen. Im Moment ist der Port,Pin und die Verzögerung (siehe AppNote AVR305) hardcoded, da werd ich noch dran feilen. Außerdem bin ich mir nicht sicher, ob das mit dem Inline-ASM-Operanden so richtig ist, auch wenn's funktioniert. Vielleicht kann da mal jemand drübergucken, der sich mit sowas auskennt.

    Hier mal mein Code:
    Code:
    #include <avr/io.h>
    #include <util/delay.h>
    
    
    void init_uart()
    {
    	DDRA |= (1<<0);
    	PORTA = 0;
    }
    
    void txd(uint8_t data)
    {
    	uint8_t bitcnt;
    	uint8_t delay;
    
    	__asm__(
    		"		ldi	%A0,0x0a\n\t"			//;1+8+sb (sb is # of stop bits)
    		"		com	%A1\n\t"				//;Inverte everything
    		"		sec\n\t"					//;Start bit
    
    		"0:		brcc 1f\n\t"		//;If carry set
    		"		sbi	0x1b,0\n\t"			//;send a '0'
    		"		rjmp 2f\n\t"		//;else	
    
    		"1:		cbi	0x1b,0\n\t"			//;send a '1'
    		"		nop\n\t"
    
    		"2:		rcall 3f\n\t"		//;One bit delay
    		"		rcall 3f\n\t"
    
    		"		lsr	%A1\n\t"				//;Get next bit
    		"		dec	%A0\n\t"				//;If not all bit sent
    		"		brne 0b\n\t"		//;send next
    										//;else
    		"		ret\n\t"					//;  return
    
    		"3:		ldi	%C0,19\n\t"
    		"4:		dec	%C0\n\t"
    		"		brne 4b\n\t"
    		"		ret\n\t"
    
    		::"r"(bitcnt),"r"(data),"r"(delay));
    
    }
    
    
    int main(void)
    {
    	uint8_t x,y;
    
    	init_uart();
    	{
    	for (y=0;y<124;y++)
    		{
    			for (x=0;x<128;x++)
    			{
    				txd(y);
    				//_delay_ms(4000);
    			}
    		}
    	}
    return 0;
    }
    Meine kleine Seite
    http://home.arcor.de/volker.klaffehn
    http://vklaffehn.funpic.de/cms
    neuer Avatar, meine geheime Identität

  4. #14
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    1. Man sollte asm volatile (anstatt asm) nehmen, damit GCC nicht auf die Idee kommt, was wegzuoptimieren. Das inline asm hat ja keine output-Operanden, also aus gcc-Sicht keine Wirkung auf die Welt.
    2. Sollte das %C0 nicht ein %A2 sein?
    3. Zur Sicherheit sollte dem GCC mitgeteilt werden, daß sich Regsiterinhalte ändern. Momentan gibt es wohl keine Probleme, aber wenn du txd zum Beispiel als static deklarierst, kann GCC es inlinen und das asm verändert Register, ohne daß GCC was davon merkt. Das Problem könnte IMHO auch auftauchen ohne inlining, weil nur nichtinitialisierte Variablen als Input(!)operanden verwendet werden. Die Operanden sind hier also besser Output-Operanden.
    Disclaimer: none. Sue me.

  5. #15
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    22.11.2005
    Ort
    Braunschweig
    Alter
    47
    Beiträge
    685
    Hallo!!
    Hier mal die Funktion, wie ich sie jetzt verwende :
    Code:
    void txd(uint8_t data)
    {
    	uint8_t bitcnt;
    	uint8_t delay;
    
    	__asm__ __volatile__(
    		"		cli\n\t"
    		"		ldi	%A0,0x0a\n\t"			//;1+8+sb (sb is # of stop bits)
    		"		com	%A2\n\t"				//;Inverte everything
    		"		sec\n\t"					//;Start bit
    
    		"0:		brcc 1f\n\t"		//;If carry set
    		"		sbi	0x1b,6\n\t"			//;send a '0'
    		"		rjmp 2f\n\t"		//;else	
    
    		"1:		cbi	0x1b,6\n\t"			//;send a '1'
    		"		nop\n\t"
    
    		"2:		rcall 3f\n\t"		//;One bit delay
    		"		rcall 3f\n\t"
    
    		"		lsr	%A2\n\t"				//;Get next bit
    		"		dec	%A0\n\t"				//;If not all bit sent
    		"		brne 0b\n\t"		//;send next
    		"		sei\n\t"								//;else
    		"		ret\n\t"					//;  return
    
    		"3:		ldi	%A1,19\n\t"
    		"4:		dec	%A1\n\t"
    		"		brne 4b\n\t"
    		"		ret\n\t"
    
    		:"=r"(bitcnt),"=r"(delay),"=r"(data));
    
    }
    Wenn ich die Operanden so übergebe, brauche ich dem Compiler nichts über veränderte Register sagen, der entscheidet ja eh selbst, welche er nimmt, richtig?

    So, und das ganze läuft zur Zeit wunderbar zusammen mit meiner GBCAM, der T26 auf 16MHz, der ADC Prescaler auf 2 (!!), schalte ich die serielle Übertragung ab und lese nur die Kamera aus, dann komme ich auf ca. 10 fps, getestet mit einer LED, die nach jedem Bild kurz blinkt.
    Meine kleine Seite
    http://home.arcor.de/volker.klaffehn
    http://vklaffehn.funpic.de/cms
    neuer Avatar, meine geheime Identität

  6. #16
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    1. data ist IN *und* out
    2. RET ist nicht in Ordnung, weil du nicht wissen kannst, wie der Epilog der Funktion aussieht (hier besteht er wirklich nur aus einem RET, aber was, wenn es einen Framepointer gibt oder Register vom Stack gepoppt werden müssen?)
    3. In deinem Code steht 0x1b, das ist DDRB !?. Treibst du den Ausgang als Open Collector? Falls nicht (push-pull), muss da PORTB hin.


    Code:
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    #define CR_TAB "\n\t"
    #define STOP_BITS 1
    
    void txd (uint8_t data)
    {
       uint8_t bitcnt = 1+8+STOP_BITS;
       uint8_t delay = 19;
    
       data = ~data;
    
       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   %[data]   ; 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), [data] "=r" (data)
          : "1" (data), "0" (bitcnt), [delay] "r" (delay), [port] "M" (_SFR_IO_ADDR(PORTB)), [pad] "M" (6)
       );
    
       sei();
    }
    Disclaimer: none. Sue me.

  7. #17
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    22.11.2005
    Ort
    Braunschweig
    Alter
    47
    Beiträge
    685
    Hallo!!

    SUPER!! Danke, genau das, worauf ich hinauswollte, auch wenn 0x1b lt. Datenblatt PORTA ist Jetzt raff ich glaube ich so langsam, wie diese Operanden funktionieren, und das [port] "M" (_SFR_IO_ADDR(PORTB)) hatte ich schonmal gesehen, aber danach nicht mehr wiedergefunden!!
    Nochmal vielen Dank für die Mühe! Jetzt kommt erstmal der nächste Teil, nämlich mein Fahrwerk mit Odometrie nachzurüsten. Da tauchen bestimmt noch weitere Fragen auf.
    Meine kleine Seite
    http://home.arcor.de/volker.klaffehn
    http://vklaffehn.funpic.de/cms
    neuer Avatar, meine geheime Identität

Seite 2 von 2 ErsteErste 12

Berechtigungen

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

12V Akku bauen