PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : 7 Segmentanzeige führende Nullen ausblenden



TobiasBlome
20.08.2008, 16:38
Hallo,
ich habe eine 7 Segmentanzeige mit 5 Stellen (also 0-99999) im Multiplexbetrieb(softwaremultiplex über AT-MEGA8).

Nun möchte ich die führenden Nullen ausblenden also nicht "00123" sondern nur " 123".

mein Versuch war:

ganz links angefangen: wenn da eine "0" ist einfach den Transistor für die gemeinsame Anode abschalten - fertig (funktioniert!)

nun die 2. Zahl von links: wenn 1. & 2. Zahl = "0" dann auch diese gemeinsame Anode abschalten. Leider klappt das wegen dem Multiplexbetrieb nicht: es leuchtet ja genaugenommen immer nur eine "Ziffer".
Also habe ich das mit Merkern versucht: wenn Ziffer gleich 0 gem.Anode abschalten und Merker (Digi1) auf 1 setzen... funktioniert aber auch nicht in allen Fällen...

Aber ich glaube das Programm sagt mehr....


'-------------------------------------------------------------------------------
7seganzeige:
' Code 7 Segmentanzeige:
'-------------------------------------------------------------------------------



'Formatiere das Display
Wertstr = Str(wert)
Fivedigitdisplay = Format(wertstr , "00000") 'Nullen geben die Anzahl der Stellen an, damit die Stellen richtig gesetzt werden


' jeder Lauf durch die Hauptschleife zeigt ein anderes Digit
Incr Digit

Portb = 0 'Ghosting vermeiden
If Digit = 5 Then 'mache das , bis 5 erreicht ist
Digit = 0

End If

' addiere 1 zum Digitcounter, weil MID 1-basiert ist
Y = Digit + 1
' und hol das Digit, das wir brauchen
Wertstr = Mid(fivedigitdisplay , Y , 1)


'Anzeige auswählen
Tempbyte = 2 ^ Digit 'Tempbyte = 1,2,4,8,16

'Digitansteuerung auf portC: PC1-5
Umdreh = Tempbyte * 2 'Umdreh = 2,4,8,16,32
'Ansteuerung umdrehen für gemeinsame Anoden
Portc = Umdreh 'Port für die Stellen auswahl



'Führende Nullen entfernen:

'INFO:
'wertstr hat immer nur eine Ziffer und wechselt also nacheinander alle 5 Stellen durch!
'wenn wertstr = 0 ist dann wird nachgesehen, in welchem Digit (Stelle) wir uns befinden.
'wenn Digit = 0 -also die ganz linke Stelle- dann auf jeden Fall Portc.1 = 0 (Transistor der Stelle) abschalten
'Digit0 = 0 -> ist nur ein Merker für die folgenden Stellen d.h.

'wenn wertstr=0 dann fragen ob Digit=1 (also 2te Stelle von links) UND der Merker Digit0=0
'dann Transistor abschalten und weiteren Merker für diese Stelle setzen

'ZehnTausenderstelle
If Val(wertstr) = 0 Then 'Führende Null wegblenden
If Digit = 0 Then : Portc.1 = 0 : Digit0 = 0 'C.1=Digit Transistor
Else
Digit0 = 1
End If
End If
'Tausenderstelle
If Val(wertstr) = 0 Then 'Führende Null wegblenden
If Digit = 1 And Digit0 = 0 Then : Portc.2 = 0 : Digit1 = 0 'C.2=Digit Transistor
Else
Digit1 = 1
End If
End If
'Hunderterstelle
If Val(wertstr) = 0 Then 'Führende Null wegblenden
If Digit = 2 And Digit0 = 0 And Digit1 = 0 Then : Portc.3 = 0 : Digit2 = 0 'C.3=Digit Transistor
Else
Digit2 = 1
End If
End If
'Zehnerstelle
If Val(wertstr) = 0 Then 'Führende Null wegblenden
If Digit = 3 And Digit0 = 0 And Digit1 = 0 And Digit2 = 0 Then : Portc.4 = 0 : Digit3 = 0 'C.4=Digit Transistor
Else
Digit3 = 1
End If
End If

'Dieser Teil erledigt die Wandlung in 7 Segment Code

'Für Anzeigen mit gemeinsamer Anode
Select Case Val(wertstr)

Case 0 : Portb = 126 'NULL
Case 1 : Portb = 12 'EINS
Case 2 : Portb = 182 'ZWEI
Case 3 : Portb = 158 'DREI
Case 4 : Portb = 204 'VIER
Case 5 : Portb = 218 'FÜNF
Case 6 : Portb = 250 'SECHS
Case 7 : Portb = 14 'SIEBEN
Case 8 : Portb = 254 'ACHT
Case 9 : Portb = 222 'NEUN
'Case Else : Portb = 128 'mittleres Segment
Case Else : Portb = 226 '"F"
End Select

'Komma setzen
'If Portc = 2 Then Portb.0 = 1 '4 Kommastellen
'If Portc = 4 Then Portb.0 = 1 '3 Kommastellen
'If Portc = 8 Then Portb.0 = 1 '2 Kommastelle
If Portc = 16 Then Portb.0 = 1 '1 Kommastellen

TobiasBlome
20.08.2008, 17:07
Ach so:

Auf der Anzeige sollen auch negative Werte angezeicht werden können.
Also kommt noch der Code hinzu:

'negatives Vorzeichen setzen
If Portc = 2 Then
If Wert < 0 Then
Portb = 128 'Binär 1000 0000 -> Dezimal = 128 (nur Segment G)
End If
End If

Artur
20.08.2008, 20:43
... wenn da eine "0" ist einfach den Transistor für die gemeinsame Anode abschalten - fertig (funktioniert!)
...

