Assembler RFN12b an Tiny44 und Tiny2313 via USI

Im Sender-Code aus #16 steht beim rfninit-Kommentar "Empfänger".
Hast Du da die korrekten Bytes für den Sender?
Bei mir wird die fehlende "stddelay.inc" am Ende bemängelt - wo finde ich die (sonst würde ich zum testen die ganze delays auskommentieren)
Hast Du den USI-Verkehr mal mit einem Logicanalyzer mitgeloggt?

Ich hab hier lediglich zwei Tiny2313A und einen Tiny26 mit USI (allerdings SMD und nur einen passenden Testsockel), und kein Funkmodul zum testen...
(Und einen Logic8)

Hast Du'n Link auf das verwendete Datenblatt des Funkmoduls? (ich hab bisher nur was zu elektrischen und mechanischen Daten gefunden, aber nichts zu den Kommandos)

Ich denke mal das USI=USI egal welcher kontroller.
Nein, beim Tiny2313 gibt's beim Empfang zB das Buffer-Register nicht, beim 44er mMn schon. Nach möglicherweise weiteren Unterschieden hab ich noch nicht gesucht...)

Ich würde mal versuchen, Deinen Sender mit 'nem 2313A nachzustricken, und mit 'nem Logic8 zu verfolgen...
 
Stdelay.inc


CodeBox Assembler

.equ t1ms = ( XTAL * 1 / 606 ) / 1000

delay5ms:
push temp1
ldi temp1,5
WGLOOP2:
rcall delay1ms
dec temp1
brne WGLOOP2
pop temp1
ret



delay10ms:
push temp1
ldi temp1,10
WGLOOP3:
rcall delay1ms
dec temp1
brne WGLOOP3
pop temp1
ret



delay100ms:
push temp1
ldi temp1,100
WGLOOP4:
rcall delay1ms
dec temp1
brne WGLOOP4
pop temp1
ret



delay1s:
push temp1
ldi temp1,10
WGLOOP5:
rcall delay100ms
dec temp1
brne WGLOOP5
pop temp1
ret







delay1ms:                               ; 5ms Pause
          push temp1
          in temp1, sreg
          push temp1
          push temp2
         
           ldi  temp1, t5ms
WGLOOP0:   ldi  temp2, $C9
WGLOOP1:   dec  temp2
           brne WGLOOP1
           dec  temp1
           brne WGLOOP0

          pop temp2
          pop temp1
          out sreg, temp1
          pop temp1
           ret                          ; wieder zurück

nur eine zerstückelung von loops hat aber bis jetzt immer sienen dienst getan.
das Datenblatt welches ich für am vertrauenswürdigsten halte findet du hier
http://www.hoperf.com/upload/rf/RFM12B.pdf
ab seite 15 gehts um die kommandos
desweiteren gibt es hier
http://tools.jeelabs.org/rfm12b.html
einen calculator für die commands

habe soeben noch einen tiny 2313a aus einer ehemals gebauten Uhr mit ein bisschen LED schnickschnack ausgebaut und geflashed.
 
Den sender zu aktivieren deaktiviert angeblich den Empfänger. Es ist lediglich ein byte was geändert werden muss und wird in send_byte mit initialisiert und nach dem senden und einem delay wieder deaktiviert.
Wenn du die Zeit investieren möchtest bestell ich dir gerne 2 module zu dir nach hause. die 7 € wär es mir wert. Ich hab nun mal das minimale aus dem Code rausgezogen und geflasht. Versuch das statusregister auszulesn liefert immer 0. Auch stiftet die pinbelegung verwirrung. kommt jetzt sdo an DI oder an DO des AVR...
 
Zuletzt bearbeitet:
Hi
Ich habe mr bisher deinen Code noch nicht angesehen, aber mal eine banale Frage: bist du dir sicher, das du das richtige Hex-File in den Controller schiebst. Ist mir auch schon passiert, das im AVR Studio das Hex- File noch auf einem anderen Projekt basierte und ich zwei Stunden mich gewundert habe, das selbst die simpelsten Änderungen keinen Erfolg brachten.
Nun ein weiterer Hinweis. Da ich im Verlauf meiner Programmierung oft genug vor dem Problem gestanden habe, das ein Controller mit meinem Assemblerprogramm so ganz eigene Vorstellungen von Abarbeitungen entwickelt hat, hab ich mir erlaubt, ihm mal auf seine Innereien zu schauen und ein Programm entwickelt, welches mir die Inhalte der Variablen zur Laufzeit anzeigt. Schau mal in der Suche nach OpenEye. Das Proramm hab ich mal vor Jahren veröffentlicht. Eine Neuauflage hab ich in einem Buch vorgestellt zur Selbstprogrammierung in Visual Basic. Ist allerdings noch nicht öffentlich. Da geht es auch in der Hauptsache um die Zusammenarbeit von µC und PC. Die Grundlage dafür bietet die Anleitung zur Erstellung des Open_Eye-Programms. Nun, ein paar Tage (Wochen?) brauch ich aber noch, bis es nach meinem Geschmack sein Geld wert sein wird. Deinen Assemblercode nehm ich mir mal vor, wenn ich etwas mehr Zeit habe.
Bis denn..
Gruß oldmax
 
Hi
Noch ein Hinweis, da nicht ausreichend geprüft, aber eine böse Falle.
Du rufst in einer Interrupt Service Routine mit RCALL ein anderes Unterprogramm auf.


CodeBox Assembler
;****************************************************************
;INTERRUPTHANDLERS
;****************************************************************
Ext0_int_handle:
;;Daten stehen bereit
;;Auslesen
rcall read_byte
reti


Nun ist eine ISR aber irgendwann einmal aktiv. Das kann an jeder ! Stelle im Programm sein. Schaust du dir nun die Routine Read_Byte an


CodeBox Assembler
read_byte:
;;DATENBYTE befindet sich in LSB
ldi msb, 0xB0
ldi lsb, 0x00
rcall send_command
in lsb, USIDR
ret

gibt es keine Sicherung des Statusregisters und der Register msb und lsb. Dazu kommt ein weiterer Aufruf eines Unterprorammes. Nun, genau genommen muss es nichts heißen und kann funktionieren, aber die Gefahr, einen benötigten Registerwert zu überschreiben oder nach einem Vergleich das Statusbit aus dem Ergebnis zu verändern, ist sehr groß. Darum versuche, in einer ISR zu bleiben. Dann weißt du auch, ob du in der ISR das Statusregister veränderst oder welche Register du sonst noch beschreibst und kannst sie mit Push und POP auf dem Stack sichern. Es geht aber auch einfach mit der Verwendung von Flags. Wenn du eine ISR hast, die kurze Signale erfasst, zur Verarbeitung aber genug Zeit bleibt, dann kannst du dir in der ISR ein Bit setzen, welche dann in der Programmschleife abgefragt und die eigentliche Bearbeitung komplett außerhalb der ISR ermöglicht. Such mal den Beitrag "Keine Angst vor Assembler". Dort ist dieses Vorgehen etwas genauer beschrieben.
Gruß oldmax
 
Auch stiftet die pinbelegung verwirrung. kommt jetzt sdo an DI oder an DO des AVR...
Beim echten SPI werden alle MOSI miteinander verbunden, und alle MISO miteinander. Die Datenrichtung an den Beinen ergibt sich dann je aus der Konfiguration des jeweiligen Controllers. Insbesondere kannst Du das ganze auch umkonfigurieren, ohne an der Verdrahtung was zu ändern (sogar zur Laufzeit - Wenn der /CS eines AVR-Master Eingang ist und von High auf Low wechselt, wird der AVR automatisch zum Slave)

