Forum: Mikrocontroller und Digitale Elektronik Bascom: Variable aufteilen für 7-Segment Anzeigen


von Manu N. (avr-manu)


Lesenswert?

Hallo,
Ich steuere gerade 3 7-Segment Anzeigen an:
Ein Mega 8 steuert ein Schieberegister (74HC595) an, an dem
8x BC547A hängen. Desweiteren steuert der Prozessor einen ULN 2803,
der dafür zuständig ist, die Anzeigen mit gemeinsamer Kathode 
nacheinander auf GND zieht (Multiplexen).
Das funktioniert nun, die Anzeigen lassen sich alle steuern.

Nun zur Software:
-Programmiert wird in Bascom, Beispiele in C oder Assembler helfen mir 
nicht
-Das Multiplexen wird per Timer0 Interrupt erledigt
-Es gibt ein Abfrage, die im Interrupt die Zahlen (1-9) Binäre Werte 
umwandelt, passend für die Anzeigen, die dann ins Schieberegister 
geschoben werden.
Code:
1
Select Case Zahl(1)
2
   Case 0 : T1 = &B11101101
3
   Case 1 : T1 = &B10000001
4
   Case 2 : T1 = &B11001110
5
   Case 3 : T1 = &B01101110
6
   Case 4 : T1 = &B00101011
7
   Case 5 : T1 = &B01100111
8
   Case 6 : T1 = &B11100111
9
   Case 7 : T1 = &B00101101
10
   Case 8 : T1 = &B11101111
11
   Case 9 : T1 = &B01101111
12
13
End Select
14
15
16
Select Case Zahl(2)
17
   Case 0 : T2 = &B11101101
18
   Case 1 : T2 = &B10000001
19
   Case 2 : T2 = &B11001110
20
   Case 3 : T2 = &B01101110
21
   Case 4 : T2 = &B00101011
22
   Case 5 : T2 = &B01100111
23
   Case 6 : T2 = &B11100111
24
   Case 7 : T2 = &B00101101
25
   Case 8 : T2 = &B11101111
26
   Case 9 : T2 = &B01101111
27
28
End Select
29
30
31
32
Select Case Zahl(3)
33
   Case 0 : T3 = &B11101101
34
   Case 1 : T3 = &B10000001
35
   Case 2 : T3 = &B11001110
36
   Case 3 : T3 = &B01101110
37
   Case 4 : T3 = &B00101011
38
   Case 5 : T3 = &B01100111
39
   Case 6 : T3 = &B11100111
40
   Case 7 : T3 = &B00101101
41
   Case 8 : T3 = &B11101111
42
   Case 9 : T3 = &B01101111
43
44
End Select

Ich habe also drei Variabeln, die jeweil eine Stelle, von 1 bis 9, 
darstellen.

Ich will eine ganze Zahl auf dieser Anzeige ausgeben, die in einer 
anderen
Varialble gespeichert ist, z.B. 142.


Wie schaffe ich es nun, diese Zahl aufzuteilen,
also in die Stellen 1, 2 und 3 ?

Hier die erste Methode, die ich mir ausgedacht hatte:
-Als erstes wird die Zahl durch 100 geteilt
-Dann werden die Kommastellen ermittelt
-Und dann abgezogen
-Jetzt könnte die Zahl z.B. lauten: 2.0
-Um das komma "wegzubringen" runde ich noch

