ADC lässt sich mit cbi ADEN nicht ausschalten

Gast #1665555
Lesenswert?

ich weis nicht wieso aber, es lässt sich irgendwie nicht machen, dass 
ich per ADEN den ADC ausschalte

die Unterprogramme habe ich der Textdatei beschrieben
1
;**********************************Header**************************************
2
;* Projektname:  Roboter-Linienverfolgung                    *
3
;* Name des Erstellers: Shamoon Andy                      *
4
;* Zuletzt aktualisiert: 7.4.2010                        *
5
;* Beschreibung: Ein ROboter, der einer ca1,5-2cm Linie nachfaährt        *                                      
6
;******************************************************************************
7

8

9
;*****************************Initialisierungen********************************
10
.include "m16def.inc" ;Definitionsdatei des Mega8
11

12
;Stackpointer-init***********
13
rjmp Stack_init
14
Weiter:
15

16
;ADC-init***********
17
rcall ADC_init  ;Externe Refernz, Prescaler = 128, Enable ADC = true, Kanal 0
18

19
;*****************Deklarierete Funktionen und Subroutinen**********************
20

21
;*************************Variablendeklarationen*******************************
22

23
;*****************************Ein-Ausgänge*************************************
24
  ser r16
25
  out DDRB, r16  ;PORTB als ausgabeport
26

27
;******************************************************************************
28

29

30
;*****************************Hauptprogramm************************************
31
    Hauptprogramm:;Do
32
call    EnableADC
33
call    DisableADC
34
call     ADC_Kanal3
35
call      StartADC
36
          in r16, ADCH
37
          com r16
38
          out PORTB, r16
39
call      EndADC
40
rjmp   Hauptprogramm ;Loop
41

42

43

44
;***********************Unterprogramme/Funktionen******************************
45
;################################################################################
46
.include "Division8Bit+Rest.asm"   ;8 Bit division    //call division
47
.include "WaitCA1s.asm"        ;Warte ca 1s ab    //call wait
48
.include "Stack_init.asm"      ;Stackinitialisieung//call Stack_init
49
.include "ADC_init.asm"        ;ADCinitialisieung  //call ADC_init
50
.include "EnableADC.asm"      ;ADC erlauben    //call EnableADC
51
.include "DisableADC.asm"      ;ADC sperren    //call DisableADC
52
.include "StartADC.asm"        ;Starte Messung    //call StartADC
53
.include "EndADC.asm"        ;Stoppe Messung    //call EndADC
54
.include "ADC_Kanal0.asm"      ;Wechsel zu Kanal 0 //call ADC_Kanal0
55
.include "ADC_Kanal1.asm"      ;Wechsel zu Kanal 1 //call ADC_Kanal1
56
.include "ADC_Kanal2.asm"      ;Wechsel zu Kanal 2 //call ADC_Kanal2
57
.include "ADC_Kanal3.asm"      ;Wechsel zu Kanal 3 //call ADC_Kanal3
58
;################################################################################
Angehängte Dateien:
#1665571
Lesenswert?

> .include "m16def.inc" ;Definitionsdatei des Mega8

Da ist entweder der Kommentar oder der Filename falsch.  Die beiden 
genannten Prozessoren sind sich aber tatsächlich sehr ähnlich, so dass 
das noch nicht der gesuchte Fehler sein muss.

Was aber der Fehler ist, hast Du weder genau genug beschrieben noch hast 
Du den nötigen Code geliefert.  Wenn man nach dem sucht, finden sich nur 
ein paar .include-Direktiven.
Gast #1665576
Lesenswert?

Hallo,

in Inhalt.txt steht:

> DisableADC:
> cbi ADMUX, ADEN
> ret

> EnableADC:
> sbi ADMUX, ADEN
> ret

Hast du nicht ins Datenblatt geschaut? Das Bit ADEN ist nicht im ADMUX, 
sondern im ADCSRA-Register zu finden ...
Gast #1665577
Lesenswert?

>Hast du nicht ins Datenblatt geschaut? Das Bit ADEN ist nicht im ADMUX,
>sondern im ADCSRA-Register zu finden ..

hah danke, natürlich habe ich im Datenblatt nachgeschaut, jedoch merke 
ich mir die Register nie und habe hier wahrscheinlich irrtümlich das 
falsche genommen

lg andy
#1665584
Lesenswert?

Ah, den Code hast Du nachgeliefert, das hat sich mit meiner Antwort 
überschnitten.

Und der Fehler äüßert sich nun genau worin?