Beim USI hingegen ist die Datenrichtung der beiden Pins immer gleich - DO und DI eben. Hier kannst Du ein Netz mit mehr als drei AVR also nicht mehr ohne Umbau unkonfigurieren.
(Genau genommen ist der Teil mit dem Schieberegister immer Slave, aber der Controller kann eben die Flanken auf sein eigenes Bein legen, und damit das ganze SCK-Netz clocken).

Der RFM ist von Natur aus immer Slave, hat also eine festgelegte Konfiguration. (Funktionsblock auf der ersten Seite des Datenblattes)
Damit ergibt sich:
  • USCK des AVR auf SCK des RFM (Clock, wird vom AVR als Master generiert)
  • DI des AVR auf SDO des RFM (Daten vom RFM zum AVR - der AVR liest)
  • DO des AVR auf SDI des RFM (Daten vom AVR zum RFM - der AVR schreibt)
  • irgendein AVR-Pin auf nSEL des RFM (Chip Select)
  • Stromversorgung (zumindest Gnd), klar
Die anderen hab ich mir noch nicht angesehen...
Ich bin selbst kurz davor, mir solche Module mal zu bestellen - aber vor Weihnachten/dieses Jahr wird das wohl nichts mehr.
 
In der routine read_byte wird meines erachtens nichts nennenswertes verändert man könnte jetzt natürlich noch die register pushen. Aber in dem aktuellen zusammenhang dürfte hier kein Problem auftreten. Ja es ist das richtige hex file :D aber danke für den TIpp. ist mir auch schon passiert....-.-
@LotadaC
Ok dann müsste meine aktuelle pinbelegung eigentlich stimmen. Noch ist mir unklar in wie weit ich nIRQ bzw den nINT/VDI pin nutzen kann.
Ich habe mir vorher andere module bestellt gehabt. ganz einfache für 2 euro der satz aus china. Da der eigenbau eines Protokols leider gescheitert war und via USART eine Fehllerrate unter der würde einer jeden FUnkverbindung zu stande kahm, landeten sie in der "Is da aber scheise"-Kiste :D. Nun dann rtecherichirte ich ...Die RFM12 sollten so einfach anzusteuern sein. Ich laß von SPI (erster gedanke " Ein TRaum")...nun ja und nun siehts nicht so prikelnd aus.
Ansich sollen die Module ohne weiteres 100m machen. Wäre natürlich super für mein Projekt. Allgemein zählt hier natürlich wieder der gedanke das es nicht darum geht eine funktsionsfähige wetterstation hier zu haben welche man auch für 10 euro in jedem baumarkt bekommt, sondern der selbstbaufaktor mit unendlichen erweiterungsmöglichkeiten.
Nun bin ich mir aber durch endlose probiererei darüber im klaren das entweder sich das statusregister nicht auslesen lässt, oder die kommunikation mit dem modul nicht funktioniert.
hier ein code welcher nur das statusregister nach der initialisierung via usart ausgeben soll. Leider auch recht erfolglos. Das Register liefert immer 0.


CodeBox Assembler
;tn2313 USART communicatrionstest RFM12

.include "tn2313def.inc"
.org 0x000
   rjmp init

.org 0x0020
.equ XTAL=1000000
.equ t5ms = ( XTAL * 5 / 606 ) / 1000

.def temp1=r16
.def temp2=r17
.def temp3=r18
.def data=r19
.def lsb=r21
.def msb=r22
.def datah=r24
.def datal=r23
.def datain=r25
.org 0x0000
.equ spiddr=ddrb
.equ spiport=portb
.equ nsel=0
.def counter=r20
.equ debugport=portd       ;Nur zu testzwecken
.equ debugddr=ddrd
.org 0x020
init:
ldi temp1, low(ramend)
out spl, temp1
rcall serinit
;rcall rfninit
rcall hallo
sbi ddrb, 7
;sbi ddrb, 6
sbi ddrb, 5

main:
rcall delay1s
rcall wert

wait:
sbic pinb, 6
rjmp wait
rcall readstatusrfm12
mov temp1, datah
rcall seroutdez
mov temp1, datal
rcall seroutdez
rjmp main


rjmp main