Hi,
und warum machst du den Blödsinn über die Gemeinsame Anode/Katode(oder was auch immer) abschalten?

Bei so was lässt man einfach die Segmente aus , also wenn "0" dann alle Segment der Zahl aus und bei der "00" genauso .

Wird zu mindest in der Hardware (FPGA) Entwicklung so gemacht

Gruss
Artur

TobiasBlome
21.08.2008, 16:08
Hallo Artur,
ach so... na gut - aber dann bleibt natürlich mein "Grundproblem":
was ist die Vorraussetzung, damit kein Segment gesetzt wird?
Wie mache ich das Programmtechnisch?

Tobias

linux_80
21.08.2008, 16:32
Du arbeitest hier sowieso mit Strings, dann formatier die Zahl nicht mit "00000" sondern mit "____0" (_ = Leerzeichen), und bau in das select case den Wert für das "_" ein, das dann den Wert 0 ausgibt (Also PortB = 0 ).
Bei Select würde ich den Wert auch nicht nochmal extra in ein Integer wandeln, sondern gleich als Text vergleich anlegen, so kann man das Leerzeichen leicht mit integrieren.

TobiasBlome
21.08.2008, 16:38
Hallo Linux_80:

wie schreibe ich den Case Befehl mit dem "Leerzeichen"?

linux_80
21.08.2008, 16:42
select case wertstr

case " " : Portb = 0
case "0" : Portb = 126

usw.

TobiasBlome
21.08.2008, 16:50
Habe den Fehler in meinem Code gefunden:

meine Rücksetzbedingung war an der falschen Stelle und konnte so nicht immer zurückgesetzt werden ](*,)

so war´s:
_____________
Wenn Wert = 0

Wenn ganz linke Stelle aktiv & "Nullmerker"=0 DANN Stelle aus und "NullMerker"=0
SONST "Nullmerker"=1
End If

End If
------------------

NEU NEU NEU

_____________
Wenn Wert = 0

Wenn ganz linke Stelle aktiv & "Nullmerker"=0 DANN Stelle aus und "NullMerker"=0
End If

SONST "Nullmerker"=1
End If
------------------

TobiasBlome
21.08.2008, 16:54
ups das hat sich wohl etwas überschnitten...

BASCOM mag den Case nicht: case " " : Portb = 0
source Variable does not match the target variable....

schöner wäre es bestimmt, weil der Code kürzer ist (und der µC ist schon sehr belastet - habe noch ein LCD & Analogeingang...)

linux_80
21.08.2008, 17:48
Warum geht das nicht ? Was hast Du für 'ne Bascom Version ?
Läuft bei mir einwandfrei, mit der 1.11.9.2. und auch vorher schon, weil ich das in älteren Programmen so öfter gemacht habe.

Aber man könnte es dann immer noch besser mit einem Asc(wertstr) machen, und dann die Hexwerte der Zahlen beim Case angeben:


Dim Wertstr As String * 1

Wertstr = "1"

Dim Bytewert As Byte

Bytewert = Asc(wertstr)

Select Case Bytewert

Case &H20 : Portb = 0
Case &H30 : Portb = 126 ' 0
Case &H31 : Portb = 12 ' 1
' usw. einfach zu merken 0 ist &H30
End Select

End


so gehts bei mir auch:

Select Case Wertstr

Case " " : Portb = 0
Case "0" : Portb = 126
Case "1" : Portb = 12

End Select

End

TobiasBlome
21.08.2008, 18:00
Version 10.11.8.7

hhmmm neue Version?

TobiasBlome
21.08.2008, 19:40
Hallo linux_80,

ich habe jetzt Version 1.11.9.2 installiert und habe NUR die Zeile: Case " " : Portb = 0
eingefügt und schon kommt der Fehler.

Kannst du bitte den Code mal bei die compilieren und mir sagen ob es geht?

Tobas



'-------------------------------------------------------------------------------

$regfile = "m8def.dat" 'AT-Mega8
$crystal = 8000000 'Quarz: 8 MHz
$baud = 9600 'Baudrate der UART: 9600 Baud
'-------------------------------------------------------------------------------
'Konfiguration Ein- / Ausgänge
Ddrb = &B11111111 '1 Ausgang, 0 Eingang => Pin PB7-0 als Ausgang
Ddrc = &B1111110 '1 Ausgang, 0 Eingang => Pin PC6-1 als Ausgang; 0 als Eingang
Ddrd = &B11110001 '1 Ausgang, 0 Eingang => Pin PD7-4,0 als Ausgang; 1-3 als Eingang

'-------------------------------------------------------------------------------
'Konfiguration LCD
Config Lcd = 16 * 2
Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.0 , Rs = Portc.6
Cursor Off Noblink
'-------------------------------------------------------------------------------
'Konfiguration ADC
Config Adc = Single , Prescaler = Auto , Reference = Avcc

'-------------------------------------------------------------------------------
'Konfiguration Timer0
Config Timer0 = Timer , Prescale = 1024
On Timer0 Timer0_isr
Const Timervorgabe0 = 230 '312 mal / Sekunde!!!
Enable Timer0
Enable Interrupts


'-------------------------------------------------------------------------------
'Konfiguration Timer1
Config Timer1 = Timer , Prescale = 256
On Timer1 Timer1_isr
Const Timervorgabe1 = 55118 '3 mal / Sekunde!!!
Enable Timer1
Enable Interrupts


'-------------------------------------------------------------------------------
'Variablen Anzeige:
Dim Wert As Long ' (-2147483648 bis 2147483647)
Dim Wert_pos As Word 'gewandelter wert
Dim Negativ As Bit 'Merker = 1 wnn Wert negativ!

