- 12V Akku mit 280 Ah bauen         
Ergebnis 1 bis 5 von 5

Thema: RFM12b an tiny2313 USI

  1. #1

    RFM12b an tiny2313 USI

    Anzeige

    LiFePo4 Akku selber bauen - Video
    Hallo community. Ich bin derzeit dabei mir eine kleine Wetterstation zu bauen, bei welcher mir ein tiny44 die außentemperatur und Luftfeuchtigkeit über ein RFM12 Modul senden soll. Ein Tiny2313 soll das Ganze dann auf einem LCD und über den USART ausgeben. Nun stehe ich gerade am Anfang des ganzen und versuche mir funktionstüchtige routinen zu schreiben. Einmal eine für den tiny(reiner empfänger) und einen für den tiny44(reiner sender)

    Das Ganze soll der USI realisiert werden.
    Hier einmal mein aktueller stand beim tiny2313 Empfänger. Das drum herum ist erst einmal nebensächlich sondern eher die vorgehensweise beim empfang.
    Könnte ein ambitioniertes Midglied des Forums einmal drüber schaun und mir evtl unter die arme greifen. Auch habe ich das gefühl das ich die ansteuerung des Moduls noch nicht so ganz verstanden habe.

    Code:
    ;;;Kleines Testprogramm
    ;;Tiny2313 als empfänger
    ;;Empfängt ein Byte und gibt dieses via usart aus
    ;;USI als SPI Master
    .list
    .include "tn2313def.inc"
    
    .nolist
    .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 datain=r23
    .org 0x0000
    .equ spiddr=ddrb
    .equ spiport=portb
    .equ nsel=0
    rjmp start
    
    
    .org 0x020
    loop:
    mov data, lsb
    rcall read_byte            ;befindet sich anschließend in LSB
    cp data, lsb
    breq loop
    mov temp1, lsb
    rcall seroutdez
    rcall delay1s
    rjmp loop
    
    
    
    start:
    ldi temp1, low(ramend)
    out spl, temp1                            ;Stackpointer init
    sbi spiddr, nsel
    rcall rfninit                            ;RFM12 inittialisiert und bereit("hoffentlich")
    rcall initrs232
    rcall loop
    
    
    ;;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
    ;0x9582        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
    
    usi_init:
    ;;USIWM1 und 0 für SPI 
    
    ;; 0        1
    ret
    send_byte:
    ;DATENBIT MUSS IN LSB Stehen
    ldi msb, 0xB8
    rcall send_command
    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
    rcall SPITransfer
    mov temp1, lsb
    rcall SPITransfer
    sbi spiport,nsel
    
    ret
    
    
    
    
    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
    
    ret
    
    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
    
    
    
    
    
    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
    
    
    serinit:
        ; Baudrate für RS232 einstellen
        ldi temp1, high(ubrr_val)
        out ubrrh, temp1
        ldi temp1, low(ubrr_val)
        out ubrrl, temp1
    
        ldi temp1, (1<<ucsz1) | (1<<ucsz0)    ; ucsz2:0 = 0 1 1 -> 8 Bit Daten, kein Parity, 1 Stopbit
        out ucsrc, temp1
    
        sbi ucsrb, txen                    ; TXE-Bit (3) setzen
        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
    Nun ja das ganze sieht aus wie kraut und rüben. Ich bin gerade in der "hauptsache es funktioniert mal irgendwas "-Phase

    mfg Daniel

    PS: Was mir gerade noch einfällt

    wenn ich 8 bits per SPI an das RFM übertrage mit vorhergehendem msb 0x82
    werden diese 8 bits dann sofort vom modul übertragen?
    kann ich diese 8 bits beim empfänger mit dem senden von 0xB000 direkt auslesen und sie aus dem USIDR entnehmen?
    kann ich das Modul einmal konfigurieren und dann durchgehend warten lassen bis etwas kommt, oder fängt es dann nur müll ein?
    wie ist das mit dem VDI pin bzw nINT. Muss ich diese nutzen? oder kann ich auch softwareseitig sicher stellen wann neue daten vorhanden sein müssten.

    Wenn ich den FIFO lese während das MOdul etwas empfängt, bekomme ich dann bitsalat oder bleiben die daten im FIFO so lange bestehen bis alle 8 bits empfangen sind und werden dann in den FIFO verschoben. Ich möchte möglichst mit einer minimalen beschaltung auskommen. Das nutzen eines externen intterupts wäre evtl noch eine nette sache. z.B intterupt wenn daten empfangen wurden...Dann auslesen und den MC in den sleep mode


    Fragen über fragen...ich hoffe jemand kann für erleuchtung sorgen

    PPS: Die Senderoutine wurde wie folgt geändert
    Code:
    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
    
    ret
    Grund dafür isT:
    -Energiesparen durch deaktivieren des senders
    - Ich habe gelsen das man erst eine Präambel senden soll dann das Synchronbyte und der receiver auf der gegenseite erst das Byte nach dem Synchronbyte in seinen FIFO übernimmt
    Geändert von dannyboy1994 (13.12.2016 um 18:22 Uhr)

  2. #2

    Hilfe

    nun nach weiteren gefühlten 10 stunden vergebener arbeit habe ich nun die Programme für Sender und empfänger noch einmal geändert

    sender:
    Code:
    ;;;Kleines Testprogramm
    ;;Tiny2313 als empfänger
    ;;Empfängt ein Byte und gibt dieses via usart aus
    ;;USI als SPI Master
    ;;interruptausgang von RFM an INT0
    ;;SPI standartverdrahtung
    ;;
    .list
    .include "tn2313def.inc"
    
    .nolist
    .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 datain=r23
    .org 0x0000
    .equ spiddr=ddrb
    .equ spiport=portb
    .equ nsel=0
    .def counter=r20
    rjmp start
    .org 0x0001
        rjmp Ext0_int_handle
    .org 0x0006
        rjmp Timer0OFL
    
    .org 0x020
    loop:
    mov data, lsb
    sleep
    cp data, lsb
    breq loop
    mov temp1, lsb
    rcall seroutdez
    rjmp loop
    
    
    
    start:
    ldi temp1, low(ramend)
    out spl, temp1                            ;Stackpointer init
    sbi spiddr, nsel
    rcall rfninit                            ;RFM12 inittialisiert und bereit("hoffentlich")
    rcall initrs232
    rcall int0_init
    rcall inittimer0
    sei
    rcall loop
    
    
    
    
    
    
    ;**********************************************
    ;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
    
    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
    rcall SPITransfer
    mov temp1, lsb
    rcall SPITransfer
    sbi spiport,nsel
    
    ret
    
    
    
    
    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
    
    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
    
    
    
    
    
    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
    ;0x9582        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
    
    
    usi_init:
    ;;USIWM1 und 0 für SPI 
    
    ;; 0        1
    ret
    
    int0_init:
            ldi temp1,(1<<ISC01)|(0<<ISC00)
            out mcucr,temp1
            ldi temp1, (1<<INT0)
            out GIMSK,temp1
            ret
    
    inittimer0:
            sbr temp1, TOIE0
            out TIMSK, temp1
            ldi temp1,0b00000111    ;max prescaler...bei 1mhz 255*1024=262144 takte
                                    ; was bei 1 mhz 1/4sek ist
            out TCCR0B, temp1
            ret
    ;****************************************************************
    ;INTERRUPTHANDLERS
    ;****************************************************************
    Ext0_int_handle:
    ;;Daten stehen bereit
    ;;Auslesen
    rcall read_byte
    reti
    
    Timer0OFL:
    inc counter
    cpi counter, 229
    brne schlafen
    cpi counter, 229
    breq wach
    reti
    
    schlafen:
    sleep
    ret
    wach:
    clr counter
    ret
    
    .include "stddelay.inc"
    Empfänger:
    Code:
    .include "tn44def.inc"
    .def temp1=r16
    .def temp2=r17
    .def temp3=r18
    .def datain=r19
    .equ spiport=porta
    .equ spiddr=ddra
    .def lsb= r20
    .def msb=r21
    .equ XTAL=1000000
    .equ t5ms = ( XTAL * 5 / 606 ) / 1000
    .equ nsel=3
    
    loop:
    inc r22
    mov lsb, r22
    rcall send_byte
    rcall delay1s
    rjmp loop
    
    start:
    ldi temp1, high(ramend)
    out sph, temp1
    ldi temp1, low(ramend)
    out spl, temp1                            ;Stackpointer init
    sbi spiddr, nsel
    rcall rfninit                            ;RFM12 inittialisiert und bereit("hoffentlich")
    rcall loop
    ;;;;;;;;;;;;;;;;;;;;;UNTERPROGRAMME
    
    
    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
    ;0x9582        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
    
    
    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
    
    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
    rcall SPITransfer
    mov temp1, lsb
    rcall SPITransfer
    sbi spiport,nsel
    
    ret
    
    
    
    
    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
    
    .include "stddelay.inc"
    Leider funktioniert garnichts. keine einzige usart ausgabe...nicht einmal das hallo...
    Programmiert den Hier keiner mehr in Assembler

  3. #3
    Erfahrener Benutzer Fleißiges Mitglied Avatar von avr_racer
    Registriert seit
    01.04.2014
    Ort
    MecklenburgVorpommern
    Beiträge
    174
    Hallo,

    um es ein wenig übersichtlicher zu gestalten lager die Programmteile aus die im Moment nicht genutzt werden und binde sie später per Include ein.

    So wie cih dich verstehe versuchst du die RS232 bzw die UART zum laufen zu bringen. Im zweiten Post erstes Programm wird nach der Startsequenz ein RCALL LOOP aufegrufen welches aber in dem LOOP mit einem RJMP beendet wird. Erstmal weiter nicht tragisch nur solltest du zu Testzwecken es eher:

    Start:
    ....
    RJMP LOOP

    oder du schreibst es einfach ganz normal drunter weg

    Start:
    ...
    ...
    ...
    RJMP LOOP ;oder lääst das nach der Initialisierung in die loop laufen also ohne RJMP

    die .org 0x020 kannst du weg lassen wenn du halt fortlaufend arbeitest brauch man nur wenn du mit nem BOOTLOADER arbeiten willst ..... sonst weg damit.. erstmal

    loop:
    mov data, lsb
    sleep
    cp data, lsb
    breq loop
    mov temp1, lsb
    rcall seroutdez
    rjmp loop



    Code:
    ;;;Kleines Testprogramm
    ;;Tiny2313 als empfänger
    ;;Empfängt ein Byte und gibt dieses via usart aus
    ;;USI als SPI Master
    ;;interruptausgang von RFM an INT0
    ;;SPI standartverdrahtung
    ;;
    .list
    .include "tn2313def.inc"
    
    .nolist
    .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 datain=r23
    .def counter=r20
    
    .equ spiddr=ddrb
    .equ spiport=portb
    .equ nsel=0
    
    .org 0x0000
    rjmp start
    .org 0x0001
        rjmp Ext0_int_handle
        reti
        reti
        reti
        reti
    .org 0x0006
        rjmp Timer0OFL
        reti
        reti
        reti
        reti
    
    start:
    ldi temp1, low(ramend)
    out spl, temp1                            ;Stackpointer init
    
    rcall initrs232
    rcall hallo
    rjmp loop                          ;kannst auch weg lassen
    
    loop:
    mov data, lsb
    sleep
    cp data, lsb
    breq loop
    mov temp1, lsb
    rcall seroutdez
    rjmp loop
    
    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
    
    ;******************************************************************
    ;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
    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
    
    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
    
    
    
    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
    
    
    int0_init:
            ldi temp1,(1<<ISC01)|(0<<ISC00)
            out mcucr,temp1
            ldi temp1, (1<<INT0)
            out GIMSK,temp1
            ret
    
    inittimer0:
            sbr temp1, TOIE0
            out TIMSK, temp1
            ldi temp1,0b00000111    ;max prescaler...bei 1mhz 255*1024=262144 takte
                                    ; was bei 1 mhz 1/4sek ist
            out TCCR0B, temp1
            ret
    ;****************************************************************
    ;INTERRUPTHANDLERS
    ;****************************************************************
    Ext0_int_handle:
    ;;Daten stehen bereit
    ;;Auslesen
    rcall read_byte
    reti
    
    Timer0OFL:
    inc counter
    cpi counter, 229
    brne schlafen
    cpi counter, 229
    breq wach
    reti
    
    schlafen:
    sleep
    ret
    wach:
    clr counter
    ret
    
    .include "stddelay.inc"
    mal versucht den Code so zu ändern das der Ablauf einigermaßen erkennbar ist, wann von wo nach wo und zurück gesprungen wird.
    Zusätzlich die Hardware geprüft ?? Also damit mein ich hast du mal tiny2313 und PC verbunden zum testen ? TX und RX geprüft ? Nicht das du die beiden 1:1 gesteckt hast richtig ist TX-RX / RX-TX.

    geb dir mal den Hinweis hier rauf https://www.roboternetz.de/community...313-Bibliothek

  4. #4
    wir sind nun auf makerconnect.com schon eine Weile mit dem Kampf beschäftigt. Der thread dort heißt RFM12b an tiny44 via USI. Es wurde versucht per soft SPI zu lösen per mega8-hardware SPI. Leider hat nun bis jetzt nichts den durchbruch gebracht. Ich weis auch nicht ob meine init stimmt. Ich poste hier gerne noch mal den aktuellen stand der routine. Deinen Link habe ich mir soeben angesehen. Sehr ausführlich Dokumentierte Arbeit. Wenn es dir nichts ausmacht würde ich sie sehr gerne verwenden, dar so viele nütziche und zeitsparende inits darin integriert sind.
    Ein Frohes Fest und einen guten rutsch ins neue jahr.
    Angehängte Dateien Angehängte Dateien

  5. #5
    Erfahrener Benutzer Fleißiges Mitglied Avatar von avr_racer
    Registriert seit
    01.04.2014
    Ort
    MecklenburgVorpommern
    Beiträge
    174
    Dafür ist solch Bibliothek da

    Aber mach mal bitte ein Schaltplan wo der RFM 12B (AVRxyz) genau dranhängt mit wem dieser AVR kommuniziert(Schnittstelle) und der AVR welcher per UART und LCD was ausgebn soll

    Danke wünsche ich ebensfalls Frohe Weihnachten und ein guten Rutsch.
    Geändert von avr_racer (24.12.2016 um 12:02 Uhr)