SPITransfer:
out    USIDR,temp1
ldi    r16,(1<<USIOIF)
out    USISR,r16
ldi    r17,(1<<USIWM0)|(1<<USICS1)|(1<<USICLK)|(1<<USITC)

SPITransfer_loop:
out    USICR,r17
in     r16, USISR
sbrs   r16, USIOIF
rjmp   SPITransfer_loop
in     temp1,USIDR
ret
;******************************************************************
;RS232 Routine
;******************************************************************
initrs232:
.equ takt = 1000000 ; 16/8 MHz Systemtakt
.equ baud =2400   ; Baudrate
.equ ubrr_val = ((takt+baud*8)/(baud*16)-1)   ; clever Runden
.equ baud_real = (takt/(16*(ubrr_val+1)))   ; tatsächliche Baudrate
.equ baud_error = ((baud_real*1000)/baud-1000)   ; Fahler in Promille
;
;
.if ((baud_error> 10) || (baud_error <-10))       ; max +/- 10 Promill Fehler
   .error "Systematischer Fehler der Baudrate größer als 1 Prozent und damit zu hoch!"
.else
   .message "Systematischer Fehler der Baudrate hält sich in Grenzen - OK!"
.endif
rcall serinit
rcall hallo
ret

seroutdez:
           push  temp1            ; die Funktion verändert temp1 und temp2,
           push  temp2            ; also sichern wir den Inhalt, um ihn am Ende
                                  ; wieder herstellen zu können

           mov   temp2, temp1     ; das Register temp1 frei machen
                                  ; abzählen wieviele Hunderter
                                  ; in der Zahl enthalten sind
;** Hunderter **
           ldi   temp1, '0'-1     ; temp1 mit ASCII '0'-1 vorladen
number_1:
           inc   temp1            ; ASCII erhöhen (somit ist nach dem ersten
                                  ; Durchlauf eine '0' in temp1)
           subi  temp2, 100       ; 100 abziehen
           brcc  number_1     ; ist dadurch kein Unterlauf entstanden?
                                  ; nein, dann zurück zu lcd_number_1
           subi  temp2, -100      ; 100 wieder dazuzählen, da die
                                  ; vorherhgehende Schleife 100 zuviel
                                  ; abgezogen hat
           cpi temp1, 0           ;Führende null weg
           breq number_2
           rcall serout        ; die Hunderterstelle ausgeben

;** Zehner  **
           ldi   temp1, '0'-1     ; temp1 mit ASCII '0'-1 vorladen
number_2:
           inc   temp1            ; ASCII erhöhen (somit ist nach dem ersten
                                  ; Durchlauf eine '0' in temp1)
           subi  temp2, 10        ; 10 abziehen
           brcc  number_2     ; ist dadurch kein Unterlauf enstanden?
                                  ; nein, dann zurück zu lcd_number_2
           subi  temp2, -10       ; 10 wieder dazuzählen, da die
                                  ; vorherhgehende Schleife 10 zuviel
                                  ; abgezogen hat
           cpi temp1, 0           ;Führende null weg
           breq number_3
           rcall serout        ; die Zehnerstelle ausgeben
;** Einer **     
number_3:
           ldi   temp1, '0'       ; die Zahl in temp2 ist jetzt im Bereich
           add   temp1, temp2     ; 0 bis 9. Einfach nur den ASCII Code für
           rcall serout         ; '0' dazu addieren und wir erhalten dierekt
                                  ; den ASCII Code für die Ziffer


           pop   temp2            ; den gesicherten Inhalt von temp2 und temp1
           pop   temp1            ; wieder herstellen
           ret                    ; und zurück


wert:
ldi temp1, 'W'
rcall serout
ldi temp1, 'e'
rcall serout
ldi temp1, 'r'
rcall serout
ldi temp1, 't'
rcall serout
ldi temp1, ';'
rcall serout
ldi temp1, ' '
rcall serout
ret