' variablen für die display routine
Dim Wertstr As String * 5
Dim Y As Byte
Dim Tempbyte As Byte
' Variable für Digitansteuerung
Dim Digit As Byte
'Anzeige im Ganzen
Dim Fivedigitdisplay As String * 5
Dim Umdreh As Byte

'führende Nullen entfernen
Dim Digit_aus As Bit 'Merker =0 wenn Stelle =0



'ADC
Dim Analog_in0 As Long 'Word '=0-1023 vom Analogeingang
Dim Pro1 As Integer
Dim Pro2 As Single
Dim Pro3 As Integer
Dim Proz_anzeige As Byte


'Variablen LCD
Dim Ani_1 As Integer 'Zähler für Startannimation LCD
Dim Ende As Word 'zum Animation beenden


'Variablen Taster
Dim S1 As Bit 'Schalter 1
Dim S2 As Bit 'Schalter 2
Dim S2_m As Bit
Dim S3 As Bit 'Schalter 3
Dim S3_m As Bit 'Schalter 3 MERKER
Dim Taste_s1 As Word

'Programmverteilung über Timer0
Dim Zeit As Word 'wird 312 mal / Sekunde mit 1 addiert


'Variablen zum testen......
Dim Test2 As Integer 'zum hochzählen zum testen
Dim Test As Integer


'-------------------------------------------------------------------------------
'Annimation LCD


Goto Sprung

Do
Cls


For Ani_1 = 16 To 1 Step -1 'Von 1 bis 16 wird gezählt
Locate 1 , Ani_1 'Die entsprechende Position im Display anwählen.
Lcd "> TOBIAS BLOME <"
Waitms 250
Next

Locate 2 , 1
Lcd "BI - EMR 10/2008"
Waitms 500
Locate 2 , 1
Lcd " "
Waitms 500
Locate 2 , 1
Lcd "BI - EMR 10/2008"
Waitms 500
Locate 2 , 1
Lcd " "
Waitms 500
Locate 2 , 1
Lcd "BI - EMR 10/2008"
Wait 3



Loop Until Ende => 1

Sprung:
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'Setzen:

Digit_aus = 0

'alle Segmente aus
Portb = 0
Digit = 0


Test2 = 9900

Start Adc



Do





'---Programm aufteilen---
If Zeit => 150 Then 'also eine halbe Sekunde
Zeit = 0 'Zeit zurücksetzen
End If







'---ENDE Programmaufteilung---


'zum testen um etwas zu "sehen"
' Incr Test

' If Test = 10 Then
' Test = 0
' Incr Test2
' End If

' If Test2 > 99999 Then
' Test2 = 0
' End If

Loop


'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'Sprungmarken
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------


'-------------------------------------------------------------------------------
Timer0_isr: 'Timer1-Interruptroutine (312 x pro Sekunde)
'-------------------------------------------------------------------------------
Timer0 = Timervorgabe0

Gosub 7seganzeige 'Routine für 7 Segmentanzeige

Incr Zeit 'Zeitgeber


If S1 = 1 Then 'soll nur hochgezählt werden, wenn Taste links gedrückt
Incr Taste_s1 'wenn taste lange gedrückt soll etwas passieren (LCD "e" wechsel)
Else
Taste_s1 = 0
End If

Return

'-------------------------------------------------------------------------------
Timer1_isr: 'Timer1-Interruptroutine (3 x pro Sekunde)
'-------------------------------------------------------------------------------
Timer1 = Timervorgabe1

Analog_in0 = Getadc(0) 'Analog in Variable schreiben

Wert = Analog_in0 - 500 'Wert für Anzeige

If Wert < 0 Then 'wenn wert negativ
Wert_pos = Wert * -1
Negativ = 1
Else
Wert_pos = Wert
Negativ = 0
End If


'Print "Digit0: " ; Digit0
'Print "Digit1: " ; Digit1
'Print "Digit2: " ; Digit2
'Print "Digit3: " ; Digit3


Return

'-------------------------------------------------------------------------------
Analog:
'Analogeingänge Auslesen:
'-------------------------------------------------------------------------------

'Analog_in0 = Getadc(0) 'Analog in Variable schreiben
' Wert = Analog_in0 'Wert für Anzeige
' Pro1 = Analog_in0 - 204 'Prozent1Wert analog 204-1005 also -204 = 0-801
' Pro2 = Pro1 * 0.12484 'Rechnen: 100% / max(801) = 0.12484
' Pro3 = Round(pro2)

