Hallo, ich habe an einen ATtiny45 ein o.g. Schieberegister gehängt, um eine 7-Segment-Anzeige zu steuern. Ich lese am ADC eine Spannung ein und lasse mir die einzelnen Ziffern für Spannung (Vorkomma, Nachkomma) abwechselnd auf der 7Seg-Anzeige darstellen. Leider nur spinnt die Anzeige reichlich: einige LEDs werden nicht auf High gesetzt, so dass die Zeichen mitunter unleserlich sind. Ich habe schon: die Kabel gekürzt (auf 2cm), Pull-Down-Widerstände an die Eingänge am Schieber gelötet und jetzt sogar mit Kondensatoren (100pF) die Eingänge entstört. All diese Massnahmen haben aber nichts gebracht. Zeitweilig ging es recht gut, aber seit ich das Kabel gekürzt habe, treten wieder gehäuft Fehler auf. Nun mache ich das mit dem Programmieren von µC erst seit etwa 2 Wochen und habe noch nicht den Überblick. Hier ist einfach mal mein Programm. An den Shifter gehen die Daten in w2led. Ich weiss, dass hier nur einfach ein Datenbit gesetzt wird und dann einmal die Taktleitung an- und ausgeht. Prinzipiell funktioniert es ja schon mal und ich habe auch im Internet ein anderes Beispiel gefunden, in dem jemand das genau so gemacht hat. Aber: kann hier die Ursache für die geschilderten Probleme liegen? Vor allem in Verbindung mit Störungen durch die fliegende Verdrahtung auf dem Breadboard? Vielleicht hat ja jemand eine gute Idee, Gruss, Stefan void w2led(int number, int dot){ //Bits zum Shifter for (int i=0;i<8;i++){ if (number%2){ //mittels MOD2 Bits auslesen PORTB|=(1<<PB1); //0 oder 1 auf Port setzen }else{ if ((i==0)&&(dot==1)){ PORTB|=(1<<PB1); }else{ PORTB&=~(1<<PB1); } } number=number/2; //Division 2 PORTB|=(1<<PB0); //1x Clock an, aus für Shifter asm("nop"); PORTB&=~(1<<PB0); } }
sind denn alle LED's an, wenn du
1 | void alle(){ |
2 | while(1) |
3 | {
|
4 | PORTB|=(1<<PB1); |
5 | asm("nop"); |
6 | asm("nop"); |
7 | asm("nop"); |
8 | PORTB|=(1<<PB1); |
9 | asm("nop"); |
10 | asm("nop"); |
11 | asm("nop"); |
12 | }
|
13 | }
|
schickst?
Hallo Metzger, hab das eben bei mir reingebastelt und aufgerufen. Nein, es sind nicht alle an: es leuchten a, d und der Dezimalpunkt. Jetzt bin ich neugierig,was Du daraus schliessen kannst!! Stefan
Zeig doch mal den Rest. Im Idealfall speckst du erst mal dein Programm komplett ab, so dass nur noch der 7-Seg Code übrig bleibt, auf dem du zb einfach nur konstante Werte ausgibst. Auf die Art * ist sicher gestellt, dass das Problem auch tatsächlich im 7_Seg Teil zu suchen ist und nicht zb dadurch entsteht, dass du rasend schnell unterschiedliche Zahlen ausgibst, die sich dann an der 7-Seg zu einem Lichtbrei verschmieren * konzentriert sich dann auch die Fehlersuche auf einen bestimmten Bereich. Zb muss man sich dann nicht darauf konzentrieren ob du nicht schwankende Werte vom ADC einliest.
OK, dann bau ich mir um Deine Schleife herum mal ein neues Testprogramm und gehe auf die Suche. Danke! Stefan
Stefan R. schrieb: > Hallo Metzger, > > hab das eben bei mir reingebastelt und aufgerufen. Nein, es sind nicht > alle an: es leuchten a, d und der Dezimalpunkt. > > Jetzt bin ich neugierig,was Du daraus schliessen kannst!! Gar nix. Es sei denn, du hättest den fehlenden Clock-Puls ergänzt.
:
Bearbeitet durch Admin
Das habe ich auch gerade eben gemerkt. Das muss natürlich noch rein...
So, nun steht im Programm: void alle(){ while(1) { PORTB|=(1<<PB1); asm("nop"); asm("nop"); asm("nop"); PORTB|=(1<<PB1); asm("nop"); asm("nop"); asm("nop"); PORTB|=(1<<PB0); //1x Clock an, aus für Shifter asm("nop"); PORTB&=~(1<<PB0); } } und es leuchten brav alle 8 LEDs. Hmm..
derMetzger schrieb: > sind denn alle LED's an, wenn du > >
1 | > void alle(){ |
2 | > while(1) |
3 | > { |
4 | > PORTB|=(1<<PB1); |
5 | > asm("nop"); |
6 | > asm("nop"); |
7 | > asm("nop"); |
8 | > PORTB|=(1<<PB1); |
9 | > asm("nop"); |
10 | > asm("nop"); |
11 | > asm("nop"); |
12 | > } |
13 | > } |
14 | >
|
> > schickst? Soll das beim zweiten Mal vielleicht PORTB&=~(1<<PB1) heissen? .
Diese Stelle im Programm hat schon eine hohe Redundanz. Aber das Bit wieder zu löschen würde doch hier noch weniger bringen, oder irre ich da?
Stefan R. schrieb: > Diese Stelle im Programm hat schon eine hohe Redundanz. Aber das Bit > wieder zu löschen würde doch hier noch weniger bringen, oder irre ich > da? Vergiss es. Systematisch vorgehen. Anstatt alle LED in einer Schleife, mschst du jetzt mal alle 8 einzeln. Ziel der Sache ist es, Volldampf auf den Leitungen zu haben um damit feststellen zu können, ob du zb Übersprechen oder sowas hast. Du willst ja wissen ob an deinem Hardwareaufbau was falsch ist. Dann setzt du nacheinander einzelne LED gezielt auf 0
1 | void Zero() |
2 | {
|
3 | PORTB &= ~(1<<PB1); |
4 | |
5 | PORTB |= (1<<PB0); //1x Clock an, aus für Shifter |
6 | asm("nop"); |
7 | PORTB &= ~(1<<PB0); |
8 | }
|
9 | |
10 | void One() |
11 | {
|
12 | PORTB |= (1<<PB1); |
13 | |
14 | PORTB |= (1<<PB0); //1x Clock an, aus für Shifter |
15 | asm("nop"); |
16 | PORTB &= ~(1<<PB0); |
17 | }
|
18 | |
19 | void alle(){ |
20 | while(1) |
21 | {
|
22 | Zero(); |
23 | Zero(); |
24 | Zero(); |
25 | Zero(); |
26 | One(); |
27 | One(); |
28 | One(); |
29 | One(); |
30 | |
31 | _delay_ms( 10 ); |
32 | }
|
33 | }
|
dass lässt gezielt nur 4 LED aufleuchten. Sind die anderen Segmente (einigermassen) dunkel? Was ist wenn du zb nur das 1-te Segment leuchten lässt und alle anderen dunkel sind? Dann nur das 2-te etc.
:
Bearbeitet durch Admin
Das 74164 war aber auch eine selten dämlich Wahl für ein Schieberegtister an dieser Stelle, weil es keine Output-Latches hat. D.h. du wirst auf deinen Anzeigen immer ein bischen sehen, wie im Hintergrund durchgeschoben wird.
Dafür, dass ich erst seit zwei Wochen an dem Thema µC dran bin, kann ich es mir verzeihen auch mal etwas dämliches zu tun. Dass ich das Geschiebe im Hintergrund sehe, stört mich weniger. Was den Test mit 4 an / 4 aus angeht, habe ich jetzt auch verstanden, worum es geht. Und: nö, es leuchtet alles schön gleichmässig. Es kommt also Müll am Shifter an, oder?
Stefan R. schrieb: > Was den Test mit 4 an / 4 aus angeht, habe ich jetzt auch verstanden, > worum es geht. Und: nö, es leuchtet alles schön gleichmässig. Es kommt > also Müll am Shifter an, oder? Probier zur Sicherheit auch noch ein paar andere Kombinationen. Aber bis jetzt sehen die Symptome eher so aus, dass deine Hardware in Ordnung ist. D.h dein Problem liegt nicht in der Funktion und auch nicht in der Hardware, sondern in den Programmteilen die du nicht gezeigt hast.
:
Bearbeitet durch Admin
OK, und weil ich keine Latches habe, kann ich jetzt auch nicht erkennen, ob das mit dem 4*an / 4*aus was gebracht hat, weil ich nur das Gewische sehe, oder?
Stefan R. schrieb: > OK, und weil ich keine Latches habe, kann ich jetzt auch nicht erkennen, > ob das mit dem 4*an / 4*aus was gebracht hat, weil ich nur das Gewische > sehe, oder? Ich hab in der Vorlage noch mal ein wenig nachgebessert und einen kleinen _delay_ms eingebaut. Der sollte eigentlich dafür sorgen, dass sich aus dem Gewische wieder ein halbwegs stabile Anzeige ergibt, weil dann die Anzeigezeit der fertigen Anzeige länger ist, als die Zeit die das 'Gewische' benötigt um sich auf die nächsten 8 Bit einzustellen. Das sollte so eigentlich ganz gut funktionieren. Wenn man genau hinsieht (vor allem im Dunkel) wird man bei den eigentlich dunklen Segmenten ein kleines Glimmen sehen können, das ist unvermeidlich bei einem Schieberegister ohne Latches. Dann muss man eben per Programm dafür sorgen, dass das nicht stört, weil zb das Schieben im Vergleich zur statischen Anzeige nur verschwindend wenig Zeit bekommt. Wenn das SChieben in 10µs verbei ist und die Anzeige danach 10ms ruhig vor sich hinleuchten darf, sollte man eigentlich fast nichts mehr sehen.
:
Bearbeitet durch Admin
OK, vielen Dank erst einmal an alle, die mir geholfen haben! Ich werde meinen restlichen Code noch einmal sichten und komplett neu überarbeiten. Wenn dabei etwas erwähnenswertes rauskommen sollte, werde ich das noch berichten.. Stefan
Also in der Tat habe ich die Probleme mit der Anzeige bei meinem Code ausmachen können. In der Funktion w2led werden die Bits für die Zahl auf der 7(8)-Segment-Anzeige ausgelesen und entsprechend auf den Ausgang PB1 gesetzt. Danach wir kurz die Clock auf PB0 gesetzt. Nun habe ich alles wieder am Laufen und es tauchen auch keine Fehler mehr auf. Allerdings ist die Logik des Ablaufs noch nicht ganz so schön, wie ich es gern gehabt hätte und eben hier liegt auch das Problem. Wenn ich nämlich den Ablauf schöner schreibe, tauchen auch wieder die Aussetzer auf dem Display auf. Hier im Quelltext die Funktion, so wie sie perfekt läuft. Über dem Codeblock zwischen den Strichen ist eine zweite Version desselben auskommentiert, die ich als schönere Version geschrieben hatte, die aber eben diese Aussetzer produziert. Obwohl ich der Meinung bin, dass beide logisch identisch sind.. oder übersehe ich da was? Also: Byte mit Modulo2 leermachen und jeweils 1 oder Null an PB1. Wenn aber dot>0 an die Funktion übergeben wurde (=Zahl mit Dezimalpunkt ausgeben), dann das erste Bit als 1 ausgeben. Nach dem Schieben des gesamten Bytes ist das ja dann an der Stelle des Dezimalpunktes. Vielleicht ist ja jemand dabei, der da den Fehler sehen kann—ich sehe gaaar nichts mehr. Stefan R. void w2led(int number, int dot){ //Bits zum Shifter for (int i=0;i<8;i++){ /* //=============================== if ((i==0)&&(dot==1)){ PORTB|=(1<<PB1); }else{ if (number%2){ PORTB|=(1<<PB1); }else{ PORTB&=~(1<<PB1); } } //============================== */ //========================== if (number%2){ PORTB|=(1<<PB1); }else{ PORTB&=~(1<<PB1); } if ((i==0)&&(dot==1)){ // <---- fand ich unschön PORTB|=(1<<PB1); } //============================== number=number/2; //Division 2 PORTB|=(1<<PB0); //1x Clock an, aus für Shifter asm("nop"); PORTB&=~(1<<PB0); } }
:
Bearbeitet durch Admin
Als allererstes solltest du mal die Beschäftigungstherapie für den µC abstellen. int ist in der Desktopprogrammierung schön und gut. Aber hier haben wir es mit einem 8 Bit µC zu tun. 16 Bit Verarbeitung ist für den ziemilch aufwändig. daher gibt es die Datentypen uint8_t, mit denen man auf 8 Bit zurückschalten kann. Dann gefällt mir nicht, was du da mit dot in der Funktion veranstaltest. Wenn dot auf 1 ist, dann setz duch einfach in number das 1-te Bit auf 1 und die nachfolgende Schleife verarbeitet das dann richtig. Dann ist das was die Funktion bekommt im eigentlichen Sinn keine Zahl mehr, sondern ein Muster, das auf die Anzeige ausgegeben werden soll. Nenn es auch so! Hier an dieser Stelle, in dieser Funktion ist das alles reines Bitgefummel. Da ist der Einsatz von Bitoperationen durchaus erlaubt. arithmetische Operationen % bzw / machen zwar in dem Fall das gleiche, sind aber nicht so aussagekräftig wie dezidierte Bitoperationen. Schreib deine Codezeilen nicht so auf Knirsch. Seit du 6 Jahre alt bist, hast du dein Gehirn darauf trainiert, dass zwischen Wörter ein Leerraum steht und es da ganz schnell erkennen kann wo ein Wort aufhört und wo das nächste anfängt. Nutze dieses Training um deinen Code so zu gestalten, dass man ihn leicht elsen kann.
1 | void w2led( uint8_t pattern, uint8_t dot) |
2 | { //Bits zum Shifter |
3 | if( dot ) |
4 | pattern |= ( 1 << 0 ); // Dezimalpunkt setzen falls angefordert |
5 | |
6 | for( uint8_t i = 0; i < 8; i++ ) |
7 | {
|
8 | // Datenbis ausgeben. Es wird immer Bit 0 von pattern betrachtet ...
|
9 | if( pattern & 0x01 ) |
10 | PORTB |= ( 1<<PB1 ); |
11 | else
|
12 | PORTB &= ~( 1 << PB1 ); |
13 | |
14 | // ... weil jetzt die Bits in pattern nachgeschoben werden
|
15 | pattern = pattern >> 1; |
16 | |
17 | // einen Clock Puls nachschieben
|
18 | PORTB |= ( 1<<PB0 ); |
19 | asm( "nop" ); |
20 | PORTB &= ~( 1<<PB0 ); |
21 | }
|
22 | }
|
So würde ich die Funktion schreiben. (Fürs erste. In dieser Funktion kann man noch vieles machen um sie lesbarer/wartbarer zu bekommen)
1 | adc_lo=ADCL; |
2 | adc_hi=ADCH; |
3 | result=(adc_hi*256)+adc_lo; |
diese Operation kann dein Compiler ganz von alleine
1 | int main() |
2 | {
|
3 | uint16_t adcValue; |
4 | |
5 | ....
|
6 | |
7 | |
8 | while( 1 ) { |
9 | ....
|
10 | |
11 | adcValue = ADCW; |
einfach den Wert aus dem 16 Bit Pseudoregister ADCW auslesen. Der Compiler dröselt das dann schon richtig auf.
1 | ADMUX = 0b00000010; |
2 | ADCSRA = 0b10000111; |
das hier ist genau die Schreibweise die du nicht benutzen sollst. Kein Mensch kann hier sehen, welche Bits du setzt, und was sie bedeuten. Benutze die symbolischen Namen mit der (1<<xyz) Schreibweise. Dann findet man im Dtaenblatt (sofern man die Werte nicht auswändig kennt) die Bedeutungen viel schneller. Schau dir im AVR-GCC-Tutorial im Abschnitt üder den ADC die Funktionen an. Dort siehst du wie man das schreiben kann, so dass man das auch leicht lesen kann.
Aber es liegt ja nicht an der Schreibweise, dass das Programm nicht läuft. Deine Änderungen zu der Funktion finde ich interessant und die werde ich auch übernehmen. Aber trotzdem läuft die Funktion so, wie Du sie geschrieben hast, nicht. Damit kommt beim Display der gleiche Wirrwarr an, wie mit der, die ich auskommentiert habe. Wie gesagt: wundersamerweise läuft die, die ich im oben in der Funktion verwende, tadellos.
Stefan R. schrieb: > Aber es liegt ja nicht an der Schreibweise, dass das Programm nicht > läuft. Deine Änderungen zu der Funktion finde ich interessant und die > werde ich auch übernehmen. Aber trotzdem läuft die Funktion so, wie Du > sie geschrieben hast, nicht. Damit kommt beim Display der gleiche > Wirrwarr an, wie mit der, die ich auskommentiert habe. Wie gesagt: > wundersamerweise läuft die, die ich im oben in der Funktion verwende, > tadellos. Dann nimm erst mal den ADC raus und ersetzte das durch einen fixen Wert, damit du erst mal fehlerhafte ADC Werte als Ursache ausschliessen kannst.
1 | uint8_t map[] = { |
2 | 0b11111100, 0b01100000, 0b11011010, //0,1,2 |
3 | 0b11110010, 0b01100110, 0b10110110, //3,4,5 |
4 | 0b10111110, 0b11100000, 0b11111110, //6,7,8 |
5 | 0b11110110 //9 |
6 | };
|
7 | |
8 | void init(void) |
9 | //binäre Ausgänge setzen
|
10 | DDRB = (1<<PB1) | (1<<PB0); |
11 | |
12 | ADMUX = 0b00000010; |
13 | ADCSRA = 0b10000111; |
14 | }
|
15 | |
16 | void w2led( uint8_t pattern, uint8_t dot) |
17 | { //Bits zum Shifter |
18 | if( dot ) |
19 | pattern |= ( 1 << 0 ); // Dezimalpunkt setzen falls angefordert |
20 | |
21 | for( uint8_t i = 0; i < 8; i++ ) |
22 | {
|
23 | // Datenbis ausgeben. Es wird immer Bit 0 von pattern betrachtet ...
|
24 | if( pattern & 0x01 ) |
25 | PORTB |= ( 1<<PB1 ); |
26 | else
|
27 | PORTB &= ~( 1 << PB1 ); |
28 | |
29 | // ... weil jetzt die Bits in pattern nachgeschoben werden
|
30 | pattern = pattern >> 1; |
31 | |
32 | // einen Clock Puls nachschieben
|
33 | PORTB |= ( 1<<PB0 ); |
34 | asm( "nop" ); |
35 | PORTB &= ~( 1<<PB0 ); |
36 | }
|
37 | }
|
38 | |
39 | int main(void) |
40 | {
|
41 | uint16_t adc_value; |
42 | |
43 | init(); |
44 | |
45 | for(;;) |
46 | {
|
47 | /*
|
48 | ADCSRA |= (1<<ADSC); //go!
|
49 | while (ADCSRA & (1<<ADSC)){
|
50 | }
|
51 | adc_value = ADCW;
|
52 | */
|
53 | adc_value = 876; |
54 | |
55 | adc_value = adc_value / 21; |
56 | |
57 | w2led( map[ adc_value / 10], 1 ); |
58 | _delay_ms( 700 ); |
59 | w2led( map[ adc_value % 10], 0 ); |
60 | _delay_ms( 270 ); |
61 | }
|
62 | }
|
was macht es damit? Das sollte abwechselnd 4 und 1 darstellen.
:
Bearbeitet durch Admin
Wie übernimmt eigentlich dieses Schieberegister die Daten? Mit der steigenden oder mit der fallenden Flanke? Dein Programm setzt auf steigende Flanke. Hast du das mit dem Datenblatt kontrolliert? Edit: OK, ich habs kontrolliert. Steigende Flanke ist richtig.
Ja, jetzt zeigt das Display abwechselnd 4. und 1 an. Ohne Fehler. Mit dem Code, der im Anhang ist.
OK. Dann aktivier den ADC mal dazu. Was hast du eigentlich am ADC Eingang hängen?
Diese Map uint8_t map[] = { 0b11111100, 0b01100000, 0b11011010, //0,1,2 0b11110010, 0b01100110, 0b10110110, //3,4,5 0b10111110, 0b11100000, 0b11111110, //6,7,8 0b11110110 //9 }; hast du schon mal bei einem Programmlauf kontrolliert? (alle Zahlen durchlaufen lassen). Nicht dass sich da noch ein Fehler drinn versteckt.
Ich habe ein Poti 50k zwischen +5V und GND. Der Schleifer geht in den ADC. Jetzt habe ich den Festwert rausgenommen und nehme die Werte wieder aus den ADC (siehe Anhang). Und wieder Müll auf der Anzeige. Einzelne Segmente fehlen, der Dezimalpunkt wird fast nie angezeigt. Ist mir ein Rätsel..
Karl Heinz Buchegger schrieb: > Diese Map > > uint8_t map[] = { > 0b11111100, 0b01100000, 0b11011010, //0,1,2 > 0b11110010, 0b01100110, 0b10110110, //3,4,5 > 0b10111110, 0b11100000, 0b11111110, //6,7,8 > 0b11110110 //9 > }; > > hast du schon mal bei einem Programmlauf kontrolliert? (alle Zahlen > durchlaufen lassen). Nicht dass sich da noch ein Fehler drinn versteckt. Nein, das habe ich noch nicht. Aber das merkwürdige ist doch, dass es mit meiner Version von 19Uhr25 ohne Probleme läuft. Auch wenn die sicher einige Schwächen bzgl. Inhalt und Form hat.
Also den 164er hab ich auch manchmal dafür verwendet, wenn nichts anderes da war. Das mit dem Durchgeschiebe würde man zwar theoretisch sehen, ich konnte es aber eigentlich noch nie wirklich erkennen, weil die Verweilzeit wesentlich länger ist, als das Reintakten. Hängt aber sicher auch von der Geschwindigkeit ab, mit der man arbeitet.
Stefan R. schrieb: > Ich habe ein Poti 50k zwischen +5V und GND. Der Schleifer geht in den > ADC. Jetzt habe ich den Festwert rausgenommen und nehme die Werte wieder > aus den ADC (siehe Anhang). Und wieder Müll auf der Anzeige. Einzelne > Segmente fehlen, der Dezimalpunkt wird fast nie angezeigt. Ist mir ein > Rätsel.. Hmm. Sieht für mich danach aus, als ob die Werte vom ADC nicht stimmen und da Werte rauskommen, die über 1023 liegen. Begrenze die mal, so dass du in weiterer Folge beim Array-Zugriff keine Overflows produzierst.
1 | int main() |
2 | {
|
3 | ....
|
4 | |
5 | for(;;) |
6 | {
|
7 | ....
|
8 | |
9 | |
10 | adc_value = ADCW; |
11 | |
12 | if( adc_value > 1023 ) |
13 | adc_value = 1023; |
14 | |
15 | adc_value /= 21; |
16 | |
17 | ....
|
:
Bearbeitet durch Admin
Stefan R. schrieb: > Nein, das habe ich noch nicht. Aber das merkwürdige ist doch, dass es > mit meiner Version von 19Uhr25 ohne Probleme läuft. Auch wenn die sicher > einige Schwächen bzgl. Inhalt und Form hat. Ich denke das war Zufall. Das geht sich irgendwie dann mit dem ADC Timing besser aus. Willst du die Zahlen durchprobieren? Kannst du zb so machen
1 | int main() |
2 | {
|
3 | uint8_t i; |
4 | |
5 | init(); |
6 | |
7 | for( ;; ) |
8 | {
|
9 | for( i = 0; i < 10; ++i ) |
10 | {
|
11 | w2led( map[ i ], 1 ); |
12 | _delay_ms( 500 ); |
13 | }
|
14 | }
|
15 | }
|
da sollten jetzt mal alle Ziffern sauber durchrauschen. Ich denke zwar die map ist in Ordnung, aber ich kann natürlich Lötfehler bzw. Lötbrücken nicht sehen. Von daher würd ich das mal probieren. Edit: Oder Steckfehler. Irgendwo weiter oben hast du ein Steckbrett erwähnt.
:
Bearbeitet durch Admin
Also die Begrenzung if( adc_value > 1023 ) adc_value = 1023; hat nichts gebracht. Ja, ich probiere das mit den reinen Zahlen mal aus......
Stefan R. schrieb: > Also die Begrenzung > > > if( adc_value > 1023 ) > adc_value = 1023; > > > hat nichts gebracht. Ja, ich probiere das mit den reinen Zahlen mal > aus...... Und sei es nur um Gewissheit zu haben, dass die Anzeige richtig verkabelt ist. Solche Tests sind nie schlecht und sind ja schnell gemacht. Das gibt eine gewisse Sicherheit, dass zumindest ein Subsystem sauber dasteht. Hast du eigentlich dem µC und dem Schiebregister ein paar Blockkondensatoren spendiert?
:
Bearbeitet durch Admin
So, hab' ich gemacht. Läuft immer von 0 bis 9 durch. 0 ohne dot 1 ohne dot 2 korrekt 3 verstümmelt, ohne dot 4 verstümmelt 5 korrekt 6 verstümmelt 7 ohne dot 8 korrekt 9 verstümmelt Und das jedes Mal genau dieser Ablauf. Immer wieder von vorn.
Stefan R. schrieb: > So, hab' ich gemacht. Läuft immer von 0 bis 9 durch. > > 0 ohne dot > 1 ohne dot > 2 korrekt > 3 verstümmelt, ohne dot > 4 verstümmelt > 5 korrekt > 6 verstümmelt > 7 ohne dot > 8 korrekt > 9 verstümmelt > > Und das jedes Mal genau dieser Ablauf. Immer wieder von vorn. Oha! Das sieht dann aber eher danach aus, als ob deine Verkabelung vom SR zur 7-Seg nicht stimmt! Kann es sein, dass deine Bits im Byte genau seitenverkehrt sind? (beliebter Fehler). Das erste Bit (Bit 0) das du reintaktest wandert am weitesten durch das SR kommt dort also an QH raus. Laut deinem Programm müsste das der Dezimalpunkt sein.
:
Bearbeitet durch Admin
Karl Heinz Buchegger schrieb: > Hast du eigentlich dem µC und dem Schiebregister ein paar > Blockkondensatoren spendiert? Ich an den Eingängen direkt am Schieber Kondensatoren jeweils auf GND (100pF) und Pull-Down-Widerstände (unter 100k). Hat aber gar nichts geändert. Zusätzlich hatte ich ja auch noch das Kabel von etwa 10 auf 2 cm verkürzt.
> Das sieht dann aber eher danach aus, als ob deine Verkabelung vom SR zur > 7-Seg nicht stimmt! Ja, das könnte man annehmen. Aber dann frage ich mich, warum es wie gesagt mit der Version, die ich erwähnt habe, ohne Probleme funktioniert.
Stefan R. schrieb: >> Das sieht dann aber eher danach aus, als ob deine Verkabelung vom SR zur >> 7-Seg nicht stimmt! > > Ja, das könnte man annehmen. Aber dann frage ich mich, warum es wie > gesagt mit der Version, die ich erwähnt habe, ohne Probleme > funktioniert. Kann Zufall sein. Das hier hast du gelesen: Kann es sein, dass deine Bits im Byte genau seitenverkehrt sind? (beliebter Fehler). Das erste Bit (Bit 0) das du reintaktest wandert am weitesten durch das SR kommt dort also an QH raus. Laut deinem Programm müsste das der Dezimalpunkt sein.
:
Bearbeitet durch Admin
> > Kann Zufall sein. > > > Zufall? Das müsste dann doch aber ein toller Zufall sein. Dass meine Funktion genau die Fehler behebt, die ich in der Verkabelung habe. Das halte ich doch für sehr unwahrscheinlich.
Karl Heinz Buchegger schrieb: > Kann es sein, dass deine Bits im Byte genau seitenverkehrt sind? > (beliebter Fehler). Das erste Bit (Bit 0) das du reintaktest wandert am > weitesten durch das SR kommt dort also an QH raus. Laut deinem Programm > müsste das der Dezimalpunkt sein. Genau, der geht als erstes rein und wandert dann 7 Positionen weiter. Aber das ist bei mir auch richtig so verdrahtet. Vom Shifter geht es bei mir so zum Display: Q0->a Q1->b ... ... Q6->g Q7->DP (dot)
Was ich mir noch vorstellen könnte Der µC ist ein klein wenig zu schnell für das SR (auch wenn ich nicht daran glaube. Alelrdings könnten Kapazitäten beim Aufbau da eine Rolle spielen). In deiner funktionierenden Variante dauert es vom Anlegen des Datenbits bis zum Clock Puls ein bischen länger als in der 'schöneren' Variante. Kann man ja mal probieren. Einfach eine kleine Verzögerung rein und sehen was passiert.
1 | void w2led( uint8_t pattern, uint8_t dot) |
2 | { //Bits zum Shifter |
3 | if( dot ) |
4 | pattern |= ( 1 << 0 ); // Dezimalpunkt setzen falls angefordert |
5 | |
6 | for( uint8_t i = 0; i < 8; i++ ) |
7 | {
|
8 | // Datenbis ausgeben. Es wird immer Bit 0 von pattern betrachtet ...
|
9 | if( pattern & 0x01 ) |
10 | PORTB |= ( 1<<PB1 ); |
11 | else
|
12 | PORTB &= ~( 1 << PB1 ); |
13 | |
14 | // ... weil jetzt die Bits in pattern nachgeschoben werden
|
15 | pattern = pattern >> 1; |
16 | |
17 | _delay_ms( 1 ); |
18 | // einen Clock Puls nachschieben
|
19 | PORTB |= ( 1<<PB0 ); |
20 | _delay_ms( 1 ); |
21 | PORTB &= ~( 1<<PB0 ); |
22 | }
|
23 | }
|
Wenn die Verzögerungen nix bewirken und die durchlaufenden Zahlen dann immer noch nicht stimmen, dann bleibt nur noch die fehlerhafte Tabelle.
Hab' ich so reingesetzt, wie Du es geschrieben hast, aber das ändert auch nichts. Aber ich hatte auch schon die Vermutung, dass meine lauffähige Variante einfach ein etwas anderes Timing verursacht. Rein logisch betrachtet sehe ich zwischen den beiden Versionen (eine ist ja auskommentiert) in der Version von 19Uhr25 keinen Unterschied. Also muss hier auch die Lösung liegen. Ich könnte die Version ja einfach so lassen und mich freuen, dass es geht. Aber da kommt dann doch mein sportlicher Ehrgeiz durch.
Karl Heinz Buchegger schrieb: > Wenn die Verzögerungen nix bewirken und die durchlaufenden Zahlen dann > immer noch nicht stimmen, dann bleibt nur noch die fehlerhafte Tabelle. Aber dann würde meine Version de Funktion ja die fehlerhafte Tabelle "korrigieren". Wie soll das gehen?
Was passiert hier
1 | int main() |
2 | {
|
3 | uint8_t i; |
4 | |
5 | init(); |
6 | |
7 | for( ;; ) |
8 | {
|
9 | for( i = 0; i < 10; ++i ) |
10 | {
|
11 | w2led( 0, 1 ); |
12 | _delay_ms( 500 ); |
13 | }
|
14 | }
|
15 | }
|
eigentlich sollte der Dezimalpunkt sauber dauerleuchten Edit: Ich schätze mal das wird er nicht. Statt dessen wird ein anderes Segment leuchten.
Karl Heinz Buchegger schrieb: > Was passiert hier > > > eigentlich sollte der Dezimalpunkt sauber dauerleuchten > > Edit: Ich schätze mal das wird er nicht. Statt dessen wird ein anderes > Segment leuchten. Ja, der leuchtet die ganze Zeit. Und auf dem restlichen Display blitzt zweimal in der Sekunde eine blasse 8. Genau das, was passieren sollte, oder?
Stefan R. schrieb: > Karl Heinz Buchegger schrieb: >> Was passiert hier >> > > >> >> eigentlich sollte der Dezimalpunkt sauber dauerleuchten >> >> Edit: Ich schätze mal das wird er nicht. Statt dessen wird ein anderes >> Segment leuchten. > > Ja, der leuchtet die ganze Zeit. Und auf dem restlichen Display blitzt > zweimal in der Sekunde eine blasse 8. Genau das, was passieren sollte, > oder? Jup. Das ist genau das was passieren sollte, wenn alles richtig ist. Jetzt bin ich auch mit meinem Latein am Ende. Die restlichen Pins vom Schieberegister, zb Clear, was hast du mit denen gemacht? (irgendwas bringt das SR anscheinend ausser tritt.)
:
Bearbeitet durch Admin
Also ein Reset ist ja noch am Shifter. Aber den habe ich unverdrahtet gelassen. Ich werde das Thema jetzt auch mal etwas sacken lassen. Ich werde die Tage ohnehin bestellen und mir dann einfach ein anderes 74LS164 holen (habe irgendein Billigding von Händler um die Ecke) und wenn es geht auch ein anderes Register. Mal sehen, was ich da am besten nehmen kann. Zum Glück habe ich den Shifter auf der Platine gesockelt, so dass ich ihn locker rausholen kann. Vielen Dank erst einmal für Deine Hilfe! Ich werde Dich wissen lassen, wenn ich irgendwie weiter gekommen bin. Umwege erhöhen zum Glück immer die Ortskenntnisse. Gruss, Stefan
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.