hallo:
ldi temp1, 'O'
rcall serout
ldi temp1, 'K'
rcall serout
ldi temp1, ' '
rcall serout
ldi temp1, 'R'
rcall serout
ldi temp1, 'S'
rcall serout
ldi temp1, ' '
rcall serout
ldi temp1, '2'
rcall serout
ldi temp1, '3'
rcall serout
ldi temp1, '2'
rcall serout
ret

serout:
   sbis ucsra,udre                   ; udre-bit ist gesetzt, wenn der Sendepuffer leer ist
                                   ; UART Data Register Empty
   rjmp serout
   out    udr, temp1                   ; Zeichen senden
   ret                               ; zurück aus der Subroutine

   ; Zeichen über RS232 einlesen
   ; temp1: gibt das Zeichen zurück
serin:
   sbis ucsra, rxc 
   rjmp serin                       ; wir warten bis ein Byte angekommen ist

   in temp1, udr                   ; Zeichen einlesen
   ;rcall serout                   ; und zurücksenden 
   ret

   ; Zeichen über RS232 einlesen und als Echo zurücksenden
   ; temp1: gibt das Zeichen zurück


serinit:
   ; Baudrate für RS232 einstellen
   ldi temp1, high(ubrr_val)       ; zuerst Baudrate Highbyte (davon Lownibble)
   out ubrrh, temp1
   ldi temp1, low(ubrr_val)           ; Lowbyte schreiben und prescaler damit triggern
   out ubrrl, temp1

   ; frameformat setzen
   ldi temp1, (1<<ucsz1) | (1<<ucsz0)   ; ucsz2:0 = 0 1 1 -> 8 Bit Daten, kein Parity, 1 Stopbit
   out ucsrc, temp1

   ; Transmitter einschalten, PortD Bit1 wird überschrieben
   sbi ucsrb, txen                   ; TXE-Bit (3) setzen
 
   ; Receiver einschalten, PortD Bit0 wird überschrieben
   sbi ucsrb, rxen                   ; RXE-Bit (4) setzen
   ;sbi ucsrb, rxcie               ; RXCIE-bit (7) setzen, damit ein irq ausgelöst werden kann, wenn ein Zeichen da ist
   ret


;***********************************************************
;INITS
;***********************************************************
;;Nsel auf low einen momment warten dann bit an SDI vom modul(mit dem höchsten bit starten)
; high low an sclk(serial clock) nächstes bit.....dann Nsel wieder auf high
rfninit:
;folgende init werte zum übertragen
;Empfänger:
;0x80E7       868mhz, RX fifo TX buffer 12pf
;0x8280       enable receiver
;0xA640       868mhz center freq
;0xC647       19,2kbaud
;0x95A2       Max empfangsstärke 200khz pin als VDI pin
;0xC2AC       digitaler fehlerbehebung
;0xCA81     
;0xC483
;0x9850       TX controll
;0xE000
;0xC800
;0xC040
;KOmmando  0xB000 read 8 bits from fifoRX
;kommando 0xB8xx   send 8 bits of data
ldi msb, 0x80
ldi lsb, 0xE7
rcall send_command
ldi msb, 0x82
ldi lsb, 0x80
rcall send_command
ldi msb, 0xA6
ldi lsb, 0x40
rcall send_command
ldi msb, 0xC6
ldi lsb, 0x47
rcall send_command
ldi msb, 0x95
ldi lsb, 0x82
rcall send_command
ldi msb, 0xc2
ldi lsb, 0xAC
rcall send_command
ldi msb, 0xCA
ldi lsb, 0x81
rcall send_command
ldi msb, 0xc4
ldi lsb, 0x83
rcall send_command
ldi msb, 0x98
ldi lsb, 0x50
rcall send_command
ldi msb, 0xE0
ldi lsb, 0x00
rcall send_command
ldi msb, 0xC8
ldi lsb, 0x00
rcall send_command
ldi msb, 0xC0
ldi lsb, 0x40
rcall send_command
ret
readstatusrfm12:
clr lsb
clr msb
rcall send_command