' If Pro3 > 100 Then 'damit keine größenren Werte als 100% auf dem LCD stehen
' Pro3 = 100
' End If
'
' If Pro3 < 0 Or Pro3 > 110 Then 'wenn errechneter %Wert falsch (kleiner 0 oder größer 110 dann immer 0 (110 wegen 4-20mA Ungenauigkeit)
' Proz_anzeige = 0
' Else
' Proz_anzeige = Pro3
' End If



'-------------------------------------------------------------------------------
7seganzeige:
' Code 7 Segmentanzeige:
'-------------------------------------------------------------------------------



'Formatiere das Display
Wertstr = Str(wert_pos)
Fivedigitdisplay = Format(wertstr , "00000") 'Nullen geben die Anzahl der Stellen an, damit die Stellen richtig gesetzt werden


' jeder Lauf durch die Hauptschleife zeigt ein anderes Digit
Incr Digit
'Waitms 6 'Zeit für die Anzeige (je länger wait desto mehr flackert es)
Portb = 0 'Ghosting vermeiden
If Digit = 5 Then 'mache das , bis 5 erreicht ist
Digit = 0

End If

' addiere 1 zum Digitcounter, weil MID 1-basiert ist
Y = Digit + 1
' und hol das Digit, das wir brauchen
Wertstr = Mid(fivedigitdisplay , Y , 1)


'Anzeige auswählen
Tempbyte = 2 ^ Digit 'Tempbyte = 1,2,4,8,16

'Digitansteuerung auf portC: PC1-5
Umdreh = Tempbyte * 2 'Umdreh = 2,4,8,16,32
'Ansteuerung umdrehen für gemeinsame Anoden
Portc = Umdreh 'Port für die Stellen auswahl



'Führende Nullen entfernen:

'INFO:
'wertstr hat immer nur eine Ziffer und wechselt also nacheinander alle 5 Stellen durch!
'wenn wertstr = 0 ist dann wird nachgesehen, in welchem Digit (Stelle) wir uns befinden.
'wenn Digit = 0 -also die ganz linke Stelle- dann auf jeden Fall Portc.1 = 0 (Transistor der Stelle) abschalten
'Digit0 = 0 -> ist nur ein Merker für die folgenden Stellen d.h.

'wenn wertstr=0 dann fragen ob Digit=1 (also 2te Stelle von links) UND der Merker Digit0=0
'dann Transistor abschalten und weiteren Merker für diese Stelle setzen

'ZehnTausenderstelle
If Val(wertstr) = 0 Then 'Führende Null wegblenden
If Wert => 0 Then 'Wert muss = > 0 sein wegem negativen Vorzeichen
If Digit = 0 Then : Portc.1 = 0 : Digit_aus = 0 'C.1=Digit Transistor
End If
End If
Else
Digit_aus = 1
End If
'Tausenderstelle
If Val(wertstr) = 0 Then 'Führende Null wegblenden
If Digit = 1 And Digit_aus = 0 Then : Portc.2 = 0 : Digit_aus = 0 'C.2=Digit Transistor
End If
Else
Digit_aus = 1
End If
'Hunderterstelle
If Val(wertstr) = 0 Then 'Führende Null wegblenden
If Digit = 2 And Digit_aus = 0 Then : Portc.3 = 0 : Digit_aus = 0 'C.3=Digit Transistor
End If
Else
Digit_aus = 1
End If

''ENTFERNT WEIL MIT KOMMASTELLE UND DANN MUSS IN DER LETZTEN STELLE NE NULL STEHEN UND DARF NICHT AUSGEBLENDET WERDEN!!!
''Zehnerstelle
'If Val(wertstr) = 0 Then 'Führende Null wegblenden
' If Digit = 3 And Digit_aus = 0 Then : Portc.4 = 0 : Digit_aus = 0 'C.4=Digit Transistor
' End If
' Else
' Digit_aus = 1
'End If

'Dieser Teil erledigt die Wandlung in 7 Segment Code

'Für Anzeigen mit gemeinsamer Anode
Select Case Val(wertstr)

Case 0 : Portb = 126 'NULL
Case 1 : Portb = 12 'EINS
Case 2 : Portb = 182 'ZWEI
Case 3 : Portb = 158 'DREI
Case 4 : Portb = 204 'VIER
Case 5 : Portb = 218 'FÜNF
Case 6 : Portb = 250 'SECHS
Case 7 : Portb = 14 'SIEBEN
Case 8 : Portb = 254 'ACHT
Case 9 : Portb = 222 'NEUN
Case " " : Portb = 0
'Case Else : Portb = 128 'mittleres Segment
Case Else : Portb = 226 '"F"
End Select

'Minusvorzeichen
If Digit = 0 And Negativ = 1 Then
Portb = 128 'mittleres Segment
End If




'Komma setzen
'If Portc = 2 Then Portb.0 = 1 '4 Kommastellen
'If Portc = 4 Then Portb.0 = 1 '3 Kommastellen
'If Portc = 8 Then Portb.0 = 1 '2 Kommastellen
If Portc = 16 Then Portb.0 = 1 '1 Kommastelle


'negatives Vorzeichen setzen
If Portc = 2 Then 'wenn Pin gem. Anode ganz linke Stelle gesetzt
If Wert < 0 Then 'wenn Wert kleiner 0
Portb = 128 'Binär 1000 0000 -> Dezimal = 128 (nur Segment G)
End If
End If


'-------------------------------------------------------------------------------
Anzeige1:
'-------------------------------------------------------------------------------

Return


'-------------------------------------------------------------------------------
Anzeige2:
'-------------------------------------------------------------------------------
Return


'-------------------------------------------------------------------------------
Anzeige3:
'-------------------------------------------------------------------------------

Return

TobiasBlome
21.08.2008, 19:41
Hallo linux_80,

ich habe jetzt Version 1.11.9.2 installiert und habe NUR die Zeile: Case " " : Portb = 0
eingefügt und schon kommt der Fehler.

Kannst du bitte den Code mal bei die compilieren und mir sagen ob es geht?

Tobias



'-------------------------------------------------------------------------------

$regfile = "m8def.dat" 'AT-Mega8
$crystal = 8000000 'Quarz: 8 MHz
$baud = 9600 'Baudrate der UART: 9600 Baud
'-------------------------------------------------------------------------------
'Konfiguration Ein- / Ausgänge
Ddrb = &B11111111 '1 Ausgang, 0 Eingang => Pin PB7-0 als Ausgang
Ddrc = &B1111110 '1 Ausgang, 0 Eingang => Pin PC6-1 als Ausgang; 0 als Eingang
Ddrd = &B11110001 '1 Ausgang, 0 Eingang => Pin PD7-4,0 als Ausgang; 1-3 als Eingang

'-------------------------------------------------------------------------------
'Konfiguration LCD
Config Lcd = 16 * 2
Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.0 , Rs = Portc.6
Cursor Off Noblink
'-------------------------------------------------------------------------------
'Konfiguration ADC
Config Adc = Single , Prescaler = Auto , Reference = Avcc

'-------------------------------------------------------------------------------
'Konfiguration Timer0
Config Timer0 = Timer , Prescale = 1024
On Timer0 Timer0_isr
Const Timervorgabe0 = 230 '312 mal / Sekunde!!!
Enable Timer0
Enable Interrupts


'-------------------------------------------------------------------------------
'Konfiguration Timer1
Config Timer1 = Timer , Prescale = 256
On Timer1 Timer1_isr
Const Timervorgabe1 = 55118 '3 mal / Sekunde!!!
Enable Timer1
Enable Interrupts


'-------------------------------------------------------------------------------
'Variablen Anzeige:
Dim Wert As Long ' (-2147483648 bis 2147483647)
Dim Wert_pos As Word 'gewandelter wert
Dim Negativ As Bit 'Merker = 1 wnn Wert negativ!

' variablen für die display routine
Dim Wertstr As String * 5
Dim Y As Byte
Dim Tempbyte As Byte
' Variable für Digitansteuerung
Dim Digit As Byte
'Anzeige im Ganzen
Dim Fivedigitdisplay As String * 5
Dim Umdreh As Byte

'führende Nullen entfernen
Dim Digit_aus As Bit 'Merker =0 wenn Stelle =0



'ADC
Dim Analog_in0 As Long 'Word '=0-1023 vom Analogeingang
Dim Pro1 As Integer
Dim Pro2 As Single
Dim Pro3 As Integer
Dim Proz_anzeige As Byte


'Variablen LCD
Dim Ani_1 As Integer 'Zähler für Startannimation LCD
Dim Ende As Word 'zum Animation beenden


'Variablen Taster
Dim S1 As Bit 'Schalter 1
Dim S2 As Bit 'Schalter 2
Dim S2_m As Bit
Dim S3 As Bit 'Schalter 3
Dim S3_m As Bit 'Schalter 3 MERKER
Dim Taste_s1 As Word

'Programmverteilung über Timer0
Dim Zeit As Word 'wird 312 mal / Sekunde mit 1 addiert


'Variablen zum testen......
Dim Test2 As Integer 'zum hochzählen zum testen
Dim Test As Integer


'-------------------------------------------------------------------------------
'Annimation LCD


Goto Sprung

Do
Cls


For Ani_1 = 16 To 1 Step -1 'Von 1 bis 16 wird gezählt
Locate 1 , Ani_1 'Die entsprechende Position im Display anwählen.
Lcd "> TOBIAS BLOME <"
Waitms 250
Next

Locate 2 , 1
Lcd "BI - EMR 10/2008"
Waitms 500
Locate 2 , 1
Lcd " "
Waitms 500
Locate 2 , 1
Lcd "BI - EMR 10/2008"
Waitms 500
Locate 2 , 1
Lcd " "
Waitms 500
Locate 2 , 1
Lcd "BI - EMR 10/2008"
Wait 3



Loop Until Ende => 1

Sprung:
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'Setzen:

Digit_aus = 0

'alle Segmente aus
Portb = 0
Digit = 0


Test2 = 9900

Start Adc



Do





'---Programm aufteilen---
If Zeit => 150 Then 'also eine halbe Sekunde
Zeit = 0 'Zeit zurücksetzen
End If







'---ENDE Programmaufteilung---


'zum testen um etwas zu "sehen"
' Incr Test

' If Test = 10 Then
' Test = 0
' Incr Test2
' End If

' If Test2 > 99999 Then
' Test2 = 0
' End If

Loop


'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'Sprungmarken
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------


'-------------------------------------------------------------------------------
Timer0_isr: 'Timer1-Interruptroutine (312 x pro Sekunde)
'-------------------------------------------------------------------------------
Timer0 = Timervorgabe0

Gosub 7seganzeige 'Routine für 7 Segmentanzeige

Incr Zeit 'Zeitgeber


If S1 = 1 Then 'soll nur hochgezählt werden, wenn Taste links gedrückt
Incr Taste_s1 'wenn taste lange gedrückt soll etwas passieren (LCD "e" wechsel)
Else
Taste_s1 = 0
End If

Return

'-------------------------------------------------------------------------------
Timer1_isr: 'Timer1-Interruptroutine (3 x pro Sekunde)
'-------------------------------------------------------------------------------
Timer1 = Timervorgabe1

Analog_in0 = Getadc(0) 'Analog in Variable schreiben

Wert = Analog_in0 - 500 'Wert für Anzeige

If Wert < 0 Then 'wenn wert negativ
Wert_pos = Wert * -1
Negativ = 1
Else
Wert_pos = Wert
Negativ = 0
End If


'Print "Digit0: " ; Digit0
'Print "Digit1: " ; Digit1
'Print "Digit2: " ; Digit2
'Print "Digit3: " ; Digit3


Return

'-------------------------------------------------------------------------------
Analog:
'Analogeingänge Auslesen:
'-------------------------------------------------------------------------------

'Analog_in0 = Getadc(0) 'Analog in Variable schreiben
' Wert = Analog_in0 'Wert für Anzeige
' Pro1 = Analog_in0 - 204 'Prozent1Wert analog 204-1005 also -204 = 0-801
' Pro2 = Pro1 * 0.12484 'Rechnen: 100% / max(801) = 0.12484
' Pro3 = Round(pro2)

' If Pro3 > 100 Then 'damit keine größenren Werte als 100% auf dem LCD stehen
' Pro3 = 100
' End If
'
' If Pro3 < 0 Or Pro3 > 110 Then 'wenn errechneter %Wert falsch (kleiner 0 oder größer 110 dann immer 0 (110 wegen 4-20mA Ungenauigkeit)
' Proz_anzeige = 0
' Else
' Proz_anzeige = Pro3
' End If



'-------------------------------------------------------------------------------
7seganzeige:
' Code 7 Segmentanzeige:
'-------------------------------------------------------------------------------



'Formatiere das Display
Wertstr = Str(wert_pos)
Fivedigitdisplay = Format(wertstr , "00000") 'Nullen geben die Anzahl der Stellen an, damit die Stellen richtig gesetzt werden


' jeder Lauf durch die Hauptschleife zeigt ein anderes Digit
Incr Digit
'Waitms 6 'Zeit für die Anzeige (je länger wait desto mehr flackert es)
Portb = 0 'Ghosting vermeiden
If Digit = 5 Then 'mache das , bis 5 erreicht ist
Digit = 0

End If

' addiere 1 zum Digitcounter, weil MID 1-basiert ist
Y = Digit + 1
' und hol das Digit, das wir brauchen
Wertstr = Mid(fivedigitdisplay , Y , 1)


'Anzeige auswählen
Tempbyte = 2 ^ Digit 'Tempbyte = 1,2,4,8,16

'Digitansteuerung auf portC: PC1-5
Umdreh = Tempbyte * 2 'Umdreh = 2,4,8,16,32
'Ansteuerung umdrehen für gemeinsame Anoden
Portc = Umdreh 'Port für die Stellen auswahl



'Führende Nullen entfernen:

'INFO:
'wertstr hat immer nur eine Ziffer und wechselt also nacheinander alle 5 Stellen durch!
'wenn wertstr = 0 ist dann wird nachgesehen, in welchem Digit (Stelle) wir uns befinden.
'wenn Digit = 0 -also die ganz linke Stelle- dann auf jeden Fall Portc.1 = 0 (Transistor der Stelle) abschalten
'Digit0 = 0 -> ist nur ein Merker für die folgenden Stellen d.h.

'wenn wertstr=0 dann fragen ob Digit=1 (also 2te Stelle von links) UND der Merker Digit0=0
'dann Transistor abschalten und weiteren Merker für diese Stelle setzen

'ZehnTausenderstelle
If Val(wertstr) = 0 Then 'Führende Null wegblenden
If Wert => 0 Then 'Wert muss = > 0 sein wegem negativen Vorzeichen
If Digit = 0 Then : Portc.1 = 0 : Digit_aus = 0 'C.1=Digit Transistor
End If
End If
Else
Digit_aus = 1
End If
'Tausenderstelle
If Val(wertstr) = 0 Then 'Führende Null wegblenden
If Digit = 1 And Digit_aus = 0 Then : Portc.2 = 0 : Digit_aus = 0 'C.2=Digit Transistor
End If
Else
Digit_aus = 1
End If
'Hunderterstelle
If Val(wertstr) = 0 Then 'Führende Null wegblenden
If Digit = 2 And Digit_aus = 0 Then : Portc.3 = 0 : Digit_aus = 0 'C.3=Digit Transistor
End If
Else
Digit_aus = 1
End If

''ENTFERNT WEIL MIT KOMMASTELLE UND DANN MUSS IN DER LETZTEN STELLE NE NULL STEHEN UND DARF NICHT AUSGEBLENDET WERDEN!!!
''Zehnerstelle
'If Val(wertstr) = 0 Then 'Führende Null wegblenden
' If Digit = 3 And Digit_aus = 0 Then : Portc.4 = 0 : Digit_aus = 0 'C.4=Digit Transistor
' End If
' Else
' Digit_aus = 1
'End If

'Dieser Teil erledigt die Wandlung in 7 Segment Code

'Für Anzeigen mit gemeinsamer Anode
Select Case Val(wertstr)

Case 0 : Portb = 126 'NULL
Case 1 : Portb = 12 'EINS
Case 2 : Portb = 182 'ZWEI
Case 3 : Portb = 158 'DREI
Case 4 : Portb = 204 'VIER
Case 5 : Portb = 218 'FÜNF
Case 6 : Portb = 250 'SECHS
Case 7 : Portb = 14 'SIEBEN
Case 8 : Portb = 254 'ACHT
Case 9 : Portb = 222 'NEUN
Case " " : Portb = 0
'Case Else : Portb = 128 'mittleres Segment
Case Else : Portb = 226 '"F"
End Select

'Minusvorzeichen
If Digit = 0 And Negativ = 1 Then
Portb = 128 'mittleres Segment
End If




'Komma setzen
'If Portc = 2 Then Portb.0 = 1 '4 Kommastellen
'If Portc = 4 Then Portb.0 = 1 '3 Kommastellen
'If Portc = 8 Then Portb.0 = 1 '2 Kommastellen
If Portc = 16 Then Portb.0 = 1 '1 Kommastelle


'negatives Vorzeichen setzen
If Portc = 2 Then 'wenn Pin gem. Anode ganz linke Stelle gesetzt
If Wert < 0 Then 'wenn Wert kleiner 0
Portb = 128 'Binär 1000 0000 -> Dezimal = 128 (nur Segment G)
End If
End If


'-------------------------------------------------------------------------------
Anzeige1:
'-------------------------------------------------------------------------------

Return


'-------------------------------------------------------------------------------
Anzeige2:
'-------------------------------------------------------------------------------
Return


'-------------------------------------------------------------------------------
Anzeige3:
'-------------------------------------------------------------------------------

Return

linux_80
21.08.2008, 23:48
Hi,

so gehts nicht, Du musst es so machen wie ich angefangen habe, nicht nur einfach die eine Zeile dazubauen !
Also bei allen Zeile die "" mit dazu, und das Val() bei Select weglassen, dann gehts.

TobiasBlome
22.08.2008, 18:50
Hi,
ja, nunn funktioniert es einwandfrei und der gesamt code ist viel kürzer dadurch, dass die Segmente einfach abgeschaltet werden :-) Der Code mit den negativen Zahlen funktioniert auch :-)