Hier wieder der Code:
(Mit Derklerationen)
1
$regfile = "m8def.dat"                                      'ATmega8-Deklarationen
2
$crystal = 1000000
3
$baud = 4800
4
5
Config Portc.5 = Output
6
Config Portc.4 = Output
7
Config Portc.3 = Output
8
Config Portc.2 = Output
9
Config Portd.5 = Output
10
Config Portd.6 = Output
11
Config Portb.7 = Output
12
13
Portb.0 = 1
14
Portd.7 = 1
15
16
Clock Alias Portc.5
17
Stout Alias Portc.4
18
Dat Alias Portc.3
19
20
Down Alias Pind.7
21
Up Alias Pinb.0
22
23
L1 Alias Portd.6
24
L2 Alias Portd.5
25
L3 Alias Portb.7
26
27
Clock = 0
28
Stout = 0
29
Dat = 0
30
31
32
Dim Zahl(3) As Integer
33
Dim Zanz As Integer
34
35
Dim K1 As Single
36
Dim K2 As Single
37
Dim K3 As Single
38
Dim Fr As Single
39
40
41
Dim T1 As Byte
42
Dim T2 As Byte
43
Dim T3 As Byte
44
Dim A As Byte
45
46
On Timer0 Isr
47
Config Timer0 = Timer , Prescale = 8
48
Enable Timer0
49
Enable Interrupts
50
51
Zanz = 123
52
53
Do
54
55
K1 = Zanz / 100
56
Fr = Frac(k1)
57
K1 = K1 - Fr
58
T1 = Round(k1)
59
60
61
K2 = Zanz / 10
62
Fr = Frac(k2)
63
K2 = K2 - Fr
64
T2 = Round(k2)
65
66
67
Print "k1:" ; K1
68
Print "k2:" ; K2
69
Print "  "
70
Print "t1:" ; T1
71
Print "t2:" ; T2
72
Print "  "
73
Print "Fr:" ; Fr
74
75
76
Loop

Aber es funktioniert nicht.

Kennt jemand einen andere Methode,
so etwas "umzuwandeln"?

Oder findet jemand den Fehler in meinem Code ?
Falls nötig kann ich auch den ganzen Code posten. (oder noch mehr zur 
Hardware?!)



Vielen Dank schonmal

PS: Ich bin in ca. 45 Minuten wieder da, gespannt auf eure Antworten.

von Volker S. (volkerschulz)


Lesenswert?

Ist zwar nicht Bascom, aber schau Dir doch das mal an:

http://www.mikrocontroller.net/articles/AVR-Tutorial:_LCD#Zahlen_ausgeben

Alleine durch die Kommentare kommst Du ja schon drauf, was gemacht wird. 
;)


Volker

von spess53 (Gast)


Lesenswert?

Hi

Bascom kennt doch den Modulo-Operator:

z.B. 142

142/100     = 1  ->erste Stelle
142 MOD 100 = 42 ->Rest
42 / 10     = 4  ->zweite Stelle
42 MOD 10   = 2  ->dritte Stelle

fertig.

MfG Spess

von Manu N. (avr-manu)


Lesenswert?

> 142 MOD 100 = 42 ->Rest

Und was mach ich mit dem Rest ?


Ich fange gleich mal an das zu Programmieren,
wobei ich die letztere  Methode für die einfacherere halte.


Danke an euch beide,
ichteste mal und melde mich nochmal.

von Volker S. (volkerschulz)


Lesenswert?

Manu N. schrieb:
>> 142 MOD 100 = 42 ->Rest
>
> Und was mach ich mit dem Rest ?

Der wird doch kurz danach MOD 10 genommen...


Volker

von spess53 (Gast)


Lesenswert?

Hi

>Und was mach ich mit dem Rest ?

Das ist der Rest von 142/100. Also deine Zehner- und Einerstellen.

MfG Spess

von Manu N. (avr-manu)


Lesenswert?

Hm,
weder die Bascom Hilfe noch die passende Fachliteratur
kennt den Befehl "mod".
Könntest du das noch mal etwas genauer erklären, ich stehe
glaub ich auf dem Schlauch.

Ansonsten probiere ich Methode Nr.1


Danke

von spess53 (Gast)


Lesenswert?

Hi

Auszug aus der Bascom-Hilfe:

Language Fundamentals ->Arithmetic

Modulo Arithmetic
Modulo arithmetic is denoted by the modulus operator MOD.
Modulo arithmetic provides the remainder, rather than the quotient, of 
an integer division.

Example: X = 10 \ 4 : remainder = 10 MOD 4

