BoGe-Ro
05.08.2011, 09:59
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
$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
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
$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