Aber eine Frage hab ich natürlich:

Welchen Bereich hat eine Single / Double Variable? von bis und wieviele kommastellen?
Der µC mach rundungsfehler: es müsste eigendlich 2,0488.... sein und in der Single steht wohl nur 2,05 obwohl ich das gar nicht gerundet habe....

Tobias

linux_80
22.08.2008, 19:32
Hi,

Zu Datentypen findet sich was in der Bascom-Hilfe:
http://avrhelp.mcselec.com/language_fundamentals.htm -> Data Types

Der AVR ist nur für Ganzzahlen ausgelegt, alles andere muss Softwaremässig gemacht werden, was die Programmgrösse schnell ansteigen lässt, was schlecht ist, wenn es um Performance geht.

TobiasBlome
22.08.2008, 21:00
Danke,
da steht zwar nichts von den Nachkommastellen aber dafür weiß ich nun wieviele Stellen die Variable hat.

Wie ich auf die Kommastellen gekommen bin:
Der Wert auf der Anzeige wird "falsch" angezeigt - zumindest wenn ich das mit Excel vergleiche: hab das nachgerechnet weil Excel einen glatten Wert errechnet hat (1111). Aber die Abweichung ist in Wirklichkeit MINIMAL! Excel sagt als Ergebnis 1111,0 und der µC hat 1110,99991. Anscheinend rechnet der µC "nur" mit 7nachkommastellen... Mal sehen, wenn der µC zu langsam wird rechne ich alles *1000 oder so um das Komma weg zubekommen (und weniger Leistung zu verschwenden)

