-         
+ Antworten
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 13

Thema: Bits senden und erkennen

  1. #1
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    31.01.2004
    Beiträge
    585

    Bits senden und erkennen

    Hallo!
    Ich brauche etwas Hilfestellung zu einem ATmega8.
    Ich möchte folgendes tun:

    Mit einem AVR möchte ich eine Bitfolge an einem Pin programmieren.
    Also es sollen 24 einzelne Bits an einen Pin gesendet werden.
    Diese schauen so aus:

    00000001 11111110 00000011

    Das erste Byte ist ein "Startsignal", das zweite Byte das eigentliche Kommando und das Dritte das "Endsignal".
    Ich möchte mit diesem Prinzip eine IR Sendediode ansteuern und später dann einen Funksender.

    Ok, ich denke das ist nicht so schwer:

    Portd.0 = 0
    waitms 10
    Portd.0 = 1

    So kann man doch schon mal 0 und 1 mit 10 Millisekunden an den Port senden , nicht?

    Nur: Mir geht es darum, dass der zweite AVR, der am IR-Empfänger TSOP1736 hängt, dann nur das Kommando erkennt.
    Also soll der zweite AVR nur 11111110 erkennen und auswerten.

    Mein Prinzip: (BASCOM)
    Der AVR erkennt das Byte 00000001 und startet somit die "Aufzeichnung", dann kommt auch schon das Kommando rein (11111110), und er wertet es aus. und das Byte 00000011 beendet die "Aufzeichnung" und der AVR wartet nun auf ein weiteres Startbyte.

    NUr wie realisiere ich so etwas?
    Wie kann ich einen Pin des AVR auslesen, und 0er und 1er -Folgen speichern und dann auslesen?
    Für 11111110 soll zB Funktion1 starten, für 11111100 Funktion2.....

    Man könnte die Bitfolgen doch in ein Array speichern und dann auslesen, oder?

    Helft mir bitte!
    MfG,
    ShadowPhoenix

  2. #2
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    02.03.2004
    Ort
    Paderborn
    Alter
    32
    Beiträge
    614
    Man könnte die Bitfolgen doch in ein Array speichern und dann auslesen, oder?
    Ja, könnte man.
    Was das Speichern angeht, kannst du über eine Zählvariable speichern, das wievielte Bit es ist und es jeweils an die entsprechende Stelle einer Byte-Variable schreiben (wenn der Zähler bei 8 ist, fängt das nächste Byte an.).
    Dann musst du nurnoch den Anfang des Signals syncronisieren (also bei deinem Startbyte 15ms nach dem ersten Bit das zweite lesen und dann im 10ms-Takt weiter bis dein Stopbyte kommt oder einfach bis 8bit empfangen sind.).
    Bei Signalen, die deutlich länger als 3 Byte sind, würde sich dann ein Interupt oder ein Pollen des Eingangspins mit höherer Frequenz anbieten, damit die Übertragung länger syncron bleibt.
    Helft mir bitte!
    Gern. Leider bin ich mir nicht ganz sicher, ob ich richtig verstanden habe, an welcher Stelle du ein Problem hast.

  3. #3
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    31.01.2004
    Beiträge
    585
    @Gottfreak

    Okay, ich verstehe dein Prinzip, aber leider nicht alles.
    Manches scheint mir etwas komplex.
    Weisst du was? Ich wäre sehr sehr zufrieden, wenn du mir ein einfaches
    Beispiel in Bascom erklären könntes.
    Leider bin ich noch ziemlicher Anfänger.
    Ich kann zwar AVR's programmieren, aber sobald neue Funktionen dazukommen, haperts bei mir , du verstehst.

    Mein eigentliches Problem ist:
    Ich möchte wissen, wie ich in Bascom mit einem AVR je 3 Bytes senden kann, und dann an einem anderen AVR je diese 3 Bytes wieder verarbeiten kann.
    Wie sollte der Code in Bascom zum senden ausschauen?
    Und wie der Code zum Empfangen?

    Würdest mir echt einen grossen Gefallen tun

    MfG,
    ShadowPhoenix

  4. #4
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    02.03.2004
    Ort
    Paderborn
    Alter
    32
    Beiträge
    614
    Hi
    Du hast echt Glück, dass ich ohnehin nix besseres vorhatte.
    Hier ist ein (hoffentlich ausreichend kommentiertes) Beispiel
    Code:
    $regfile = "2313def.dat"                                    'AT90S2313 natürlich muss hier die Definitionsdatei für deinen AVR hin
    $crystal = 8000000                                          'Und hier deine Taktfrequenz
    
    'Konstanten
    Const Startbyte = 00000001
    Const Stopbyte = 00000011
    
    'Variablen
    Dim Zaehl As Byte : Dim Fehler As Bit : Dim Temp As Byte
    Dim Zaehl2 As Byte : Dim Temp2 As Byte                      'Nur zum Zaehlen im Interrupt - nicht woanders benutzen, da es plötzlich auf 7 wechseln könnte. Temp2 ändert sich auch(höchstwahrscheinlich) bei jedem Interrupt
    Dim Gelesen As Byte : Dim Zusenden As Byte                  'In Gelesen steht nach dem Empfang (also automatisch, wenn ein Signal am Port anlag) der empfangene Wert. In Zusenden musst du vor dem Aufrufen der Senderoutine den Wert reinschreiben, den du senden willst.
    Enable Int0
    Config Int0 = Falling
    On Int0 Onint0 Nosave
    Enable Interrupts
    Ddrb.0 = 0                                                  'PortB.0 auf Eingang - Die Ports sind willkürlich gewählt
    Ddrb.1 = 1                                                  'PortB.1 auf Ausgang
    Do
    Zusenden = 54                                               'Sendet erstmal einfach jede Sekunde 54
    Gosub Senden
    Waitms 760                                                  'Wartet den Rest der Sekunde, den das Senden nicht gedauert hat
        Loop
    
    Onint0:                                                     'löst das erste mal aus, wenn das Startbyte vorbei ist(dafür würde auch ein Bit genügen. Ist schlecht für die Fehlerkorrektur.)
    push SREG
    Waitms 5                                                    'jetzt sind wir in der Mitte des ersten Datenbits...
    Gosub Bytelesen                                             'und lesen die anderen
    Temp = Gelesen                                              'Hier sind wir in der Mitte des ersten Bit des Stopbytes...
    Gosub Bytelesen                                             ' ...und lesen es
    If Gelesen <> Stopbyte Then Fehler = 1 Else Fehler = 0      'Für ein Minimun an Fehlererkennung kannst du in Fehler abfragen, ob das Stopbyte korrekt empfangen wurde
    Gelesen = Temp                                              'In Gelesen steht jetzt der empfangene Wert
    waitms 5                                                         'Damit die fallende Flanke am Ende des Stopbytes nicht als Anfang eines neuen Bytes verstanden wird (da der Empfang während eines Interupts stattfindet, löst der so nicht nochmal aus).
    pop SREG
    Return
    
    Bytelesen:
    For Zaehl2 = 0 To 7
    Gelesen.zaehl2 = Portb.1
    Waitms 10
    Next
    Return
    
    Senden:
    Temp = Zusenden                                             'Zu sendendes Byte sichern, da die Variable Zusenden mehrfach benutzt wird
    Zusenden = Startbyte
    Gosub Bytesenden
    Zusenden = Temp
    Gosub Bytesenden
    Zusenden = Stopbyte
    Gosub Bytesenden
    Return
    
    Bytesenden:
    For Zaehl = 0 To 7
    Portb.0 = Zusenden.zaehl
    Waitms 10
    Next
    End
    Zu erwähnen wäre folgendes:
    1. Ich hab's nicht getestet (zwei AVRs damit bespielen, verbinden und irgendwie ausprobieren, ob das richtige angekommen ist, war mir dann doch zu aufwändig). Im Prinzip sollte das halt gehen.
    2. Ich hab' keine Ahnung, wie lange die einzelnen Bascom-Befehle brauchen. Zum Zeitbedarf der Warteschleifen kommt also noch der der Befehle hinzu(der Unterschied zwischen deren Zeitbedarf beim Senden und Empfangen ist hoffentlich bei einem Byte <5ms, sonst verpasst der ein Bit).
    3. Senden und Empfangen "gleichzeitig"(also auf einem AVR) ist nicht ohne weiteres möglich, da die Empfangsroutine das Senden unterbricht (und so lange Pause macht, dass das Gesendete unverständlich wird). Dann müsstest du während dessen die Interrupts ausmachen und irgendwie dafür sorgen, dass die AVRs sich mit dem Zeitfenster abwechseln (oder statt Warteschleifen Timer nehmen, was aber erstens recht umständlich ist und zweitens wohl nur in ASM genau geht).
    Die Routinen sind also nur zur Anschauung im gleichen Programm untergebracht.
    4. Ich weis auch nicht, welche Register Bascom einfach so benutzt(für die Schleifen), die nicht gesichert werden(siehe nosave). Wenn der Rest deiner Programmausführung beim Empfangen nicht richtig geht, lass es weg(und wenn es dann zu lange dauert, mach die ersten "waitms 5" kürzer.).

  5. #5
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    02.03.2004
    Ort
    Paderborn
    Alter
    32
    Beiträge
    614
    Ups
    Da war wohl der eine oder andere Kommentar zu lang. Wenn du das ganze wieder in Bascom kopierst, verschwinden die hässlichen Zeilenumbrüche.

  6. #6
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    31.01.2004
    Beiträge
    585
    Ich danke dir vielmals für diesen Beispielcode.
    Jedoch bin ich wiegesagt noch eher ein Anfänger in Bascom & AVR programmieren.
    Mein Problem besteht nun darin, dass ich nicht verstehe, wie ich
    den Code nun anwenden soll.

    Ich weiß, es kann schwierig mit mir sein (:-O), aber auf jegliche Hilfe freue ich mich dafür umso mehr.
    Leider weiß ich nun nicht, wo ich das Kommandobyte eingeben muss und wo das Kommandobyte dann empfangen wird.

    Eines weiß ich:
    Dieser Code ist zum Senden & Empfangen gleichzeitig, oder?
    Man muss ihn nun irgendwie in zwei Hälften "trennen", einen Code zum Senden und einen Code zum Empfangen.
    Dann kommt je ein Code auf einen AVR.
    So stelle ich mir das vor. Könntest du mir noch diesen Gefallen machen, und den Code fachgemäß teilen?

    Vielen Dank @Gottfreak für deine bisherige Hilfe, ich weiß das sehr zu schätzen

    MfG,
    ShadowPhoenix

  7. #7
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    02.03.2004
    Ort
    Paderborn
    Alter
    32
    Beiträge
    614
    Hier nochmal in "zerhackstückselt" und mit Einrückungen
    Immerhin sind mir noch sinnvolle Änderungen eingefallen (der Code ist nicht richtig kompatibel zu den Routinen oben).
    Hier zum Senden. In der Hauptschleife, die jetzt die ganze Zeit das gleiche sendet, fügst du dann ein, was auch immer du dir als Anwendung überlegt hast.
    Code:
    $regfile = "2313def.dat"                                    'AT90S2313 natürlich muss hier die Definitionsdatei für deinen AVR hin
    $crystal = 8000000                                          'Und hier deine Taktfrequenz
    
    'Konstanten
    Const Startbyte = 00000001
    Const Stopbyte = 00000011
    
    'Variablen
    Dim Zaehl As Byte : Dim Temp As Byte
    Dim Zusenden As Byte
    
    Ports sind willkürlich gewählt
    Ddrb.1 = 1                                                  'PortB.1 auf Ausgang
    Do
        Zusenden = 54                                           'Sendet erstmal einfach jede Sekunde 54
        Gosub Senden
        Waitms 760                                              'Wartet den Rest der Sekunde, den das Senden nicht gedauert hat
        Loop
    
    Senden:
        Temp = Zusenden                                         'Zu sendendes Byte sichern, da die Variable Zusenden mehrfach benutzt wird
        Zusenden = Startbyte
        Gosub Bytesenden
        Zusenden = Temp
        Gosub Bytesenden
        Zusenden = Stopbyte
        Gosub Bytesenden
        Return
    
    Bytesenden:
        For Zaehl = 0 To 7
        Portb.1 = Zusenden.zaehl
        Waitms 10
        Next
        return
        End
    Und hier zum Empfangen (in der Hauptschleife kannst du wieder die gewünschte Auswertung einfügen.)
    Code:
    $regfile = "2313def.dat"                                    'AT90S2313 natürlich muss hier die Definitionsdatei für deinen AVR hin
    $crystal = 8000000                                          'Und hier deine Taktfrequenz
    
    'Konstanten
    Const Stopbyte = 00000011
    
    'Variablen
    Dim Fehler As Bit
    Dim Zaehl2 As Byte : Dim Temp As Byte                       'Nur zum Zaehlen im Interrupt - nicht woanders benutzen, da es plötzlich auf 7 wechseln könnte. Temp ändert sich auch(höchstwahrscheinlich) bei jedem Interrupt
    Dim Gelesen As Byte
    Enable Int0
    Config Int0 = Falling
    On Int0 Onint0 Nosave
    Enable Interrupts
    Ddrd.2 = 0                                                  'PortD.2 auf Eingang - Der Port sollte zu dem Interrupt gehören, über den empfangen wird
    Do
        If Gelesen = 4 Then Portb.5 = 1 Else Portb.5 = 0        'Hier kannst du den empfangenen Wert auswerten
        Loop
    
    Onint0:                                                     'löst das erste mal aus, wenn das Startbyte vorbei ist(dafür würde auch ein Bit genügen. Ist schlecht für die Fehlerkorrektur...)
        Waitms 5                                                'jetzt sind wir in der Mitte des ersten Datenbits...
        Gosub Bytelesen                                         'und lesen die anderen
        Temp = Gelesen                                          'Hier sind wir in der Mitte des ersten Bit des Stopbytes...
        Gosub Bytelesen                                         ' ...und lesen es
        If Gelesen <> Stopbyte Then Fehler = 1 Else Fehler = 0  'Für ein Minimun an Fehlererkennung kannst du in Fehler abfragen, ob das Stopbyte korrekt empfangen wurde
        Gelesen = Temp                                          'In Gelesen steht jetzt der empfangene Wert
        Waitms 5
        Return
    
    Bytelesen:
        For Zaehl2 = 0 To 7
        Gelesen.zaehl2 = Portd.2
        Waitms 10
        Next
        Return
    End
    PS: Deine Antwort kam so schnell, dass ich mir kaum vorstellen kann, dass du wirklich den ganzen Code durchgegangen bist und in der Hilfe alles nachgeschlagen hast, was nicht klar war.

  8. #8
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    31.01.2004
    Beiträge
    585
    Quote:
    PS: Deine Antwort kam so schnell, dass ich mir kaum vorstellen kann, dass du wirklich den ganzen Code durchgegangen bist und in der Hilfe alles nachgeschlagen hast, was nicht klar war.

    Hmm, ich habe mir den Code einmal angeschaut, da ich hier auf dem Laptop kein Bascom installiert habe, sondern in meiner Werkstätte am PC, hast du Recht; ich bin wirklich nicht alle Befehle durchgegangen :-/
    Leider bin ich manchmal etwas ungeduldig oder begriffsstutzig *g*

    Wow, ich danke dir trotzdem dafür, dass du dir so viel Mühe gemacht hast und mir den Code auch noch zerhackstückselt hast )

    Wenn ich nur irgendetwas für dich tun könnte...,... :-o
    MfG,
    ShadowPhoenix

    PS: Eins verstehe ich nicht, warum verwendest du "Ddrb.1" anstatt normal Portb.1 ?

  9. #9
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    02.03.2004
    Ort
    Paderborn
    Alter
    32
    Beiträge
    614
    Eins verstehe ich nicht, warum verwendest du "Ddrb.1" anstatt normal Portb.1 ?
    DDRB ist das Datenrichtungsregister von Portb.
    Eine 0 an dieser Stelle heisst Eingang, eine 1 Ausgang (tatsächlich verwende ich in dem Code "normal Portb.1". Die Klarstellung ist für den Compiler wichtig, da es durchaus auch Sinn machen kann, einen Eingang zu setzen und einen Ausgang auszulesen.).
    it works best if you plug it (aus leidvoller Erfahrung)

  10. #10
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    31.01.2004
    Beiträge
    585
    Okay!

    So, ein großes Danke noch einmal!
    Habe mir zufällig beim schlafen gehen noch Gedanken über die Fehlerkorrektur gemacht.
    Nehmen wir an, das Signal wird durch irgendetwas gestört (Sei es eine Hochspannungsleitung oder eine Mikrowelle :-o).
    Dann kommen doch die 3 Bytes nicht so an, wie sie sollten, oder?

    Das könnte dann echt zu einem großen Problem ausarten, oder sehe ich das falsch bzw. ist in dem Code schon eine gewisse Fehlerkorrektur eingebaut?

    MfG;
    ShadowPhoenix

+ Antworten
Seite 1 von 2 12 LetzteLetzte

Berechtigungen

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