Forum: Mikrocontroller und Digitale Elektronik Probleme mit ADC und UART


von Benedikt (Gast)


Lesenswert?

Ich hatte keinen ADC da um Werte mit dem PC zu messen, daher habe ich
ein kleines Programm für den AT90S8535 geschrieben, um die Spannungen
an den 8 Eingängen zu messen.
Durch Befehle kann man die einzelnen Kanäle abfragen, oder zwischen 10
oder 8bit Wählen (Bit ADC10 in Register Bits gesetzt oder nicht).
Ebenso wird entweder einmal oder kontinuierlich umgewandelt und
übertragen (Bit FreeRun in Register Bits, ich verwende dabei nicht den
FreeRun Modus des ADC sondern den Singe Modus !).
Wenn ich nur einmal umwandle (FreeRun gelöscht), dann funktioniert
alles.
Ist aber das Bit FreeRun gesetzt, wird am Ende der ADC Interrupt
Routine nach der Übertragung wieder eine neue Umwandlung gestartet und
somit ununterbrochen Werte übertragen. Aber das funktioniert nicht. Ich
bekomme falsche Werte und Framing Fehler.
Hier der Code der ADC Interrupt Routine:

ADC_COMPLETE_INT:      ;ADC Interrupt
  sbis  USR,UDRE    ; wait for TX to be ready
  rjmp  ADC_COMPLETE_INT; no, wait some more
  sbrc   Bits, ADC10
    rjmp ADC10bitSend
  in r18, ADCL
  in r0, ADCH
  ror r0
  ror r18          ;10bit -> 8bit
  ror r0
  ror r18
  out UDR, r18
  sbrc Bits, FreeRun
  sbi ADCSR, ADSC
reti

ADC10bitSend:
  sbrc Bits, FreeRun
  cbr Bits, 1
  in r18, ADCL
  out UDR, r18
HBWait:
  sbis  USR,UDRE    ; wait for TX to be ready
    rjmp  HBWait    ; no, wait some more
  in r18, ADCH
  out UDR, r18
  sbrc Bits, FreeRun
  sbi ADCSR, ADSC
reti

von ...HanneS... (Gast)


Lesenswert?

Hi...

Sehe ich das richtig?

Du hast in der ADC-ISR eine Warteschleife auf "UART fertig"??

Warteschleifen in ISRs sind sträflich! Du musst die ISR so schnell wie
möglich verlassen, damit andere Interrupts nicht blockiert werden.

Schick das doch mal durch den Simulator (ich kann es nicht, da ich
nicht das komplette Programm habe).

Ich arbeite oft mit ADC (Tiny15, Mega8, 8535/Mega8535), meist lasse ich
den ADC im Free-Running-Mode (Ohne Int!!!) vor sich hin klappern und
lese das nächste Wertepaar aus, wenn ich es brauche, meist durch einen
Timer-Interrupt gesteuert. Dabei muss ich natürlich überprüfen
(rechnen), dass der ADC auch fertig ist, danach richtet sich auch der
Vorteiler. Notfalls (wenn man nicht vorhersagen kann, wann der nächste
Wert ausgelesen werden soll) muss man vor dem Auslesen des ADC eben in
einer Schleife das ADC-Int-Flag abfragen (Datenblatt fragen). Aber dies
im normalen Code und nicht in einer ISR!

Viel Erfolg, Bit- & Bytebruch...
...HanneS...

von Benedikt (Gast)


Lesenswert?

Der ADC ist so eingestellt, dass er langsamer ist als das Senden eines
Bytes. Da der uC nur als ADC arbeitet und sonst nicht viel zu tun hat,
ist eine Warteschlange in der ISR nicht weiter schlimm.

Außerdem stelle ich das Programm auf den Noice canceler Modus um, da
wird der Mikrocontroller sowiso während der Messung angehalten...


Den Fehler habe ich jetzt auch gefunden:
Es lag am Kabel !
Mir fiel auf, dass die Transmit (PC->uC) LED am MAX232 aufleuchtet,
obwohl ich keine Daten sende, nur Daten empfange.
Anscheinend ist der MAX232 (kein orginal MAX, sondern so ein billig
Nachbau) etwas empfindlicher und das Kabel (ca.5m) hat zu hohe
Kapazitäten zwischen den beiden Leitungen. Mit kurzem Kabel geht es
jetzt einwandfrei, seltsam ich hatte damit bisher noch nie Probleme...
Das beste ist immer noch Stereo Audioleitung mit eigener Abschirmung um
jede Leitung.

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.