MfG Spess

von Volker S. (volkerschulz)


Lesenswert?

Manu N. schrieb:
> Hm,
> weder die Bascom Hilfe noch die passende Fachliteratur
> kennt den Befehl "mod".

MOD ist auch kein Befehl sondern ein Operator... Und laut Google gibt es 
den in Bascom. ;)


Volker


P.S.: Das Vorgehen in ASM ist auch nur der "Modulus zu Fuss"...

von spess53 (Gast)


Lesenswert?

Hi

Beispiel findest du in der Hilfe zum Befehl 'SET'.

MfG Spess

von Rolf I. (for_ro)


Lesenswert?

Manu N. schrieb:
> Select Case Zahl(1)
>    Case 0 : T1 = &B11101101
>    Case 1 : T1 = &B10000001
>    Case 2 : T1 = &B11001110
>    Case 3 : T1 = &B01101110
>    Case 4 : T1 = &B00101011
>    Case 5 : T1 = &B01100111
>    Case 6 : T1 = &B11100111
>    Case 7 : T1 = &B00101101
>    Case 8 : T1 = &B11101111
>    Case 9 : T1 = &B01101111
>
> End Select

Da multiplexen normalerweise etwas zeitkritisch ist, würde ich sowas 
nicht machen, besonders nicht 3 mal.
Im Falle der Zahl 9 muss er 10 Vergleiche ausführen und dann eine 
Zuweisung machen und zum End Select springen.
Wenn du noch 10 Byte im SRAM frei hast, würde ich die Werte in einem 
Array abspeichern.
Dim Ziffern(10) as Byte
Ziffern(1) = &B10000001
Ziffern(2) = &B11001110
...
Ziffern(10) = &B11101101

Dann kannst du mit

T1 = Ziffern(Zahl(1))
T2 = Ziffern(Zahl(2))
T3 = Ziffern(Zahl(3))

die ganze Arbeit der drei Select-Blöcke erledigen.
Wenn du jetzt genau hinsiehst, hat das aber einen kleinen Fehler. Die 0 
steht im 10 Element und nicht im 0-ten Element.
BASCOM startet die Indexe leider bei 1 und nicht bei 0. Aber es gibt 
einen Trick, wie man BASCOM 0-basierte Indexe beibringen kann. Und zwar 
so:

Dim Ziffern_0 As Byte
Dim Ziffern(9) As Byte

Ziffern_0 = &B11101101
Ziffern(1) = &B10000001
Ziffern(2) = &B11001110
...
Ziffern(9) = &B01101111

Wenn jetzt in Zahl(1) z.B. eine 0 steht, dann würde die Zuweisung

T1 = Ziffern(Zahl(1))

so aussehen

T1 = Ziffern(0)

Ziffern(0) ist zwar in BASCOM nicht erlaubt, wird aber in die Adresse im 
SRAM vor der Adresse von Ziffern(1) übersetzt. Also tatsächlich auf die 
Dummy Variable Ziffern_0, die die Segmente der Zahl 0 enthält.

Wenn man sich erst einmal daran gewöhnt hat, funktioniert dies ganz 
automatisch.

von Manu N. (avr-manu)


Lesenswert?

@  Rolf Im forum (for_ro) :
Später werde ich das mal ändern, aber im Moment funktioniert das so 
super.


Leider verstehe ich diese mod Geschichte immer noch nicht stöhn
Hier mal ein kleiner Versuch: (der nicht funzt ...)
1
Rest = Zanz / 100
2
Zahl(1) = Rest
3
4
Rest = Rest Mod 10
5
Zahl(2) = Rest
6
7
8
Rest = Rest Mod 1
9
Zahl(3) = Rest


Danke für eure Bemühungen ...

von Peter D. (peda)


Lesenswert?

Rolf Im forum schrieb:
> Ziffern(0) ist zwar in BASCOM nicht erlaubt, wird aber in die Adresse im
> SRAM vor der Adresse von Ziffern(1) übersetzt.