Tobias

PS. hier noch mal der Komplette funktionierende Code falls jemand Interesse hat ;-)



'7 Segmentanzeige im multiplexbetrieb mit Analogeingang
' für die Anzeige wird ein kompletter Port (0-7 = 7Seg+DP) benötigt
' für Anzeigen mit gemeinsamer Anode
'
' Anschlüsse:
' 7 Segmente = PB 0 - PB 7 (PB0=DP)
' 4 Anzeigen = PC 4 - PC 1 (4 Anzeigen)
' 5 Anzeigen = PC 5 - PC 1 (5 Anzeigen) PC5 = Einerstelle ganz rechts!!!!
'
'
'-------------------------------------------------------------------------------

$regfile = "m8def.dat" 'AT-Mega8
$crystal = 8000000 'Quarz: 8 MHz
'-------------------------------------------------------------------------------
'Konfiguration Ein- / Ausgänge
Ddrb = &B11111111 '1 Ausgang, 0 Eingang => Pin PB7-0 als Ausgang
Ddrc = &B1111110 '1 Ausgang, 0 Eingang => Pin PC6-1 als Ausgang; 0 als Eingang
Ddrd = &B11110001 '1 Ausgang, 0 Eingang => Pin PD7-4,0 als Ausgang; 1-3 als Eingang

'-------------------------------------------------------------------------------
'Konfiguration LCD
Config Lcd = 16 * 2
Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.0 , Rs = Portc.6
Cursor Off Noblink
'-------------------------------------------------------------------------------
'Konfiguration ADC
Config Adc = Single , Prescaler = Auto , Reference = Avcc

'-------------------------------------------------------------------------------
'Konfiguration Timer0
Config Timer0 = Timer , Prescale = 1024
On Timer0 Timer0_isr
Const Timervorgabe0 = 245 '230 '312 mal / Sekunde!!!
Enable Timer0
Enable Interrupts


'-------------------------------------------------------------------------------
'Konfiguration Timer1
Config Timer1 = Timer , Prescale = 256
On Timer1 Timer1_isr
Const Timervorgabe1 = 55118 '3 mal / Sekunde!!!
Enable Timer1
Enable Interrupts


'-------------------------------------------------------------------------------
'Variablen Anzeige:
Dim Anfangswert As Long 'Anfangswert vom Benutzer
Dim Endwert As Long 'Endwert vom Benutzer
Dim Differenz As Long 'Endwert - Anfangswert
Dim Zergebnis_1 As Single 'Zwischenergebnis 1
Dim Zergebnis_2 As Single 'Zwischenergebnis 2
Dim Zergebnis_3 As Single 'Zwischenergebnis 2

Dim Wert As Long ' (-2147483648 bis 2147483647)
Dim Wert_pos As Long 'gewandelter wert
Dim Negativ As Bit 'Merker = 1 wnn Wert negativ!

' variablen für die display routine
Dim Wertstr As String * 5
Dim Y As Byte
Dim Tempbyte As Byte
' Variable für Digitansteuerung
Dim Digit As Byte
'Anzeige im Ganzen
Dim Fivedigitdisplay As String * 5


'führende Nullen entfernen
Dim Digit_aus As Bit 'Merker =0 wenn Stelle =0



'ADC
Dim Analog_in0 As Word 'Word '=0-1023 vom Analogeingang
Dim Pro1 As Integer
Dim Pro2 As Single
Dim Pro3 As Integer
Dim Proz_anzeige As Byte


'Variablen LCD
Dim Ani_1 As Integer 'Zähler für Startannimation LCD
Dim Ende As Word 'zum Animation beenden


'Variablen Taster
Dim S1 As Bit 'Schalter 1
Dim S2 As Bit 'Schalter 2
Dim S2_m As Bit
Dim S3 As Bit 'Schalter 3
Dim S3_m As Bit 'Schalter 3 MERKER
Dim Taste_s1 As Word

'Programmverteilung über Timer0
Dim Zeit As Word 'wird 312 mal / Sekunde mit 1 addiert


'Variablen zum testen......
Dim Test2 As Integer 'zum hochzählen zum testen
Dim Test As Integer


'-------------------------------------------------------------------------------
'Annimation LCD


Goto Sprung

