ADC mit Schieberegister und LEDs

OP #7573368
Lesenswert?

Hallo zusammen,

ich bräuchte dringend bitte Hilfe.

Ich soll 8 LEDs mit einem Schieberegister (74HC595) verwenden. Anschließend sollen die LEDs die Stellung des Potentiometer angeben.

Programm: MPLAB X IDE; C-Programmiersprache; PIC 16F18446; Compiler: XC8

Header Datei:

1
#ifndef Schieberegister
2
#define  Schieberegister
3

4
#define serPin LATAbits.LATA1
5
#define srclkPin LATAbits.LATA4
6
#define rclkPin LATAbits.LATA5
7

8
# define LED_1 0b00000001
9
# define LED_2 0b00000010
10
# define LED_3 0b00000100
11
# define LED_4 0b00001000
12
# define LED_5 0b00010000
13
# define LED_6 0b00100000
14
# define LED_7 0b01000000
15
# define LED_8 0b10000000
16

17

18
#include <xc.h> // include processor files - each processor file is guarded.  
19

20
 void digDisplay();
21

22
 char dispCode[8]= {0b00000001,0b00000010,0b00000100,0b00001000,0b00010000,0b00100000,0b01000000,0b10000000};
23

24

25
void serTakt (); // SChieberegister
26

27
void schreibTakt (); // SChieberegister
28

29
#endif
30

31
Schieberegister.c:
32
#include "Schieberegister.h"
33
#include "16F18446_Init.h"
34
#include "16F18446_Konfiguration.h"
35

36
//Variable zur Speicherung der Segmentcodierung für die übergene Ziffer
37

38
int displayZiffer;
39

40
void digDisplay (int dezZiffer){
41
    displayZiffer=dispCode[dezZiffer];
42
        
43
        for (int i=0; i<8;i++) {
44
            serPin=(displayZiffer>> i) & (0x01);
45
            serTakt();
46
        }
47
        schreibTakt ();
48
        return;
49
    }
50
    
51
 // Erzeugung einer positiven Flanke am Pin SRCLK
52

53
void serTakt (void) {
54
    srclkPin=0;
55
    __delay_us(1);
56
    srclkPin=1;
57
    __delay_us(1);
58
    srclkPin=0;
59
    __delay_us(1);
60
    return;
61
}
62

63
// Erzeugung einer positiven Flanke am Pin RCLK
64
void schreibTakt (void) {
65
    rclkPin=0;
66
    __delay_us(1);
67
    rclkPin=1;
68
    __delay_us(1);
69
    rclkPin=0;
70
    __delay_us(1);
71
    
72
    return;
73
}
74
main.c:
75
#include "16F18446_Init.h"
76
#include "Schieberegister.h"
77

78
void initADC(void);
79
int resultADC(void);
80

81
int displayWert;
82

83
void main(void) {
84
    
85
    TRISA= 0x0;
86
    TRISB=0x00;
87
    initADC();
88
    
89
    
90
    while (1) {
91
        
92
        displayWert=resultADC() / 512;
93
        
94
        for (int i=0; i<8;i++){
95
            digDisplay(i);
96
            __delay_ms(1000);
97
            }
98
            
99
         }
100
    return;
101
}
102

103
// AD Wandler:
104
void initADC () {
105
    TRISBbits.TRISB4=1;
106
    ANSELBbits.ANSB4=1;
107
    ADPCH=0x4;
108
    
109
    ADREFbits.PREF=0b00;
110
    ADREFbits.NREF=0;
111
    
112
    ADCON0bits.ON=1;
113
    return;
114
}
115

116
int resultADC() {
117
    uint8_t resultLOWBit;
118
    uint8_t resultHIGHBit;
119
    
120
    int dezResult=0;
121
    
122
    ADCON0bits.GO=1;
123
    while (ADCON0bits.GO);
124
    
125
    resultLOWBit=ADRESL;
126
    resultHIGHBit=ADRESH;
127
    
128
    for (int i=0;i<=8;i++){
129
         pow(2.0, (float) i);
130
        dezResult=dezResult + ((resultLOWBit >> i) & 0x01) * (1<<i);
131
    }
132
    
133
   
134
    
135
    return dezResult;
136
}
Angehängte Dateien:
OP #7573396
Lesenswert?

Es funktioniert nicht und ich finde meinen Fehler nicht

das ist die direkte Aufgabenstellung "Bauen und programmieren Sie die vorangegangene Schaltung so um, dass eine Reihe von 8 LEDs die Stellung des Potentiometers angibt (linker Anschlag ! keine LED leuchtet, rechter Anschlag ! alle LEDs leuchten). Nutzen Sie zur Umsetzung dieser Schaltung das Schieberegister 74HC595

Angehängte Dateien:
Gast #7573400
Lesenswert?

Trenne das ganze auf.

Steuer zuerst mal die LED leiste mit einem festen Wert an, dann mit einem anderen, um zu testen, ob dieser Teil funktioniert.

Frage den ADC und prüfe das Ergebnis mit einem Debugger oder gebe es seriell aus.

Wenn beide Teile einzeln funktionieren, bringe sie wieder zusammen und schau dir ganz genau die Schnittstellen dazwischen an.

Viele serielle Ausgaben zwischendurch können dabei sehr hilfreich sein, falls du keinen Debugger hast.

Moderator (Firma: Titel) Persönliche Seite #7573503
Lesenswert?

Max S. schrieb:

ich bräuchte dringend bitte Hilfe.

Denk erst mal nach, vor du vogelwild drauflosprogrammierst.

Max S. schrieb:

Bauen und programmieren Sie die vorangegangene Schaltung so um, dass eine Reihe von 8 LEDs die Stellung des Potentiometers angibt linker Anschlag = keine LED leuchtet

rechter Anschlag = alle LEDs leuchten

Damit hast du also 9 Zustände:

1
0  ........
2
1  *.......
3
2  **......
4
3  ***.....
5
4  ****....
6
5  *****...
7
6  ******..
8
7  *******.
9
8  ********

Und jetzt musst du zuallererst mal den ADC-Wert von z.B. 0..1023 (bei einem 10-Bit-Wandler ) auf 0..8 abbilden. Dazu brauchst du Mathe, 5. oder 6. Klasse, solltest du hinbekommen (ein Tipp: ADC-Wert/114 kommt in etwa hin).

Und wenn du dann die Zahl von 0..8 hast, dann dürfte es einfach sein, die passende Anzahl Einsen aus dem Ausgang hinauszutakten.

War ja gar nicht so schwierig.

#7573909
Lesenswert?

Max S. schrieb:

Ich soll 8 LEDs mit einem Schieberegister (74HC595) verwenden.

Warum? Hausübung?

Max S. schrieb:

dass eine Reihe von 8 LEDs die Stellung des Potentiometers angibt

Wenn Dich die Stellung des Potis interessiert, dann solltest Du eventuell den Rückgabewert vom ADC auch irgendwie weiterverarbeiten, meinst Du nicht. Ich muß mich doch glatt korrigieren, Du dividierst ihn ja durch 512 (hat der PIC - ich kenne ihn nicht - einen 12 Bit ADC? Dann wär diese Rechnung wenigstens näher dran an richtig, als alles andere) und erst das Ergebnis läßt Du links liegen, aber das ist sowieso immer 0. (siehe unten)

Max S. schrieb:

rechter Anschlag ! alle LEDs leuchten

Dazu ist Dein Code schon mal nicht in der Lage; da wird nie mehr als eine LED leuchten können. (Umwandlungs-Tabelle mal scharf anschauen)

Max S. schrieb:

Es funktioniert nicht und ich finde meinen Fehler nicht

Es ist, wie man bereits erkennen kann, weit mehr als nur einer.

Wie gesagt, ich kenne den PIC nicht, hab also keine Ahnung, wie man z.B. seinen ADC ansprechen sollte, aber dafür finde ich in Deiner ADC-Lese-Funktion ein paar Ungereimtheiten:

*) resultLOWBit und resultHIGHBit - ich hoffe doch, der ADC hat ein paar mehr als nur 2 Bit? Sind zwar nur Namen, aber man sollte sich das Programmieren doch nicht noch komplizierter machen, als es eh schon ist, drum mein Tip: Ein Bit sollte ein Bit sein und ein Byte jedenfalls mehr als ein Bit haben (i.A. acht Stück, aber wenn ein Wertebereich kein vielfaches von 8 Bit verbraucht, dann kann das höchstwertige Byte auch mal weniger Bits beinhalten).

*) Nachdem Du Deine beiden Bits, die vermutlich eher Bytes sind (hoffentlich korrekt) von der HW abgeholt hast, wirds wieder etwas skuril: das LOWBit verschiebst Du bitweise in Deine Ergebnisvariable (außerdem schiebst Du gleich 9 Bits rüber, obwohl hier vermutlich nur acht vorhanden sind, klassischer off-by-one Fehler, hier aber egal), das könnte man durchaus mit einer einfachen Zuweisung etwas abkürzen, aber die Verschiebe-Schleife hast Du immerhin korrekt von irgendwo kopiert; trotzdem: such Dir doch qualitativ bessere Kopiervorlagen, das Internet ist voll davon.

*) Tja, und vor lauter Freude übers richtig kopiert haben, vergißt Du dann komplett, Dich auch Deines HIGHBits des Ergebnisses anzunehmen. Damit bleibt der höchstmögliche Rückgabewert halt leider auf das beschränkt, was sich in 8 Bit unterbringen läßt, also max. 255 - die Du dann in Deiner Hauptschleife gleich mal forsch in 512 Teile dividieren willst. (siehe oben)

Das werden jetzt sicher nicht alle Fehler gewesen sein, die Du in Deinem Code versteckt hast, aber damit hast Du zumindest mal ein paar Ansätze, wo noch etwas zu tun ist.

Was mir sonst noch aufgefallen ist: eine Flanke ist an sich immer ein Wechsel von LOW (0) zu HIGH (1) bzw. umgekehrt. Folglich könntest Du in Deinen beiden Takt-Routinen jeweils eine Pinwackelei einsparen, welche kannst Dir aussuchen, solange es nicht die mittlere ist; aber klar tut die eine µs dort auch nicht wirklich weh.

#7573934
Lesenswert?

Was erstmal zu klären ist, soll ein Binärwert angezeigt werden oder ein Balken. Für den Binärwert nimmst Du die obersten 8 Bit des ADC, für den Balken die obersten 3 Bits.

Und wie schon gesagt wurde, teste den Code funktionsweise und nicht als ganzen Haufen auf einmal.

Max S. schrieb:

ich bräuchte dringend bitte Hilfe.

Das ist natürlich eine super Fehlerbeschreibung, mit der jeder was anfangen kann.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren