bedingtes Assemblieren in einem Makro - wie erkenne ich ein Register?



  • Hi

    Habe gerade mit AVR-Assembler begonnen, genauer mit einem ATtiny45.
    Das Ansprechen eines 8x7Segment-Display (MAX7219 Platine, eBay) klappt auch schon befriedigend.

    Nun wollte ich die Routinen für die Ansteuerung des MAX7219 in ein Include-File packen, damit ich Diese einfacher benutzen kann.

    Hier fiel mir auf, daß z.B. die Routine:

    ;Anzeigestellen ändern
    .MACRO MAX7219_ScanLimit	;(i, 0...7// i=immediate = Zahl wird übergeben, @1=Wert)
    	ldi MAX7219BEFEHL,@1
    .if @0=="i"
       ldi MAX7219Wert,@0			;wird eine Zahl (kein Register) übergeben, muß das i als erster Parameter angegeben werde
    .else
    	mov MAX7219Wert,@0			;wenn ein Register übergeben wurde, dann per mov den ersten Parameter laden
    .endif
    	rcall MAX7219_SENDEN		;Daten an Display senden
    .ENDMACRO
    

    MAX7219WERT und MAX7219BEFEHL sind definiert sowie die Ausgaberoutine MAX7219_SENDEN ist vorhanden (die Werte werden bitweise MSB...LSB ausgetaktet und dann übernommen)

    So aufgerufen:

    MAX7219_ScanLimit	(7) ;(klappt)
    MAX7219_ScanLimit ("i", r16) ;(klappt überhaupt nicht)
    

    Ohne den if-Block und ohne das mov klappt die Zahlenübergabe, zum Initiieren wunderbar.
    Wenn ich aber den Rest wieder rein bringe, da ich z.B. einige der Stellen im Programm ausschalten will - wofür sich ein Register ganz gut macht - meckert der Kollege Assembler, daß ich einen unerwarteten String im Aufruf habe.

    Meine Frage an Euch deshalb:
    Wie kann ich überprüfen, ob ein Parameter ein Register oder eine Zahl ist?
    Oder: Wie macht Ihr so was?

    MfG
    posti

    PS: fand dieses Forum via Google bei der Suche nach Assembler und AVR, hoffe, Das passt trotz des Namen C++ halbwegs hier her.



  • Hi

    Scheinbar ein doch nicht so einfaches Problem 🙂

    Da es sich um Makros handelt und Diese eh nur bei Nutzung eingebaut werden, habe ich für beide Fälle eigene Makros erstellt.

    Wie ich einen übergebenen Wert auf ASCII überprüfen kann, ist mir somit immer noch nicht bekannt, geht aber auch so.

    Danke für's Lesen

    ;*************************************
    ;** Routiene dient dem einfachen
    ;** (und fehlerfreiem) Ansprechen
    ;** der 8x7Seg-Anzeige MAX7219
    ;** by posti NOV 2016
    ;*************************************
    ;** Einbinden nur per INCLUDE **
    ;*******************************
    ;** r16 = Wert		=	7219Wert
    ;** r17 = Befehl	=	7219Befehl
    ;** werden zerstört
    ;*************************************
    .EQU PUSHALL=1		;wenn beim SENDEN die Register NICHT gesichert werden sollen, auskommentieren
    
    ;30.11.16	Routinen funktioniert und lassen sich per INCLUDE einbinden (hinter .ORG 0 !!)
    
    ;-----Register-----
    ;
    ;r00...r15
    ;r16...r25
    .MESSAGE "**** Register R16 und R17 werden zerstört ****"
    .def	MAX7219Wert		=	r16
    .def	MAX7219Befehl	=	r17
    ;r26_r27	X
    ;r28_r29	Y
    ;r39_r31	Z
    ;
    ;-----Ports, Portbits-----
    ;Pins für das Display am MAX7219
    .equ	pClockD	=	DDRB	;Richtungsport des Clock-Signal
    .equ	bClockD	=	DDB0	;Bit der Richtung des Clock-Signal
    .equ	pClock	=	PortB	;Port des Clock-Signal
    .equ	bClock	=	PortB0	;Bit des Port
    
    .equ	pOutD	=	DDRB	;Richtungsport
    .equ	bOutD	=	DDB1
    .equ	pOut	=	PortB	;Port des Daten-Signal
    .equ	bOut	=	PortB1	;Bit des Port
    
    .equ	pCSD	=	DDRB	;Richtungsport
    .equ	bCSD	=	DDB2
    .equ	pCS		=	PortB	;Port des CS-Signal (Datenübernahme)
    .equ	bCS		=	PortB2	;Bit des Port
    ;
    ;
    
    ;Name							C/M	Funktion
    ;MAX7219_INIT					C	die PortPins auf OUT und LOW setzen
    ;MAX7219_OFF					M	schaltet die Anzeige aus
    ;MAX7219_ON						M	schaltet die Anzeige an
    ;MAX7219_0xBCD					M	keine Stelle BCD-Decode intern
    ;MAX7219_1xBCD					M	nur letzte Stelle BCD-Decode intern
    ;MAX7219_4xBCD					M	letzte 4 Stellen BCD-Decode intern
    ;MAX7219_8xBCD					M	alle Stellen BCD-Decode intern
    ;MAX7219_Helligkeit	(Register)	M	ändert die Helligkeit
    ;MAX7219_Helligkeit_i (0...15)	M	ändert die Helligkeit
    ;MAX7219_ScanLimit	(Register)	M	Anzahl der anzuzeigeden Stellen ändern
    ;MAX7219_ScanLimit_i (0 ... 7)	M	Anzahl der anzuzeigeden Stellen ändern
    ;MAX7219_TEST	(0/1)			M	Display-Test 0=aus, 1=an
    ;MAX7219_SENDEN					C	r16 (Wert) und r17 (Befehl) an Display senden
    
    ;C= Call aufrufbar
    ;M=	Makro
    
    ;r16 als MAX7219_WERT		benannt
    ;r17 als MAX7219_Befehl		benannt
    
    ;Pins auf Ausgang einstellen, alle auf LOW
    MAX7219_INIT:
    	SBI pClockD,bClockD		;Ausgang für CLK
    	SBI poutD,boutD		;Ausgang für Data
    	SBI pcsD,bcs		;Ausgang für CS
    	cbi pclock,bclock	;Alle aus LOW setzen
    	cbi pout,bout
    	cbi pcs,bcs
    ret
    
    ;Anzeige AUS
    .MACRO MAX7219_OFF
    	ldi MAX7219Wert,0			;0=aus, 1=an
    	ldi MAX7219Befehl,12		;12=Display an/aus
    	rcall MAX7219_SENDEN	;Daten senden
    .ENDMACRO
    
    ;Anzeige AN
    .MACRO MAX7219_ON
    	ldi MAX7219Wert,1			;0=aus, 1=an
    	ldi MAX7219Befehl,12		;12=Display an/aus
    	rcall MAX7219_SENDEN	;richtig :) -> Daten senden
    .ENDMACRO
    
    ;Alle Stellen BCD
    .MACRO MAX7219_8xBCD
    	ldi MAX7219Befehl,0x09
    	ldi MAX7219Wert,0xFF		;alle Stellen BCD-Code
    	rcall MAX7219_SENDEN		;Daten an Display senden
    .ENDMACRO
    
    ;Alle Stellen ohne interne Decodierung
    .MACRO MAX7219_0xBCD
    	ldi MAX7219Befehl,0x09
    	ldi MAX7219Wert,0x00		;keine Stellen BCD-Code
    	rcall MAX7219_SENDEN		;Daten an Display senden
    .ENDMACRO
    
    ;Nur letzte Stelle BCD
    .MACRO MAX7219_1xBCD
    	ldi MAX7219Befehl,0x09
    	ldi MAX7219Wert,0b00000001	;nur letzte Stellen BCD-Code
    	rcall MAX7219_SENDEN		;Daten an Display senden
    .ENDMACRO
    
    ;Nur letzten 4 Stelle BCD
    .MACRO MAX7219_4xBCD
    	ldi MAX7219Befehl,0x09
    	ldi MAX7219Wert,0b00001111	;Stellen 7-4 'normal', 3-0 BCD
    	rcall MAX7219_SENDEN		;Daten an Display senden
    .ENDMACRO
    
    ;Helligkeit ändern_i
    .MACRO MAX7219_Helligkeit_i	;(i, 0...15// i=immediate = Zahl wird übergeben)
    	ldi MAX7219Befehl,10
    	ldi MAX7219Befehl,@0
    	rcall MAX7219_SENDEN		;Daten an Display senden
    .ENDMACRO
    ;Helligkeit ändern
    .MACRO MAX7219_Helligkeit	;(Register = Zahl wird übergeben)
    	ldi MAX7219Befehl,10
    	mov MAX7219Wert,@0
    	rcall MAX7219_SENDEN		;Daten an Display senden
    .ENDMACRO
    
    ;Anzeigestellen ändern
    .MACRO MAX7219_ScanLimit	;(Register = Zahl wird übergeben)
    	ldi MAX7219BEFEHL,11
    	mov MAX7219Wert,@0			;wenn ein Register übergeben wurde, dann per mov den ersten Parameter laden
    	rcall MAX7219_SENDEN		;Daten an Display senden
    .ENDMACRO
    ;Anzeigestellen ändern
    .MACRO MAX7219_ScanLimit_i	;(i, 0...7// i=immediate = Zahl wird übergeben, @1=Wert)
    	ldi MAX7219BEFEHL,11
    	ldi MAX7219Wert,@0			;wenn ein Register übergeben wurde, dann per mov den ersten Parameter laden
    	rcall MAX7219_SENDEN		;Daten an Display senden
    .ENDMACRO
    
    ;Display-Test an/aus
    .MACRO MAX7219_TEST		;(0/1)
    	ldi MAX7219Befehl,15
    	ldi MAX7219Wert,@0			;Wert 0 (Display normal), 1 (alle Segmente an)
    	rcall MAX7219_SENDEN		;Daten an Display senden
    .ENDMACRO
    
    ;Befehl und Wert zum Display senden.
    ;Nach den 16 bit wird ein CS gesendet,
    ;wodurch die Daten übernommen werden
    MAX7219_SENDEN:
    .ifdef PUSHALL
    	push MAX7219BEFEHL
    	push MAX7219WERT
    	.MESSAGE "PUSHALL"
    .else
    	.MESSAGE "kein PUSHALL"
    .endif
    	PUSH MAX7219WERT		;den Wert sichern (wird gleich noch benötigt)
    	ldi MAX7219WERT,16		;ges. 16 Bit austakten
    MAX7219_nextbit:
    	ROL	MAX7219Befehl		;schiebe Bits H...L der Reihe nach raus
    	brcs MAX7219_SET		;das jetzige Bit=1? (Überlauf? -> nach SET springen)
    	cbi pout,bout			;Port auf LOW
    	rjmp MAX7219_TAKT		;zum Clock-Takt springen
    MAX7219_SET:
    	sbi pout,bout			;Port auf HIGH
    MAX7219_TAKT:
    	sbi pclock,bclock		;Clock auf HIGH
    	cbi pclock,bclock		;Clock auf LOW	(Bit in Schieberegister übernehmen)
    	dec MAX7219WERT			;Anzahl an Bits -1
    	breq MAX7219_Fertig		;=0? -> Fertig
    	cpi MAX7219WERT,8		;=8?
    	brne MAX7219_nextbit	;nein, dann nächstes Bit
    	POP MAX7219Befehl		;ja, gesicherten Wert zurück holen in 'Befehl', da dieses Register durchgeschoben wird
    	rjmp MAX7219_nextbit
    MAX7219_Fertig:
    	sbi pCS,bCS				;CS auf HIGH
    	cbi pCS,bCS				;CS auf LOW	(Daten aus Schieberegister übernehmen)
    .ifdef PUSHALL
    	pop MAX7219WERT
    	pop MAX7219BEFEHL
    .endif
    
    ret
    

    TAG: SPI, MAX7219, ATtiny, AVR, Assembler, Include, 7-Segment, Anzeige, 8x7-Segment

    Einfach bei eBay 'MAX7219' suchen - gibt Dot-Matrix 8x8 und 7-Segment mit 8 Stellen zur Anzeige bis 99999999


Anmelden zum Antworten