Do
Cls


For Ani_1 = 16 To 1 Step -1 'Von 1 bis 16 wird gezählt
Locate 1 , Ani_1 'Die entsprechende Position im Display anwählen.
Lcd "> TOBIAS BLOME <"
Waitms 250
Next

Locate 2 , 1
Lcd "BI - EMR 10/2008"
Waitms 500
Locate 2 , 1
Lcd " "
Waitms 500
Locate 2 , 1
Lcd "BI - EMR 10/2008"
Waitms 500
Locate 2 , 1
Lcd " "
Waitms 500
Locate 2 , 1
Lcd "BI - EMR 10/2008"
Wait 3



Loop Until Ende => 1

Sprung:
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'Setzen:

Digit_aus = 0

'alle Segmente aus
Portb = 0
Digit = 0

'Benutzerangaben:
Anfangswert = -987 'Anfangswert vom Benutzer
Endwert = 1111 'Endwert vom Benutzer



Start Adc



Do





'---Programm aufteilen---
If Zeit => 150 Then 'also eine halbe Sekunde
Zeit = 0 'Zeit zurücksetzen
End If







'---ENDE Programmaufteilung---




Loop


'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'Sprungmarken
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------


'-------------------------------------------------------------------------------
Timer0_isr: 'Timer1-Interruptroutine (312 x pro Sekunde)
'-------------------------------------------------------------------------------
Timer0 = Timervorgabe0

Gosub 7seganzeige 'Routine für 7 Segmentanzeige

Incr Zeit 'Zeitgeber


If S1 = 0 Then 'soll nur hochgezählt werden, wenn Taste links gedrückt
Incr Taste_s1 'wenn taste lange gedrückt soll etwas passieren (LCD "e" wechsel)
Else
Taste_s1 = 0
End If

Return

'-------------------------------------------------------------------------------
Timer1_isr: 'Timer1-Interruptroutine (3 x pro Sekunde)
'-------------------------------------------------------------------------------
Timer1 = Timervorgabe1

Gosub Analog 'gosub springt zurück!





Return

'-------------------------------------------------------------------------------
Analog:
'Analogeingänge Auslesen:
'-------------------------------------------------------------------------------

Analog_in0 = Getadc(0) 'Analog in Variable schreiben

'Analogwert umrechnen: FORMEL = Anfangswert+(Analogeingang*((Endwert-Anfangswert)/1023))



Differenz = Endwert - Anfangswert
Zergebnis_1 = Differenz / 1023
Zergebnis_2 = Analog_in0 * Zergebnis_1
Zergebnis_3 = Anfangswert + Zergebnis_2
Wert = Zergebnis_3 * 10 'damit bei einer Kommastelle auch eine RICHTIGE Kommastelle ist!





If Wert < 0 Then 'wenn wert negativ
Wert_pos = Wert * -1
Negativ = 1
Else
Wert_pos = Wert
Negativ = 0
End If

Return


'-------------------------------------------------------------------------------
7seganzeige:
' Code 7 Segmentanzeige:
'-------------------------------------------------------------------------------



'Formatiere das Display
Wertstr = Str(wert_pos)
Fivedigitdisplay = Format(wertstr , " 00") 'Nullen geben die Anzahl der Stellen an, damit die Stellen richtig gesetzt werden


' jeder Lauf durch die Hauptschleife zeigt ein anderes Digit
Incr Digit

Portb = 0 'Ghosting vermeiden
If Digit = 5 Then 'mache das , bis 5 erreicht ist
Digit = 0

End If

' addiere 1 zum Digitcounter, weil MID 1-basiert ist
Y = Digit + 1
' und hol das Digit, das wir brauchen
Wertstr = Mid(fivedigitdisplay , Y , 1)


'Anzeige auswählen
Tempbyte = 2 ^ Digit 'Tempbyte = 1,2,4,8,16

'Digitansteuerung auf portC: PC1-5
Portc = Tempbyte * 2 'Umdreh = 2,4,8,16,32




'Führende Nullen entfernen:




'Dieser Teil erledigt die Wandlung in 7 Segment Code

'Für Anzeigen mit gemeinsamer Anode
Select Case Wertstr

Case "0" : Portb = 126 'NULL
Case "1" : Portb = 12 'EINS
Case "2" : Portb = 182 'ZWEI
Case "3" : Portb = 158 'DREI
Case "4" : Portb = 204 'VIER
Case "5" : Portb = 218 'FÜNF
Case "6" : Portb = 250 'SECHS
Case "7" : Portb = 14 'SIEBEN
Case "8" : Portb = 254 'ACHT
Case "9" : Portb = 222 'NEUN
Case " " : Portb = 0 'nichts - kein Segment
'Case Else : Portb = 128 'mittleres Segment
Case Else : Portb = 226 '"F"
End Select





'Komma setzen
'If Portc = 2 Then Portb.0 = 1 '4 Kommastellen
'If Portc = 4 Then Portb.0 = 1 '3 Kommastellen
'If Portc = 8 Then Portb.0 = 1 '2 Kommastellen
If Portc = 16 Then Portb.0 = 1 '1 Kommastelle


'negatives Vorzeichen setzen / Minus
If Portc = 2 Then 'wenn Pin gem. Anode ganz linke Stelle gesetzt
If Wert < 0 Then 'wenn Wert kleiner 0
Portb = 128 'Binär 1000 0000 -> Dezimal = 128 (nur Segment G)
End If
End If

linux_80
23.08.2008, 10:23
Nachkommastellen alleine kann man schlecht angeben, das hängt davon ab wieviel Vorkommastellen man schon verbraucht hat.

TobiasBlome
23.08.2008, 16:04
und was heiß das genau, wenn ich schon 6 vorkommastellen der Single "verbraucht" habe?