Forum: Mikrocontroller und Digitale Elektronik ADC mit Schieberegister und LEDs


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Max S. (masch_bau)


Angehängte Dateien:

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
}

: Bearbeitet durch Moderator
von Sebastian R. (sebastian_r569)


Lesenswert?

Max S. schrieb:
> ich bräuchte dringend bitte Hilfe.

Und wobei jetzt genau?
Was ist deine konkrete Frage bei deiner Hausaufgabe?

von Max S. (masch_bau)


Angehängte Dateien:

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

von Steve van de Grens (roehrmond)


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.

: Bearbeitet durch User
von Obelix X. (obelix)


Lesenswert?

Was geht denn nicht?
-Analogwert einlesen
-Schieberegister ansteuern
-LED leuchten?

von Wastl (hartundweichware)


Lesenswert?

Max S. schrieb:
> Bauen und programmieren Sie die vorangegangene Schaltung so um

Welche Schaltung? Sollen wir hellsehen?

Was an diesem einfachen Satz

>> Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

verstehst du nicht?

von Michael (Firma: HW Entwicklung) (mkn)


Lesenswert?

Max S. schrieb:
> Es funktioniert nicht
Das Einfügen des Code mit
1
 C-Code
?

Das liefern einer verständlichen Beschreibung was nicht geht?
Oder hapert es schon dabei die Aufgabe in einzelne Schritte 
runterzubrechen und die einzeln zu testen?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

Max S. schrieb:
> ich bräuchte dringend bitte Hilfe.
Bitte Bedienungsanleitung beachten...

von Obelix X. (obelix)


Lesenswert?

1
char dispCode[8]= {0b00000001,0b00000010,0b00000100,0b00001000,0b00010000,0b00100000,0b01000000,0b10000000};
2
3
x = dispCode[i]

vs
1
x = 1<<i

von Obelix X. (obelix)


Lesenswert?

Max S. schrieb:
> void serTakt (); // SChieberegister
> void schreibTakt (); // SChieberegister

Könnte man nicht auch die SPI Schnittstelle verwenden?

von Steve van de Grens (roehrmond)


Lesenswert?

Obelix X. schrieb:
> Könnte man nicht auch die SPI Schnittstelle verwenden?

Sicher, aber das ist wohl nicht Teil der Aufgabe.

: Bearbeitet durch User
von Stefan S. (chiefeinherjar)


Lesenswert?

Steve van de Grens schrieb:
> Obelix X. schrieb:
>> Könnte man nicht auch die SPI Schnittstelle verwenden?
>
> Sicher, aber das ist wohl nicht Teil der Aufgabe.

Woher liest du das? Ich tippe eher darauf, dass der TO nicht weiß, wie 
er die SPI-Schnittstelle konfigurieren soll.

von Steve van de Grens (roehrmond)


Lesenswert?

Stefan S. schrieb:
> Woher liest du das?

In der angehängten Datei ist die Kommunikation mit dem Schieberegister 
bereits vorgegeben.

von Ron-Hardy G. (ron-hardy)


Lesenswert?

Max S. schrieb:
> while (1) {
>
>         displayWert=resultADC() / 512;
>
>         for (int i=0; i<8;i++){
>             digDisplay(i);
>             __delay_ms(1000);
>             }
>
>          }

Sieht für mich nach einem Lauflicht aus. Der displayWert wird doch 
garnicht benutzt?

von Udo S. (urschmitt)


Lesenswert?

Ron-Hardy G. schrieb:
> Sieht für mich nach einem Lauflicht aus. Der displayWert wird doch
> garnicht benutzt?

Deshalb die Aufgabe:
Beitrag "Re: ADC mit Schieberegister und LEDs"

von Wastl (hartundweichware)


Lesenswert?

Obelix X. schrieb:
> die SPI Schnittstelle

Also die Serial Peripheral Interface Schnittstelle .....

weisser Schimmel, tote Leiche, LCD Display, ADC Converter ....

von Obelix X. (obelix)


Lesenswert?

Max S. schrieb:
> for (int i=0;i<=8;i++){
>    pow(2.0, (float) i);
>    dezResult=dezResult + ((resultLOWBit >> i) & 0x01) * (1<<i);
> }

Echt Lustig der Code ;-D

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


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.

: Bearbeitet durch Moderator
von Gustl B. (gustl_b)


Lesenswert?

Das Schieberegister braucht einen Schreibtakt je Bit. Und danach einen 
Latch-Takt damit die Bits ausgegeben werden an den Pins.

Also brauchst du eine Schleife:
1
For i in range(8):
2
   Datenpin = bits(i)
3
   Srclk = 1
4
   Srclk = 0
5
6
Lclk = 1
7
Lclk = 0

: Bearbeitet durch User
von Obelix X. (obelix)


Lesenswert?

Lothar M. schrieb:
> Denk erst mal nach, vor du vogelwild drauflosprogrammierst.

Ich denke, da wurde nicht programmiert, sondern nur kopiert.

von Michi S. (mista_s)


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.

von Peter D. (peda)


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.

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.