www.mikrocontroller.net

Forum: GCC Rätselhaftes AVR.

Autor: Sven Pauli (haku) Benutzerseite
Datum: 03.05.2008 22:28

Huhu,

Habe an meinem AVR ein paar simple Taster angeschlossen, und zwar wie
folgt:
* an Port B4 (als Input) liegt ein Pull-down (!)-Widerstand
* zwischen den Pins von Port C liegen die Taster über Dioden an B4.

D.h., bei gedrücktem Taster kriegt Port B4 einen High-Pegel. Das mag
zwar etwas ungewöhnlich anmuten, macht aber im Gesamtaufbau der
Schaltung Sinn.
Beim Abfragen tritt jedoch ein (für mich...) unerklärliches Phänomen
auf.

Folgender Code schaltet eine LED erwartungsgemäß immer dann ein, wenn
der Taster an Port C0 gedrückt wird:
PORTC = _BV(0);
if (PINB & _BV(PINB4)) {
  LED_AN;
}

/*
buttons = 0;
for (i = 0; i < 5; i++) {
  buttons <<= 1;
  if (PINB & _BV(PINB4)) {
    buttons |= _BV(0);
  }

  PORTC <<= 1;
}
*/

Wenn ich den auskommentierten Block oben nun aber einbinde
(Kommentarzeichen weglassen, logisch), dann leuchtet die LED immer dann,
wenn der Taster an Port C1 (1!) gedrückt ist!

Ich rätsel nun schon seit zwei Tagen rum und komm auf keinen grünen
Zweig. Wodran hängt das nun? (Taktrate ist 4MHz, hab auch schon
reichlich NOP eingebaut^^)

Hoffentlich kann mir da jemand helfen -- vielen Dank schonmal!

Viele Grüße,
Sven
Autor: Andreas Kaiser (a-k)
Datum: 03.05.2008 22:36

Mit dem bischen Code lässt sich nix anfangen. Es fehlt mindestens die
Initialisierung der Ports und der Code für LED_AN und was sonst nocht
alles passiert und vielleicht mitmischt (und von dem du 100% genau
sicher garantiert weisst, dass es nichts damit zu tun hat ;-).
Autor: Schwurbl (Gast)
Datum: 03.05.2008 22:41

Ich schätze, es liegt an der Verzögerung der äußeren Beschaltung. Du
mußt Deiner Schaltung Zeit zur Stabilisierung geben. Das heißt, Port C
einstellen, warten, und dann abfragen. Dann erst mit dem nächsten Bit
weitermachen. Du "siehst" an der LED immer noch die Wirkung von Port 0.
Autor: Sven Pauli (haku) Benutzerseite
Datum: 03.05.2008 22:44

Andreas Kaiser wrote:
> Mit dem bischen Code lässt sich nix anfangen.
Hab schon drei Tage den Code isoliert, aber bitteschön:
#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>

#define LED_AN     PORTD |= _BV(PORTD1)

ISR(TIMER0_OVF_vect) {
  volatile uint8_t buttons = 0;
  uint8_t i;

  PORTC = _BV(0);
  if (PINB & _BV(PINB4)) {
    LED_AN;
  }
  

/*
  buttons = 0;
  for (i = 0; i < 5; i++) {
    buttons <<= 1;
    if (PINB & _BV(PINB4)) {
      buttons |= _BV(0);
    }

    PORTC <<= 1;
  }
*/
}

int main() {
  cli();

  PORTB = 0;
  DDRB = 0;

  PORTC = 0;
  DDRC = 0xFF;

  PORTD = 0;
  DDRD = 0xFF;

  TCCR0 = _BV(CS01);
  TIMSK = _BV(TOV0);
  sei();

  for (;;) {
    asm volatile ("nop" ::);
  }
}

Autor: Sven Pauli (haku) Benutzerseite
Datum: 03.05.2008 22:46

Schwurbl wrote:
> Ich schätze, es liegt an der Verzögerung der äußeren Beschaltung. Du
> mußt Deiner Schaltung Zeit zur Stabilisierung geben. Das heißt, Port C
> einstellen, warten, und dann abfragen. Dann erst mit dem nächsten Bit
> weitermachen. Du "siehst" an der LED immer noch die Wirkung von Port 0.

