-         

Ergebnis 1 bis 8 von 8

Thema: an Sub übergebene Werte

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    19.02.2010
    Beiträge
    67

    an Sub übergebene Werte

    Anzeige

    Hallo Forum,

    ich möchte mit 3 DA-Wandlern LTC1257 analoge Spannungen ausgeben.
    Diese DA-Wandler hängen hintereinander, hinter Optokopplern und müssen daher mit invertierten Signalen angesteuert werden.

    Ich habe dazu eine Sub Analog, welche die 3 Sollspannungen übergeben bekommt.
    Um nun nicht laufend identische Werte in die DA-Wandler zu shiften, möchte ich einen Vergleich zwischen bereits geladenen Werten und neuen Werten durchführen und nur bei Differenz neu laden.

    Testweise rufe ich die Sub zyklisch mit identischen Werten auf - dennoch werden unterschiedliche Parameter erkannt.

    Wo ist hier der Fehler?

    Hier eine Beispielausgabe aus dem Terminal:

    1000 0 2000 0 3000 0
    1000 1000 331 2000 3000 3000
    1000 1000 2000 331 3000 3000
    1000 1000 2000 2000 364 3000
    1000 1000 2000 2000 3000 364
    800 1000 2000 2000 3000 3000
    1000 800 2000 2000 3000 3000
    1000 1000 288 2000 3000 3000
    1000 1000 2000 288 3000 3000
    288 1000 2000 2000 3000 3000
    1000 288 2000 2000 3000 3000
    1000 1000 288 2000 3000 3000
    1000 1000 2000 288 3000 3000
    288 1000 2000 2000 3000 3000
    1000 288 2000 2000 3000 3000
    1000 1000 2000 2000 288 3000
    1000 1000 2000 2000 3000 288
    1000 1000 2000 2000 2848 3000
    1000 1000 2000 2000 3000 2848
    353 1000 2000 2000 3000 3000
    1000 353 2000 2000 3000 3000
    1000 1000 2000 2000 314 3000
    1000 1000 2000 2000 3000 314
    288 1000 2000 2000 3000 3000
    1000 288 2000 2000 3000 3000
    288 1000 2000 2000 3000 3000
    1000 288 2000 2000 3000 3000
    288 1000 2000 2000 3000 3000
    1000 288 2000 2000 3000 3000
    800 1000 2000 2000 3000 3000
    1000 800 2000 2000 3000 3000
    1000 1000 288 2000 3000 3000
    1000 1000 2000 288 3000 3000
    288 1000 2000 2000 3000 3000
    1000 288 2000 2000 3000 3000
    1000 1000 288 2000 3000 3000
    1000 1000 2000 288 3000 3000
    288 1000 2000 2000 3000 3000
    1000 288 2000 2000 3000 3000
    1000 1000 2000 2000 288 3000
    1000 1000 2000 2000 3000 288
    1000 1000 2000 2000 2848 3000
    1000 1000 2000 2000 3000 2848
    288 1000 2000 2000 3000 3000
    1000 288 2000 2000 3000 3000
    1000 1000 288 2000 3000 3000
    1000 1000 2000 288 3000 3000
    288 1000 2000 2000 3000 3000
    1000 288 2000 2000 3000 3000


    und nachfolgend der reduzierte Quellcode

    mfG
    BoGe-Ro


    Code:
    $regfile = "M32def.dat"
    $crystal = 12288000
    $hwstack = 128
    $swstack = 64
    $framesize = 64
    $baud = 57600
    
    
    '### LCD #######################################################################
    Config Lcdpin = Pin , Db4 = Portb.2 , Db5 = Portb.3 , Db6 = Portb.4 , _
                           Db7 = Portb.5 , E = Portb.1 , Rs = Portb.0
    Config Lcd = 20 * 4
    Cursor Off Noblink
    Initlcd
    Lcd_enable Alias Portb.1 : Config Lcd_enable = Output
    Dim Lcd_inhalt As String * 80                               'Textpuffer für Displayausgabe
    Dim Lcd_inhalt_byte(80) As Byte At Lcd_inhalt Overlay
    Lcd_inhalt = Space(80)
    Dim Lcd_cnt As Byte
    Dim Lcd_text As String * 20                                 'Temp-Variable für String-Zusammenbau
    Dim Lcd_text_char(20) As Byte At Lcd_text Overlay
    
    Declare Sub Lcd_put(byval _x As Byte , Byval _reg As Byte)
    Declare Sub Lcd_print(byval _x As Byte , Byval _y As Byte , Byval _text As String)
    '###############################################################################
    
    
    '### Timer0-Systemtakt #########################################################
    Tccr0 = &B1000_1011                                         'ctc-mode, prescaler=64
    Ocr0 = 191                                                  '95=500µs   /   191=1ms
    Timsk.ocie0 = 1
    On Oc0 Isr_timer0
    
    
    '### DA-Wandler ################################################################
    A_latch Alias Portd.6 : Config A_latch = Output : Reset A_latch
    A_clock Alias Portd.4 : Config A_clock = Output : Set A_clock
    A_data Alias Portd.3 : Config A_data = Output
    Declare Sub Analog(byval _w1 As Word , Byval _w2 As Word , Byval _w3 As Word , Byval _mamv As Byte)
    '_w1 = p-soll
    '_w2 = p-ist
    '_w3 = 0-10V / 4-20mA
    '_mav: 0=µA / 1=mV
    Dim W1_alt As Word , W2_alt As Word , W3_alt As Word
    
    Dim L_temp As Long
    Dim B_temp As Byte
    Dim W_temp As Word
    Dim Beschleunigung As Word : Beschleunigung = 0
    
    
    Enable Interrupts
    
    
    Do
       L_temp = 2000
       Sreg.7 = 0
       Lcd_text = "Kanal 3: " + Str(l_temp) + Space(2) : Call Lcd_print(1 , 3 , Lcd_text)
       Sreg.7 = 1
    
       If Beschleunigung = 0 Then Call Analog(1000 , 2000 , 3000 , 1)
    Loop
    End
    
    
    
    '### ISR's #####################################################################
    Isr_timer0:
       If Beschleunigung > 0 Then Decr Beschleunigung
       Incr Lcd_cnt                                             'nächstes Zeichen im Display-Puffer
       If Lcd_cnt =< 80 Then Call Lcd_put(lcd_inhalt_byte(lcd_cnt) , 1)       'Zeichen ausgeben
       If Lcd_cnt = 81 Then Call Lcd_put(2 , 0)                 'Cursor at home (2ms)
       If Lcd_cnt = 90 Then Lcd_cnt = 0
    Return
    
    
    
    
    
    '### Sub's #####################################################################
    
    '### DA-Wandler ################################################################
    Sub Analog(_w1 , _w2 , _w3 , _mamv)
    'invertierte Ansteuerung aufgrund Optokoppler
    '_w1 = p-soll
    '_w2 = p-ist
    '_w3 = 0-10V / 4-20mA
    '_mamv:0=10µA / 1=mV
    Local _s1 As Single
    Local _s2 As Single
    Local _s3 As Single
    
       '4095        1
       '---- => --------
       '10 V    2.442 mV
    
       If _w1 <> W1_alt Or _w2 <> W2_alt Or _w3 <> W3_alt Then
          Sreg.7 = 0
          Print _w1 ; Chr(9) ; W1_alt ; Chr(9) ; _w2 ; Chr(9) ; W2_alt ; Chr(9) ; _w3 ; Chr(9) ; W3_alt
          Sreg.7 = 1
          W1_alt = _w1 : W2_alt = _w2 : W3_alt = _w3
    
          _s1 = _w1 * 0.4095 : _s1 = _s1 + 0.5 : _w1 = _s1
          _s2 = _w2 * 0.4095 : _s2 = _s2 + 0.5 : _w2 = _s2
    
          If _mamv = 1 Then
                _s3 = _w3 * 0.4095
                _s3 = _s3 + 0.5
             Else
                If _w3 >= 400 Then
                      _s3 = _w3 * 2.559375
                      _s3 = _s3 - 1023.25                       '-1023.75 + 0.5 für Rundung
                   Else
                      _s3 = 0
                End If
          End If
          _w3 = _s3
    
          Shift _w1 , Left , 4 : _w1 = _w1 Xor &HFFFF
          Shift _w2 , Left , 4 : _w2 = _w2 Xor &HFFFF
          Shift _w3 , Left , 4 : _w3 = _w3 Xor &HFFFF
          Shiftout A_data , A_clock , _w3 , 0 , 12 , 10
          Shiftout A_data , A_clock , _w2 , 0 , 12 , 10
          Shiftout A_data , A_clock , _w1 , 0 , 12 , 10
          Set A_latch : Waitms 1 : Reset A_latch
       End If
    End Sub
    
    
    '### LCD #######################################################################
    '
    Sub Lcd_print(byval _x As Byte , Byval _y As Byte , _text As String * 20)
    'Z1S1 = 1-20
    'Z2S1 = 41-60
    'Z3S1 = 21-40
    'Z4S1 = 61-80
    Local _position As Byte
    Local _anzahl As Byte
    Local _i As Byte
       Select Case _y
          Case 1 : _position = 0
          Case 2 : _position = 40
          Case 3 : _position = 20
          Case 4 : _position = 60
       End Select
       _position = _position + _x
       _anzahl = Len(_text)
    '   _i = Memcopy(_text , Lcd_inhalt_byte(_position) , _anzahl)
       For _i = 1 To _anzahl
          If Lcd_text_char(_i) = "ü" Then Lcd_text_char(_i) = $f5
          If Lcd_text_char(_i) = "ö" Then Lcd_text_char(_i) = $ef
          If Lcd_text_char(_i) = "ä" Then Lcd_text_char(_i) = $e1
          If Lcd_text_char(_i) = "ß" Then Lcd_text_char(_i) = $e2
          Lcd_inhalt_byte(_position) = Lcd_text_char(_i)
          Incr _position
          If _position = 81 Then Exit For
       Next _i
    End Sub
    
    
    Sub Lcd_put(_x As Byte , _reg As Byte)
    ' _reg=1: Datenregister
    ' _reg=0: Befehlsregister
    Local Lcd_data As Byte
       Lcd_data = _x And &HF0 : Shift Lcd_data , Right , 2      'oberes Nibble
       Portb = Lcd_data + _reg                                  'Datenbyte auf Bus legen
       !nop
       !nop
       Lcd_enable = 1
       !nop
       !nop
       Lcd_enable = 0
    
       Lcd_data = _x And &H0F : Shift Lcd_data , Left , 2       'unteres Nibble
       Portb = Lcd_data + _reg                                  'Datenbyte auf Bus legen
       !nop
       !nop
       Lcd_enable = 1
       !nop
       !nop
       Lcd_enable = 0
    End Sub

  2. #2
    Benutzer Stammmitglied
    Registriert seit
    19.02.2010
    Beiträge
    67
    Der Fehler liegt offenbar an dem Funktionsaufruf der Sub Lcd_put(_x As Byte , _reg As Byte).
    Werden beide Aufrufe in der Timer0-ISR auskommentiert, gibt es keine Differenzen bei der Analog-Sub.
    Kommentiere ich dagegen nur den Inhalt der Sub Lcd_put(_x As Byte , _reg As Byte) aus, treten diese Fehler wiederum auf.

    Wer kann helfen?

    mfG
    BoGe-Ro

  3. #3
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    18.05.2007
    Ort
    Berlin
    Alter
    46
    Beiträge
    765
    In einer ISR sollten keine LCD Ausgaben getätigt werden. Die Ausführzeit des Sub LCDPUTist evtl. länger als der Abstand zwischen 2 IRQ.
    Wenn das Herz involviert ist, steht die Logik außen vor! \/

  4. #4
    Benutzer Stammmitglied
    Registriert seit
    19.02.2010
    Beiträge
    67
    Hallo peterfido,

    die Antwort triffts leider nicht.
    Die Sub Lcd_put ist sehr sehr kurz - daran liegt es ganz sicher nicht. Es wird ja lediglich an den Pins des LCD gewackelt, so dass pro ms ein Byte im 4-bit-Mode ans LCD übertragen wird.
    Weiterhin tritt der Fehler sogar auf, wenn in der Sub gar nichts mehr steht.

    Weiterhin wurde festgestellt:
    - spring ich in die leere Sub Lcd_put und übergebe einen Byte-Wert für _x, ist es genau dieser Byte-Wert der im Fehlerfall an Stelle _w1 in der Sub Analog auftaucht.
    - veränder ich den bei Lcd_put übergebenen Byte-Wert für _x in der Lcd_put-Sub, so taucht der veränderte Byte-Wert für _w1 in der Sub Analog auf
    - sogar im Bascom-Simulator ließ sich der Fehler produzieren - allerdings scheint es hier unmöglich die Register zu beobachten, weil während einiger hundert Durchläufe der Hauptschleife nur ab und an der Fehler auftaucht.

    Da ich das Testprogramm allerdings auf Arbeit vergessen habe, kann ich leider erst am Montag weiterforschen

    mfG
    BoGe-Ro

  5. #5
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    18.05.2007
    Ort
    Berlin
    Alter
    46
    Beiträge
    765
    Welche Bascom Version hast Du? Ich habe gestern einen Fehler im Code gesucht, den es gar nicht gab. Der Code lief schon einige Zeit zuverlässig und wurde mit einer älteren Bascom Version kompiliert. Gestern habe ich an anderer Stelle etwas geändert und anschließend kam nur Mist bei raus. Nach dem Update auf 2.0.7.0 war der Fehler wieder weg. So tippe ich auf ein Problem der 2.0.6.x
    Wenn das Herz involviert ist, steht die Logik außen vor! \/

  6. #6
    Benutzer Stammmitglied
    Registriert seit
    19.02.2010
    Beiträge
    67
    Hallo,

    also ich nutze die Version 1.11.9.3
    Mir steht aktuell auch nur diese Version zur Verfügung.
    Nachfolgend der aktuelle Testcode - welcher noch immer den Fehler mitbringt.

    Sogar im Bascom-Simulator taucht die "55" aus der Sub Lcd_put in der Sub Analog auf.

    Also die Variablen _w1, _w2 und _w3 haben manchmal den Wert 55 obwohl sie mit _w1=10 , _w2=20 und_w3=30 übergeben werden.


    Code:
    $regfile = "M32def.dat"
    $crystal = 12288000
    $hwstack = 128
    $swstack = 96
    $framesize = 64
    $baud = 57600
    '$sim
    
    
    '### LCD #######################################################################
    Dim Lcd_cnt As Byte
    Declare Sub Lcd_put(byval _x As Byte , Byval _reg As Byte)
    '###############################################################################
    
    
    '### Timer0-Systemtakt #########################################################
    On Oc0 Isr_timer0
    Tccr0 = &B1000_1011                                         'ctc-mode, prescaler=64
    Ocr0 = 191                                                  '95=500µs   /   191=1ms
    Timsk.ocie0 = 1
    
    
    
    '### DA-Wandler ################################################################
    Declare Sub Analog(byval _w1 As Byte , Byval _w2 As Byte , Byval _w3 As Byte )
    Dim W1_alt As Byte , W2_alt As Byte , W3_alt As Byte
    
    
    
    Enable Interrupts
    
    
    Do
       Call Analog(10 , 20 , 30 )
    Loop
    End
    
    
    
    '### ISR's #####################################################################
    Isr_timer0:
       Incr Lcd_cnt                                             'nächstes Zeichen im Display-Puffer
       If Lcd_cnt <= 80 Then Call Lcd_put(5 , 1)                'Zeichen ausgeben
       If Lcd_cnt = 81 Then Call Lcd_put(2 , 0)                 'Cursor at home (2ms)
       If Lcd_cnt = 250 Then Lcd_cnt = 0
    Return
    
    
    
    
    
    '### Sub's #####################################################################
    
    '### DA-Wandler ################################################################
    Sub Analog(_w1 , _w2 , _w3 )
       If _w1 <> W1_alt Or _w2 <> W2_alt Or _w3 <> W3_alt Then
    '   If _w1 <> W1_alt Then
          Sreg.7 = 0
          Print _w1 ; Chr(9) ; W1_alt ; Chr(9) ; _w2 ; Chr(9) ; W2_alt ; Chr(9) ; _w3 ; Chr(9) ; W3_alt
          Sreg.7 = 1
          W1_alt = _w1
          W2_alt = _w2
          W3_alt = _w3
        End If
    End Sub
    
    
    '### LCD #######################################################################
    '
    Sub Lcd_put(_x , _reg )
       _x = 55
    End Sub

  7. #7
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    18.05.2007
    Ort
    Berlin
    Alter
    46
    Beiträge
    765
    Da scheint der Softwarestack oder Framestack aus dem Takt zu kommen. Am besten Du postest direkt im mcselc Forum mit Deinem Beispiel Code. Mark Albert bereinigt solche Sachen immer recht schnell, wenn er sie denn kennt. Da eine Sub mit Parameter aufrufen immer eine Menge Stackschieberei nutzt, rufen die meisten Programmierer aus einer ISR keine SUB mit Parameter auf. Ich persönlich nutze so gut wie keine Subs, sondern verwende globale Variablen und springe per Gosub dahin und mit return zurück. Läuft wesentlich schneller, braucht aber mehr RAM als mehrere Subs mit lokalen Variablen. Aber auch da kann man sich helfen und Variablen einfach nur für solche Zwecke verwenden. Aber dann nicht aus einer ISR heraus...

    PS: Ein Update auf die 2.0.7.0 lohnt sich in jedem Fall. Oft wird Code kürzer, sodass gefühlt mehr Programm in den MC passt.
    Wenn das Herz involviert ist, steht die Logik außen vor! \/

  8. #8
    Benutzer Stammmitglied
    Registriert seit
    19.02.2010
    Beiträge
    67
    Hallo,

    für mich hat sich herausgestellt, dass es offenbar bei Funktions- und Subaufrufen aus einer ISR heraus zu Differenzen zwischen übergebenen und ankommenden Werten kommt.

    Bei Arbeit mit globalen Variablen und Verzweigung mit Gosub - Return traten derartige Fehler nicht auf


    Danke
    BoGe-Ro

Ähnliche Themen

  1. Werte begrenzen
    Von Martinius11 im Forum Robby RP6
    Antworten: 17
    Letzter Beitrag: 27.06.2010, 19:56
  2. Unregelmäßige werte für PWM
    Von BastelWastel im Forum PIC Controller
    Antworten: 5
    Letzter Beitrag: 21.02.2006, 01:43
  3. A/D Werte ausgeben
    Von toraX im Forum C - Programmierung (GCC u.a.)
    Antworten: 13
    Letzter Beitrag: 17.02.2006, 02:20
  4. Werte senden
    Von Elle im Forum Sensoren / Sensorik
    Antworten: 1
    Letzter Beitrag: 01.02.2006, 00:49
  5. CNY Werte
    Von noNeed 4 aNick im Forum AVR Hardwarethemen
    Antworten: 7
    Letzter Beitrag: 30.01.2005, 19:09

Berechtigungen

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