Übrigens:  StartADC wartet nicht, bis der ADC fertig ist, sondern kehrt 
in diesem Fall sofort zurück.  Das kann vielleicht noch gewünscht sein. 
Aber für den Fall, dass der ADC 'fertig' meldet, läuft es in die Wüste 
(in den hier nicht beschriebenen Code danach).
Gast #1665627
Lesenswert?

Hi

Hat es einen bestimmten Grund, das du dein Programm auf zig, fast leere, 
Dateien verteilst?
Ebenfalls ist es recht sinnfrei, Programmteile, die nur einmal benötigt 
werden, (z.B. Stackinitialisierung) in Unterprogramme zu packen.
Sinnvoller ist es, z.B. die Umschaltung der Kanäle in einem 
Unterprogramm zu machen. Die Kanalnummer wird einfach in einem Register 
übergeben.
Im Datenblatt findest du übrigens ein Codebeispiel aus dem du ersehen 
kannst, wie man eine ADC-Wandlung startet und auf das Ergebnis wartet.

MfG Spess
#1665813
Lesenswert?

> Hat es einen bestimmten Grund, das du dein Programm auf zig, fast leere,
> Dateien verteilst?

Ich mach's auch manchmal, weil Blättern zum anderen Editorfenster 
schneller geht als Scrollen und Zurückscrollen im längeren Quältext. Und 
ich muss (dank Alzheimer Light) oft nachschaun, wie ich denn nun meine 
Labels auf Konstanten, Register, RAM-Bereiche und Routinen genannt habe. 
Daher rechnet sich das Aufsplitten des Quältextes gelegentlich. Meist 
kopiere ich die Teile aber später wieder zusammen.

Bei den restlichen Punkten stimme ich Dir zu.

Ich kann mir aber gut vorstellen, dass man versucht, modular zu 
programmieren und wie bei einer Hochsprache alles in "Funktionen" zu 
packen. Das täuscht Übersichtlichkeit vor, verbraucht aber aufgrund 
unnötiger Sprünge und Rücksprünge unnötig Ressourcen. Dieselbe 
Übersichtlichkeit erreicht man auch mit ein paar Kommentaren. ;-)

...
#1665839
Lesenswert?

Hannes Lux schrieb:

> Ich kann mir aber gut vorstellen, dass man versucht, modular zu
> programmieren und wie bei einer Hochsprache alles in "Funktionen" zu
> packen. Das täuscht Übersichtlichkeit vor, verbraucht aber aufgrund
> unnötiger Sprünge und Rücksprünge unnötig Ressourcen.

Das ist einer der Vorteile einer Hochsprache, sie kann beim Optimieren 
alle nur einmal aufgerufene Funktionen inlinen.


Peter
#1665879
Lesenswert?

Na ja
Bei sowas
1
ADC_Kanal1:
2
  push r16
3
    ldi r16, 0x21
4
    out ADMUX, r16
5
  pop r16
6
ret

hat der Programmierer schon ein wenig  übertrieben. Das ist zwar (aus 
Registersicht) alles abgesichert, jedoch stehen die Chancen, dass dieser 
Code in einer tief verschatelten Aufrufhierarchie aufgerufen wird, nicht 
besonders gut. Benutzt man, wie Peter meint, ein paar Scratchpad 
Register, die jeder nach Gutdünken verändern darf (in dem Fall r16), 
dann ist man ds 'Problem' erst mal los.

Der Programmierer wollte eben Universalroutinen haben, die er überall 
einsetzen kann ohne sich grossartig Gedanken zu machen. Dagegen ist 
erstmal nicht viel zu sagen, ausser: Machs dann wenigstens richtig! Wenn 
die Funktion nur einen bestimmten Kanal einstellen soll, dann soll sie 
auch nur das tun! D.h. die restlichen Bits in ADMUX sind für die 
Funktion tabu und dürfen nicht verändert werden.

So wie sie jetzt ist, ist diese Funktion nicht Fisch und nicht Fleisch.
Gast #1666285
Lesenswert?

>Übrigens:  StartADC wartet nicht, bis der ADC fertig ist, sondern kehrt
>in diesem Fall sofort zurück.
wie lässt es sich denn anders schreiben?


>So wie sie jetzt ist, ist diese Funktion nicht Fisch und nicht Fleisch.
1
ADC_Kanal0:
2
  push r16
3
    in r16, ADMUX  
4
    cbr r16, 15    ;rechten 4 bits löschen
5
    sbr r16, 0    ;Kanal 0
6
    out ADMUX, r16  ;ausgabe 
7
  pop r16
8
ret

ist es so besser?
Gast #1666427
Lesenswert?

Soweit ich weiss gibt man bei sbr  cbr genauso wie bei sbi  cbi als 
zweiten Operanden die Bitnummer an.
D.h.:

cbr r16, 3

entspricht:

ori r16, 1<<3



Also wäre "sbr r16, 0" => "ori r16, 1". Damit würde man Kanal 1 setzen 
nicht 0.
Gast #1666487
Lesenswert?

Hi

>Soweit ich weiss gibt man bei sbr  cbr genauso wie bei sbi  cbi als
>zweiten Operanden die Bitnummer an.

Soweit das Instruction Set richtig ist, kann der 2.Operant einen Wert 
von 0..$FF annehmen.
Entspricht einem ANDI mir dem Komplement des Operanten.

MfG Spess
#1666544
Lesenswert?

Karl heinz Buchegger schrieb im Beitrag #1665879

> ...

> Wenn
> die Funktion nur einen bestimmten Kanal einstellen soll, dann soll sie
> auch nur das tun! D.h. die restlichen Bits in ADMUX sind für die
> Funktion tabu und dürfen nicht verändert werden.

Das ist generell erstmal richtig und wird von mir nicht angezweifelt.

Bei ADMUX sehe ich das aber anders. Da gehören die Bits einfach 
zusammen. Zu jedem ADC-Kanal gehört auch die Referenzeinstellung und 
auch (sofern es auch in ADMUX liegt) die Formatierung (links/rechts) des 
Ergebnisses (ADLAR). Hier sehe ich Referenz und Resultatformat als 
Bestandteil (Zusatzparameter) des Kanals. Somit ziehe ich das direkte 
Zuweisen des ganzen Bytes vor. Ich bevorzuge dabei ein temporäres 
Register, das nicht gesichert werden muss und undeutsch 
"Scratchregister" genannt werden könnte.

Ich generiere dafür aber keine extra "Funktion". Ist nur ein Kanal 
abzufragen, so wird das im Ini-Bereich eingestellt, sind mehrere Kanäle 
abzufragen, so wird das Setzen von ADMUX Bestandteil der zyklisch 
aufgerufenen Ausleseroutine (ADC-Interrupt oder durch Timer 
synchronisiertes Auslesen).
Dieser zyklisch aufgerufene Job legt das geholte ADC-Ergebnis in ein 
Array (mit oder ohne Mittelwertbildung), zählt den Index hoch (oder 
runter) und begrenzt ihn, holt aus einem weiteren Array (mit demselben 
Index, in ASM durch Zugriff über LDD) den ADMUX-Wert für die nächste 
Wandlung und startet den ADC wieder. Somit erfolgt im Hintergrund reihum 
die Wandlung aller Kanäle mit den zugehörigen Parametern (Referenz, 
Format), ohne dass man sich weiter darum kümmern muss.
Die Mainloop holt sich die Werte dann aus dem Array, da liegt dann immer 
der letzte Wert bzw. der Mittelwert der letzten Messungen. Und das zu 
jeder Zeit für jeden Kanal.

...
Gast #1667016
Lesenswert?

>Soweit ich weiss gibt man bei sbr  cbr genauso wie bei sbi  cbi als
>zweiten Operanden die Bitnummer an.
>D.h.:

>cbr r16, 3

>entspricht:

>ori r16, 1<<3



>Also wäre "sbr r16, 0" => "ori r16, 1". Damit würde man Kanal 1 setzen
>nicht 0.

ich habs schon ausgetestet, was ich stehen habe passt


>Ich generiere dafür aber keine extra "Funktion". Ist nur ein Kanal
>abzufragen, so wird das im Ini-Bereich eingestellt, sind mehrere Kanäle
>abzufragen, so wird das Setzen von ADMUX Bestandteil der zyklisch
>aufgerufenen Ausleseroutine (ADC-Interrupt oder durch Timer
>synchronisiertes Auslesen).
>Dieser zyklisch aufgerufene Job legt das geholte ADC-Ergebnis in ein
>Array (mit oder ohne Mittelwertbildung), zählt den Index hoch (oder
>runter) und begrenzt ihn, holt aus einem weiteren Array (mit demselben
>Index, in ASM durch Zugriff über LDD) den ADMUX-Wert für die nächste
>Wandlung und startet den ADC wieder. Somit erfolgt im Hintergrund reihum
>die Wandlung aller Kanäle mit den zugehörigen Parametern (Referenz,
>Format), ohne dass man sich weiter darum kümmern muss.
>Die Mainloop holt sich die Werte dann aus dem Array, da liegt dann immer
>der letzte Wert bzw. der Mittelwert der letzten Messungen. Und das zu
>jeder Zeit für jeden Kanal.

sry is mir im Moment viel zu hoch

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