Ähnliche Themen

  1. RN-MikroFunk - Fertiges Projekt eines Miniaturboards inkl Funkmodul RFM12b
    Von Frank im Forum Eigene fertige Schaltungen und Bauanleitungen
    Antworten: 16
    Letzter Beitrag: 22.06.2016, 17:28
  2. Programmierung von RFM12b mit RN-MikroFunk
    Von Roboternetz-News im Forum Neuigkeiten / Technik-News / Nachrichten / Aktuelles
    Antworten: 0
    Letzter Beitrag: 18.12.2015, 18:50
  3. Arduino mit Rfm12b empfängt nicht
    Von Der Einsteiger im Forum Arduino -Plattform
    Antworten: 0
    Letzter Beitrag: 28.07.2015, 15:00
  4. Bascom Funksteckdosen mit RN AVR-Universal (und RFM12b) ansteuern
    Von Frank im Forum Bascom / C / ASM / Sketch / Codesammlung / Programmschnipsel
    Antworten: 0
    Letzter Beitrag: 18.01.2013, 17:33
  5. Rfm12B und Xmega128A3
    Von ChRiZ im Forum C - Programmierung (GCC u.a.)
    Antworten: 0
    Letzter Beitrag: 22.03.2011, 09:09

Berechtigungen

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

Solar Speicher und Akkus Tests