Das kann ja nicht sein.
Die Codepassage, die die LED anschaltet, ändert sich ja nicht. Und
zwischen den Aufrufen der ISR ist auch genug Zeit über. Ferner hängt ja
bis auf die Dioden und die Schalter rein garnix am AVR dran... bis auf
den Quarz und die Blockkondis natürlich.
  PORTC = _BV(0);
  if (PINB & _BV(PINB4)) {
    LED_AN;
  }
Autor: Andreas Kaiser (a-k)
Datum: 03.05.2008 22:58

Doch, Schwurbl hat schon recht. Wenn man im direkt auf einen
Ausgabebefehl folgenden Befehl einen Pin abfragt, der von der Ausgabe
beeiflusst wird, dann klappt das nicht wie erwartet. Steht übrigens im
Datasheet.

Daher hängt das Ergebnis davon ab, was am Port C vorher ausgegeben
wurde. Und das wiederum wird vom kommentierten Code bestimmt. Allerdings
wäre da nicht C1 zu erwarten, sondern C5.
Autor: Sven Pauli (haku) Benutzerseite
Datum: 03.05.2008 23:03

Andreas Kaiser wrote:
> Allerdings wäre da nicht C1 zu erwarten, sondern C5.

Hmm, du hast vollkommen Recht, das ist auch C5... muss mal wieder die
Brille putzen :-)

Also, so funktioniert es:
ISR(TIMER0_OVF_vect) {
  volatile uint8_t buttons = 0;
  uint8_t i;

  PORTC = _BV(0);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
asm volatile ("nop" ::);
  if (PINB & _BV(PINB4)) {
    LED_AN;
  }
  

/*
  buttons = 0;
  for (i = 0; i < 5; i++) {
    buttons <<= 1;
    if (PINB & _BV(PINB4)) {
      buttons |= _BV(0);
    }

    PORTC <<= 1;
  }
*/
}

Entschuldigung (...) Aber selbst mit 8 NOPs wars noch nicht getan... wo
kommt denn da bloß die ganzen Leitungskapazität her?!
Autor: Andreas Kaiser (a-k)
Datum: 03.05.2008 23:05

Das wäre jetzt eine prima Gelegenheit, die exakt verbaute Hardware zu
dokumentieren.

Sind die Dioden vielleicht 1N4000 oder ähnlich schnarchlangsame
Genossen?
Autor: Schwurbl (Gast)
Datum: 03.05.2008 23:10

Ist es denn so, dass PORTC in Wahrheit einen Spaltentreiber schaltet,
der eine entsprechende Abschaltverzögerung ausweist? Transistoren sind
im Schaltbetrieb echte Low Performer.
Autor: Sven Pauli (haku) Benutzerseite
Datum: 03.05.2008 23:14
Dateianhang: c.png (21,2 KB, 105 Downloads)
preview image for c.png

Das kriegen wir auch hin...

Anmerkungen:
* An J1 (oben) hängen normalerweise noch LEDs, die sind aber testweise
abgeklemmt.
* Die Chose mit Q10 ist in Arbeit :-)

Nachtrag:
* Ja, es sind 4148er, die sollten aber bei dem Schnarchtakt, den der MC
vorlegt, locker mitmachen.
* Und Schwurbl hat auch Recht, es sind Spaltentreiber. Aber wenn der MC
in die Basis mal seine 40mA reinfeuert, dann sollte auch das kein
Problem darstellen, zumal ja noch 1kOhm dazwischen liegen.

Was ich gerade denke: 10kOhm Pull-down sollten eigentlich auch langen,
oder?
Autor: Andreas Kaiser (a-k)
Datum: 03.05.2008 23:17

Wo ist denn der Pulldown an B4?
Autor: Schwurbl (Gast)
Datum: 03.05.2008 23:18