int0_init:
        ldi temp1,(1<<ISC01)|(0<<ISC00)
        out mcucr,temp1
        ldi temp1, (1<<INT0)
        out GIMSK,temp1
        ret


;**********************************************
;UNTERPROGRAMME
;**********************************************
send_byte:
push lsb
;sender einschalten
ldi msb, 0x82
ldi lsb, 0x20
rcall send_command
;DATENBIT MUSS IN LSB Stehen
ldi msb, 0xB8
push lsb
ldi lsb, 0xAA               ;präambel
rcall send_command
rcall send_command
;;nun das synchronbyte
ldi lsb, 0x2D
rcall send_command
ldi lsb, 0xD4
rcall send_command
;;nun die nutzdaten
pop lsb
rcall send_command
;Zeit geben
rcall delay100ms
;sender wider ausschalten und empfänger an
ldi msb, 0x82
ldi lsb, 0x80

rcall send_command
pop lsb                       ;16.12.2016
ret

read_byte:
;;DATENBYTE befindet sich in LSB
ldi msb, 0xB0
ldi lsb, 0x00
rcall send_command
in lsb, USIDR
ret

send_command:
mov temp1, msb
cbi spiport,nsel
nop nop nop nop           ;Zu testzwecken nach Dirk ein kleines delay
nop nop nop nop
rcall SPITransfer
in datah, USIDR
mov temp1, lsb
rcall SPITransfer
in datal, USIDR
sbi spiport,nsel

ret
;****************************************************************
;INTERRUPTHANDLERS
;****************************************************************
Ext0_int_handle:
;;Daten stehen bereit
;;Auslesen
rcall read_byte
reti




.include "stddelay.inc"


Ich denke sollte ich hier mit eurer hilfe das Modul zum laufen bringen werde ich auf jeden fall eine funktionstüchtige routine sauberst dokumentiert hier im forum veröffentrlichen. Dieses leiden soll nicht noch einmal jemanden passieren :)
Ich bin auch schon am überlegen das ganze mal an einem mega8 zu testen welcher ja ein "echtes" SPI mit SS besitzt. Wobei das natürlich auch nicht das problem aus der welt schafft den mehr platz als für einen tiny44 hab ich im gehäuße für den außenfühler leider nicht. Aber die Funktion der Module wäre merst einmal gesichert.
noch einen schönen Sonntag an alle
Daniel
 
Zuletzt bearbeitet:
Hi
Nun, mag ja sein, das die Register nur in Readbyte gesetzt werden und sonst nirgendwo, aber ich glaube gesehenzu haben, das die Routine Readbyte auch im normalen Programm aufgerufen wird. Dann sind deine Registerwerte natürlich nicht sicher. Auch mit den POP's scheinst du irgendwie nicht so richtig zu liegen. Ein wert, den du auf den Stack gepusht hast, kanst du nur sooft herunter holen, wie er gepusht ist.


CodeBox Assembler
send_byte:
push lsb
;sender einschalten
ldi msb, 0x82
ldi lsb, 0x20
rcall send_command
;DATENBIT MUSS IN LSB Stehen
ldi msb, 0xB8
push lsb                                     ; hier einmal gepusht !
ldi lsb, 0xAA              ;präambel
rcall send_command
rcall send_command
;;nun das synchronbyte
ldi lsb, 0x2D
rcall send_command
ldi lsb, 0xD4
rcall send_command
;;nun die nutzdaten
pop lsb                                       ; und hier zurückgeholt. Der nächste Wert auf dem Stack ???
rcall send_command
;Zeit geben
rcall delay100ms
;sender wider ausschalten und empfänger an
ldi msb, 0x82
ldi lsb, 0x80

rcall send_command
pop lsb                      ;16.12.2016         ; also, keine Ahnung was das für ein Wert ist
ret

Aber vielleicht ist das tatsächlich doch irgendwie richtig, nur nachvollziehen kann ich das nicht.
Gruß oldmax
 