Solche häßlichen Tricks sollte man sich garnicht erst angewöhnen. Die 
werden mit Sicherheit mal Probleme machen und dann suchst Du Dich dumm 
und dämlich.

Mach eben ne Funktion draus und dann wird zum Argument noch 1 addiert. 
Fertig ist die Laube.

Du kannst aber auch das Select zu ner Funktion machen.
Ob Bascom die Tabelle oder das Select besser implementiert, kann man 
dann anhand der Codegröße vergleichen.


Peter

von Volker S. (volkerschulz)


Lesenswert?

Manu N. schrieb:
> Leider verstehe ich diese mod Geschichte immer noch nicht *stöhn*
> Hier mal ein kleiner Versuch: (der nicht funzt ...)
>
1
> Rest = Zanz / 100
2
> Zahl(1) = Rest
3
> 
4
> Rest = Rest Mod 10
5
> Zahl(2) = Rest
6
> 
7
> 
8
> Rest = Rest Mod 1
9
> Zahl(3) = Rest
10
>

Das ist ja auch nicht das von oben...
1
Zahl(1) = Zanz / 100
2
Rest = Zanz MOD 100 
3
4
...

Muesste es beginnen...


Volker

von spess53 (Gast)


Lesenswert?

Hi

>Leider verstehe ich diese mod Geschichte immer noch nicht stöhn
>Hier mal ein kleiner Versuch: (der nicht funzt ...)

>Rest = Zanz / 100
>Zahl(1) = Rest

>Rest = Rest Mod 10
>Zahl(2) = Rest

>Rest = Rest Mod 1
>Zahl(3) = Rest

Machs mal so:

Zahl(1) = Zanz / 100
Rest    = Zanz MOD 100

Zahl(2) = Rest/10
Zahl(3) = Rest MOD 10

Ich kann es nicht testen, weil ich nicht mit BASCOM programmiere.

MfG Spess

von MWS (Gast)


Lesenswert?

Die Segmentdaten würde man besser mit Data & Lookup holen, außerdem 
beginnt bei Lookup der erste Datensatz bei 0, da ist dann auch kein so 
ein Gebastel notwendig.
1
T1 = Lookup(Zahl(1) , 7Seg_data)
2
...
3
7Seg_data:
4
Data &B11101101
5
Data &B10000001
6
...

Und warum SRam verschwenden, wenn's eh' Konstanten sind, die man im 
Flash vorhalten kann ?

von Manu N. (avr-manu)


Lesenswert?

Yippi Yippi Yeah

Es funktioniert.
Nur mit einem Problem habe ich noch zu kämpfen:
Wenn die Zehnerstelle umschaltet flackert bzw. leuchtet eine eins kurz
an der Hunderterstelle. Wiso bloß?
Hab auch schonmal den Timer Prescaler verändert, kein Erfolg.

Hat da jemand ne Ahnung ?

von Manu N. (avr-manu)


Lesenswert?

Ah, jetzt ist der Spuk vorbei,
war nur n´ kleiner Bug im Programm.
Jetzt ist es Fehlerfrei.


Morgen werde ich noch das mit Lookup und Data Sachen einbauen.

Vielen Dank nochmal an alle die mir hier geholfen haben.
Manu

von Hannes L. (hannes)


Angehängte Dateien:

Lesenswert?

Im Anhang ist noch eine Variante, sie gehört zu dieser Bastelei:
http://www.hanneslux.de/avr/divers/pm24/index.html

> Und warum SRam verschwenden, wenn's eh' Konstanten sind, die man im
> Flash vorhalten kann ?

Weil z.B. die SRAM-Zugriffe schneller sind und genügend SRAM zur 
Verfügung steht. Und weil man (in ASM) mit nur einer 
Pointer-Adressierung auf mehrere Arrays (mit gleichem Index) zugreifen 
kann (LDD/STD), was sehr schnelle (also Interrupt-taugliche) Zugriffe 
auf mehrere Arrays ermöglicht.

...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.