Und welchen Wert hat nun der Pulldown für die Taster? Ich denke Du hast
10k verbaut. Reduzieren den mal auf ein 1k.
Autor: Sven Pauli (haku) Benutzerseite
Datum: 03.05.2008 23:20
Dateianhang: c.png (21,3 KB, 57 Downloads)
preview image for c.png

Andreas Kaiser wrote:
> Wo ist denn der Pulldown an B4?

Auch das, der wurde nachgerüstet (Designfehler) und liegt unterm PCB...
ich hab ihn hier mal dazugemalt.
Autor: Andreas Kaiser (a-k)
Datum: 03.05.2008 23:27

Wie programmierst du den eigentlich? 80-er Jahre Methode:
raus/rein/raus/rein/... oder fehlt im Bild auch der ISP-Anschluss? Ich
frage deshalb so blöd, weil B4 zum ISP gehört.
Autor: Sven Pauli (haku) Benutzerseite
Datum: 03.05.2008 23:29

Andreas Kaiser wrote:
> Wie programmierst du den eigentlich? 80-er Jahre Methode:
> raus/rein/raus/rein/... oder fehlt im Bild auch der ISP-Anschluss? Ich
> frage deshalb so blöd, weil B4 zum ISP gehört.

Die Frage ist absolut berechtigt :-)
Neee, des Rätsels Lösung ist viiiieel einfacher:

http://www.trianglemicro.com/TMS-DIP8.jpg
Autor: Schwurbl (Gast)
Datum: 03.05.2008 23:30

Jetzt mal grundätzlich gesprochen darfst Du sowieso pro Timerinterrupt
genau eine Spalte weiterschalten. Vor dem Weiterschalten, also bei
Eintritt in den Interrupt wird der Button abgefragt.

Also:
volatile uint8_t buttons = 0;

ISR(TIMER0_OVF_vect)
{
  if (PINB & _BV(PINB4))
    buttons |= PORTC;
  if (PORTC == 0x20)
    PORTC = 0x01;
  else
    PORTC <<= 1;
}

Die Weitermeldung/Synchronisation mit main fehlt hier natürlich.
Autor: Andreas Kaiser (a-k)
Datum: 03.05.2008 23:32

Sven Pauli wrote:

> * Ja, es sind 4148er, die sollten aber bei dem Schnarchtakt, den der MC
> vorlegt, locker mitmachen.

1N4148 sind ok. Ich bezog mich auf die 1N400x Serie. Die sind nämlich
ein bischen langsam.

> Was ich gerade denke: 10kOhm Pull-down sollten eigentlich auch langen,
> oder?

Hängt davon ab, wie lang die Leitung ist. Daumenregel ist 100pF/m.
Autor: Sven Pauli (haku) Benutzerseite
Datum: 03.05.2008 23:38

Schwurbl wrote:
> Jetzt mal grundätzlich gesprochen darfst Du sowieso pro Timerinterrupt
> genau eine Spalte weiterschalten. Vor dem Weiterschalten, also bei
> Eintritt in den Interrupt wird der Button abgefragt.

Auch das stimmt natürlich. Ich hab das ganze Anzeige-Multiplexing erst
einmal entfernt, um das Problem mit den Eingaben zu lösen. Erst wenn das
einmal richtig funktioniert, dann kann werde ich auch wieder MUXen :-)

Und zwar so:
1. Spalte für Zeit t anschalten
2. Zeilen für Zeit t dunkeltasten (verhindert Schlieren und
"Nachleuchten"!) und gleichzeitig die Spalten durchlaufen, um die Taster
abzufragen
3. Nächste Spalte anzeigen
4. von vorne

Ich werde in jeder Dunkeltastung alle Taster auslesen, um genug
Geschwindigkeit für den Encoder vorzulegen... das ist der Hintergedanke
dabei.
Autor: Schwurbl (Gast)
Datum: 03.05.2008 23:58

Naja, Deine Auflistung fing so gut an und dann dieses Tasterabfragen
während Dunkteltastung. Keine Ahnung, was Dein Encoder für
Sonderansprüche stellt. Ich denke, Du stellst Dich unnötigen
Herausforderungen.
Autor: Sven Pauli (haku) Benutzerseite
Datum: 04.05.2008 00:06