die erste zeile der routine ist ebenfalls ein push. Mit dem SPI des megas scheint es auch nicht zu klappen ddar er den ss pin nach jedem byte wieder auf high setzt.
ich pushe lsb einmal um es zu sichern und den sender zu aktivieren dann push ich es erneut nach dem ich es mit dem befehlsbyte für das senden gefüttert habe und pope es zu entsprechenden zeitpunkt wieder.
Aber wenn ich genauer darüber nachdencke sollte ich den teil eventuell noch einmal genauer durchdenken...iwie kommt mir gerade auch etwas stuzig vor.
 
also ich sehe je ein Push in den Zeilen 2 und 9, und je ein Pop in den Zeilen 19 und 28.
Ob das soweit korrekt/gewollt ist, kann ich noch nicht sagen.

Da Du grad dabist, Oldmax, wann wird eigentlich eine .equ-Direktive (und wann #equ) wirksam? Genau da, wo es steht? Muß ich insbesondere Variablen, die ich in einer Bibliothek weiterverrechnen will vor dem Include definieren?
 
Also meines wissens nach muss alles verwendete vor der eigentlichen verwendung definiert oder ge"equ"t werden. Ich mache dies zumindest meist vorsichtshalber und hab von AVR studio noch nie ein warning oder einen error deswegene erhalten. Anders sieht es aus wenn ich temp1 in zeile 10 verwende und in zeile 30 definiere. Dann kommt ein error register not found oder so ähnlich
 
Ok laut datenblatt wird SS nicht von der Hardware getoggelt. Nun hab ich das händisch eingefügt. nur funktioniert mein USART auf dem mega nicht...seltsam. Auf dem tiny hab ich zumoindest nun das ergebniss das ich mehr oder weniger zufällige register werte bekomme. das lowbyte bleibt konstatn das highbyte schlabbert in der gegen umher.. Das ist auch nocht wirklich eine besserung...nu ja..könnte der tag nicht 48 Stunden haben...
 
Hi
@Lothar
Soweit mir bekannt ist, ist auch eine Compilerdirektive genau an der Stelle wirksam, wo sie steht. Erst nach der Anweisung ist die erzeugte Referenz bekannt und im weiteren Programm verwendbar. Die Anweisung #EQU ist mir in Assembler, zumindest dem Atmel, nicht bekannt. Wenn du es dort einsetzt, erhälst du auch eine Fehlermeldung. Möglicherweise funktioniert das bei Hochsprachen so. Da ist es auch möglich, das Compiler das anders händeln. Bei Pascal ist mir bekannt, das Function und Procedure eine Forward-Anweisung hatten, wenn sie intern untereinander Zugriff brauchten. Aber das ist lang her und bei Delphi oder VB ist mir das noch nie aufgefallen. Wie auch, da werkeln Objekte, die von schlauen Köpfen mit ausgeklügeltem Code gefüllt sind.:cool:
@ dannyboy1994
Sorry, mein Fehler. Das zweite Push hab ich mittlerweile auch erkannt. Allerdings lass mich noch eine Bemerkung loswerden. PUSH und POP benötigen mehr Taktzyklen wie bspw. ein MOV oder ein erneutes Laden. Wenn es darum geht, Register in einer ISR zu sichern ist PUSH und POP die richtige Wahl, da oftmals nicht sicher ist, wie tief Interrupts geschachtelt sein können. Manche Prozessoren lassen in einer ISR weitere Interrupts zu. Ist das nicht der Fall, reicht ein reserviertes Register und eine MOV- Anweisung, um Bspw. das Statusregister zu sichern.


CodeBox Assembler
.DEF   SReg_Temp  = r3   ; beliebiges Register, vorzugsweise unterhalb r16
...
ISR_Irgendwas:
    MOV  SReg_Temp, SReg
...
    MOV  SReg, SReg_Temp
RETI
.
Das ersetzt die übliche Sicherung


CodeBox Assembler
ISR_Irgendwas:
    Push   r16
    IN        r16, SReg
    Push   r16
....
    POP   r16
    OUT   SReg, r16
    POP   r16
RETI

Gruß oldmax
 
Die Anweisung #EQU ist mir in Assembler, zumindest dem Atmel, nicht bekannt.
Richtig, ich meinte #define. Und das scheint tatsächlich vor der Verwendung stehen zu müssen.
Bei .equ ist's egal.
Interessant wirds bei .set, welches ja im Code verändert werden kann. Setzt Du die Variable hinter der Verwendung, gilt diese. Setzt Du die Variable vor und(!) hinter der Verwendung, gilt die davor.
Der Compiler scheint also die Codezeilen nacheinander zu parsen, und dabei auch die eventuellen Compilervariablen/konstanten anzulegen. Wird eine bisher unbekannte verwendet, wird der restliche Code durchsucht.
Manche Prozessoren lassen in einer ISR weitere Interrupts zu
Das gilt auch für alle(*) AVR. Du kannst in jeder ISR das I in SREG setzen.
(*) Bei einigen alten AVR ohne SRAM gabs nur einen drei-level-stack für Rücksprungadressen.

Nachtrag: MOV arbeitet nur mit Rechenregistern (also nicht mit SREG). Du wolltest SREG mit IN/OUT und dem tempregister verwenden...
 
Zuletzt bearbeitet:
Ich habe so eben eine Anfrage an den Pollin-Service geschrieben ob die technische Abteilung irgendwelche nützlichen Tipps hat. Die kOMmunikation mit dem Modul will einfach nicht funktionieren.
 
Das ist genau das ganze was mich ebenfalls aus der bahn wirft das ganze frequenz und verstärkung und tüdelü.. ICh versuchs etz gerade mal mit SOFTSPI speziell mit SS für den RFM wie es im DAtenblatt steht.
Kannst du dir evtl diesen schnippsel mal kurz ansehen ob das ganze funktionstüchtig sien könnte.



CodeBox Assembler
;SOFTSPI setzt SS low und überträgt 2 BYTE (DATAH und DATAL) die Antwort steht in (REcH und RECL)


softspiout:           //sendet byte aus DATA und Empfängt Daten in REC

;Prinzip des SPI:
;Datenbit wird an Pin angelegt und SCL wird ein impuls gegeben
cbi SPIPORT, SS
nop
nop
nop                   ;Lieber Pausen statt das se wieder nicht funktioniert
ldi counter, 8
highbyte:
rol   DATAH               ;Schieben das höchste bit steht im carry
brcs highm
brcc lowm
rcall sckimpuls
sbis spipin, MISO
rcall nullreinh
sbic spipin, MISO
rcall einsreinh
dec counter
brne highbyte
;So das ganze acht mal das highbyte is raus
;Und rein in recH

;Das ganze für das lowbyte
ldi counter, 8
lowbyte:
rol   DATAL               ;Schieben das höchste bit steht im carry
brcs highm
brcc lowm
rcall sckimpuls
sbis spipin, MISO
rcall nullreinl
sbic spipin, MISO
rcall einsreinl
dec counter
brne lowbyte
nop
nop
nop
sbi SPIPORT, SS

ret


highm:
sbi spiport, mosi
ret

lowm:
cbi spiport, mosi
ret

nullreinh:

cbr recH, 0
rol recH
ret

einsreinh:

sbr recH, 0
rol recH
ret

nullreinl:

cbr recl, 0
rol recl
ret

einsreinl:

sbr recl, 0
rol recl
ret



sckimpuls:
sbi spiport, sck
nop nop nop
cbi spiport, sck
ret





.include "stddelay.inc"
 
Kannst du dir evtl diesen schnippsel mal kurz ansehen ob das ganze funktionstüchtig sien könnte.
Ich bin zwar nicht LotadaC ;) aber ich antworte trotzdem mal. Für mich sieht es richtig aus. SCK muss zuvor mit low initialisiert sein, SlaveSelect mit high.

Dirk :ciao:
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)