Schwurbl wrote:
> Naja, Deine Auflistung fing so gut an und dann dieses Tasterabfragen
> während Dunkteltastung. Keine Ahnung, was Dein Encoder für
> Sonderansprüche stellt. Ich denke, Du stellst Dich unnötigen
> Herausforderungen.

Naja, das warn nur Experimente. Rechne mal durch:
Timer läuft mit 4MHz/8 = 500kHz, die ISR wird dann mit 500kHz/256 =
knapp 2kHz aufgerufen. Jetzt würde ich noch 6 Stellen mit entsprechender
Dunkeltastung dazwischen (die brauchts, wirklich!) multiplexen, also
läge ein vollständiger Datensatz der Tasten mit 2kHz/12 = knapp 160Hz
vor, das reicht einfach nicht für diesen Pollin-Encoder -- zumindest hat
es bei meinen Versuchen nicht gereicht, leider.
Autor: Schwurbl (Gast)
Datum: 04.05.2008 00:16

Ja, an der Dunkeltastung zweifle ich nicht. Warum braucht man die? Weil
die externen Bauteile so langsam sind? Was war nochmal Dein Problem?
Langsam sollte es klingeln ;-)

Aber zugegeben: Einen Drehgeber hab ich tatsächlich noch nicht in eine
gemultiplexte Matrix gehängt... Für mich bist Du der Evel Knievel unter
den Multiplexern.
Autor: Peter Dannegger (peda)
Datum: 04.05.2008 01:36

Sven Pauli wrote:
> knapp 2kHz aufgerufen. Jetzt würde ich noch 6 Stellen mit entsprechender
> Dunkeltastung dazwischen (die brauchts, wirklich!)

Liegt aber nur an Deiner Schaltung.
Emitterschaltung ohne Basisableitwiderstand sättigt richtig fett und
sperrt nur ganz langsam.

Ich nehme daher lieber Kollektorschaltung, dann brauchts keinerlei
Dunkeltastung und spart die Basiswiderstände. Den größeren
Spannungsabfall muß man bei der Dimensionierung der Segmentwiderstände
berücksichtigen.


Peter
Autor: Sven Pauli (haku) Benutzerseite
Datum: 04.05.2008 08:56

Peter Dannegger wrote:
> Liegt aber nur an Deiner Schaltung.
> Emitterschaltung ohne Basisableitwiderstand sättigt richtig fett und
> sperrt nur ganz langsam.

Hmm... ganz langsam ist ja auch der MUX-Takt, also 160Hz sollten die
Transen aber mitmachen...

Aber trotzdem macht mich das stutzig -- woher soll die Verzögerung denn
noch kommen?
Autor: Andreas Kaiser (a-k)
Datum: 04.05.2008 09:38

Peter Dannegger wrote:

> Emitterschaltung ohne Basisableitwiderstand sättigt richtig fett und
> sperrt nur ganz langsam.

Sind doch welche drin. Rechne den steuernden Ausgang mit, der ja dann
via Basiswiderstand in die Gegenrichtung zieht. Mit niederohmigem
Ableitwiderstand geht es zwar noch schneller, aber das ist eher bei
20KHz Schaltfrequenz interessant.

Nur im Reset ist die Basis offen, was bei bipolaren Transistoren in
dieser Spannungsklasse aber nicht weiter stört (bei Hochspannung wär's
was anderes).
Autor: Sven Pauli (haku) Benutzerseite
Datum: 04.05.2008 09:51

Hab jetzt mal den Pulldown auf ein Zehntel (1kOhm) reduziert -- die
Tastenabfrage funktioniert jetzt eindeutig; ich frag mich aber immer
noch, wo ich die ganzen parasitären C verbaut hab...

Ich schieb die Bits der Tasten jetzt doch gemütlich im MUX-Takt rein, so
wie Schwurbl oben mal vorgeschlagen hatte; mit dem Encoder muss ich mir
aber noch was einfallen lassen...
Autor: Schwurbl (Gast)
Datum: 04.05.2008 09:59

Bedenke, dass die Leitung, die Umgeladen werden muss, an sämtlichen
Tastern und Dioden anliegt. Das addiert sich sicherlich zu einer
hübschen Gesamtkapazität. Ich hoffe, Du hast ein Oszi.
Autor: Sven Pauli (haku) Benutzerseite
Datum: 04.05.2008 10:03

Schwurbl wrote:
> Bedenke, dass die Leitung, die Umgeladen werden muss, an sämtlichen
> Tastern und Dioden anliegt. Das addiert sich sicherlich zu einer
> hübschen Gesamtkapazität. Ich hoffe, Du hast ein Oszi.

Hab ich... wobei ein Logic hier sinnvoller wäre :-)
Ne, die Flanken waren und sind steil.
Autor: Andreas Kaiser (a-k)
Datum: 04.05.2008 10:11

Mit einem Scope bewaffnet kannst du ja die zeitliche Differenz zwischen
dem C-Ausgang und dem B-Eingang bewundern und nach dem obskuren
"Verzögerungsglied" suchen. Und bei der Gelegenheit auch die Kapazität
ausrechnen.

Es wurde schon mehrfach auf die Länge der Verdrahtung hingewiesen. Wie
sieht's da denn aus?
Autor: Sven Pauli (haku) Benutzerseite
Datum: 04.05.2008 10:48

Andreas Kaiser wrote:
> Es wurde schon mehrfach auf die Länge der Verdrahtung hingewiesen. Wie
> sieht's da denn aus?

10 cm Litze...
Autor: Peter Dannegger (peda)
Datum: 04.05.2008 11:16

Andreas Kaiser wrote:
> Peter Dannegger wrote:
>
>> Emitterschaltung ohne Basisableitwiderstand sättigt richtig fett und
>> sperrt nur ganz langsam.
>
> Sind doch welche drin. Rechne den steuernden Ausgang mit, der ja dann
> via Basiswiderstand in die Gegenrichtung zieht.

Beim Einschalten fallen etwa 4,2V ab, beim Ausschalten nur 0,5V. Der
Entladestrom ist also deutlich geringer.


> Mit niederohmigem
> Ableitwiderstand geht es zwar noch schneller
> aber das ist eher bei
> 20KHz Schaltfrequenz interessant.

Nö.
Im Dunkeln sieht man selbst ein LED deutlich aufblitzen, die nur 1µs
eingeschalten wird.
Ich hatte mal beim STK500 das DDRB-Register einen Zyklus vor dem PORTB
gesetzt und mich gewundert, warum die LEDs bei jedem Reset aufblitzten.


Peter
Autor: Sven Pauli (haku) Benutzerseite
Datum: 04.05.2008 11:18

Peter Dannegger wrote:
> Im Dunkeln sieht man selbst ein LED deutlich aufblitzen, die nur 1µs
> eingeschalten wird.
> Ich hatte mal beim STK500 das DDRB-Register einen Zyklus vor dem PORTB
> gesetzt und mich gewundert, warum die LEDs bei jedem Reset aufblitzten.

Das stimmt... ich hab die Dunkeltastung mal spaßeshalber einfach so
realisiert, indem ich direkt hintereinander die Spalte ein- und wieder
ausgeschaltet hab (ASM-Listing sagt: 2 Zyklen). Hat schon gereicht, um
die Anzeige bei Dunkelheit abzulesen.

Antwort schreiben

Die Angabe einer Email-Adresse ist freiwillig. Wenn Sie automatisch per Email über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Suchfunktion und Betreffsuche benutzen - vielleicht gibt es schon einen ähnlichen Beitrag
  • Aussagekräftigen Betreff wählen
  • Im Betreff angeben um welchen Controllertyp es geht (AVR, PIC, ...)
  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
  • JPEG-Dateien (.jpg) nur für Fotos verwenden, Schaltpläne, Screenshots usw. als PNG oder GIF anhängen

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [pre]vorformatierter Text (z.B. Code in anderen Sprachen)[/pre]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel






webmaster@mikrocontroller.netImpressumWerbung auf Mikrocontroller.net