Forum: Mikrocontroller und Digitale Elektronik einfaches AD-Wandler Programm in Assembler


von BenBu (Gast)


Lesenswert?

Hallo,
Ich versuche seit längerem den AD- Wandler des atmega 8 zum laufen zu 
kriegen. ... leider bis heute ohne Erfolg. :(
Mein Wunsch ist in Assembler eine Spannung auszulesen und entsprechend 
(Schwellwert) zwei LEDs anschalten/ausschalten.

Da es immer nicht klappt habe ich versucht den Wert einfach an einen 
Port ausgeben zu lassen. So wollte ich sehen ob der AD- Wandler was 
macht. Dazu habe ich einfach 8 LEDs angeschlossen.... naja sie leuchten 
alle und das dauerhaft. Egal welche spannung ich einstelle. Daraus 
folgere ich, dass ich etwas am AD-Wandler falsch gemacht habe.

Hier mein Code:
.include "avr.h"

begin:  rjmp main
  reti
  reti
  reti
  reti
  reti
  reti
  reti
  reti
  reti
  reti
  reti
  reti
  reti
  rjmp  onADC
  reti
  reti
  reti
  reti

main:  ldi   r16, lo8  (RAMEND)
  out  SPL, r16
  ldi   r16, hi8  (RAMEND)
  out  SPH, r16
  sei

  sbi  DDRD,0
  sbi  DDRD,1
  sbi  DDRD,2
  sbi  DDRD,3
  sbi  DDRD,4
  sbi  DDRD,5
  sbi  DDRD,6
  sbi  DDRD,7

  ldi  r20,0b00000000
  out  PORTD,r20

  ldi  r16,0
  out  ADMUX,r16
  ldi  r25,0b11011101
  out  ADCSRA,r25

loop:
  rjmp  loop

onADC:  in  r26,ADCL
  in  r27,ADCH
  asr  r27
  ror  r26
  asr  r27
  ror  r26
  mov  r25,r26
  out  PORTD,r25
  sbi  ADCSRA,6
  reti


............................................
Ich hoffe ihr könnt meinen Fehler finden oder mir eine vielleicht 
einfachere Möglichkeit zeigen.

Vielen lieben Dank
und liebe Grüße
BenBu

von Assembleranfänger (Gast)


Lesenswert?

Ich hab jetz nicht nachgeschaut ob diese Befehlssequenz

BenBu schrieb:
> ldi  r25,0b11011101
> out  ADCSRA,r25

den ADC Interrupt enabled, und ob der Interrupt Vektor
stimmt, aber den Globalen Interrupt Enable (sei())
müsstest du sicherlich setzen um jemals in die ISR
zu kommen.

von Assembleranfänger (Gast)


Lesenswert?

... huch ... kaum zweimal hingeschaut und schon ist
er da, der SEI.

von Ziegenpeter (Gast)


Lesenswert?

BenBu schrieb:
> ldi  r25,0b11011101
> out  ADCSRA,r25


Warum nicht lieber so? Dann weißt du (und die Leute, die dir helfen 
sollen) auch am nächsten Tag noch, was die einzelnen Bits bedeuten:
1
ldi r16, (1<<ADEN) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (0<<ADPS0) ;// adc enabled, interrupt enabled, prescaler div factor 64
2
out ADCSRA, r16


und...

BenBu schrieb:
> begin:  rjmp main
>   reti
>   ...
>   rjmp  onADC
>   ...

==>
1
begin:  rjmp main
2
.org ADCCaddr
3
rjmp onADC

von MWS (Gast)


Lesenswert?

BenBu schrieb:
>   ldi  r16,0
>   out  ADMUX,r16

AREF ist mit irgendetwas verbunden?

von BenBu (Gast)


Lesenswert?

Nein... AREF ist frei

von MWS (Gast)


Lesenswert?

BenBu schrieb:
> Nein... AREF ist frei

Schlecht oder auch gut. Im Falle in ADMUX lauter Nullen reinzuschreiben: 
schlecht.

von Jobst M. (jobstens-de)


Lesenswert?

Für ATmega48 im Pollingbetrieb:
1
; ADC konfigurieren
2
        ldi     tmp1,   0b01000101      ; 01   AVCC with external capacitor at AREF pin
3
        sts     ADMUX,  tmp1            ; 0    ADLAR - right adjusted
4
                                        ; 0    reserved
5
                                        ; 0101 ADC5 (Pin28)
6
7
        ldi     tmp1,   0b00000000      ; Auto-Trigger = Free running mode (not used)
8
        sts     ADCSRB, tmp1
9
        ldi     tmp1,   0b00100000      ; ADC5 (Pin28) nur analog
10
        sts     DIDR0,  tmp1
11
12
13
GET_ADC:
14
        ldi     tmp1,   0b11000111      ; Wandlung wird gestartet
15
        sts     ADCSRA, tmp1            ; 1  ADC enable ; 1  Start conversion ; 0  Autotrigger off ; 0  Interrupt Flag ; 0  Interrupt enable ; 111  Prescaler
16
warteadc:
17
        lds     tmp1,   ADCSRA          ; Werte ADSC aus
18
        andi    tmp1,   64
19
        brne    warteadc                ; solange ADSC gesetzt ist warten
20
        lds     IST_L,  ADCL            ; Ergebnis
21
        lds     IST_H,  ADCH
22
        RET

Vielleicht hilft es weiter ...

Gruß

Jobst

von S. Landolt (Gast)


Lesenswert?

Nachfolgendes läuft auf dem ATmega16A, in Anlehnung an das 
Originalprogramm; ich habe keinen ATmega8, es sollte auf diesem aber 
auch funktionieren.
1
.include "m16Adef.inc"
2
3
.def    tmp0                = r16
4
.def    tmpi                = r18           ; reserviert fuer Interrupt
5
6
.org $0000
7
    rjmp    reset
8
.org ADCCaddr
9
    in      tmpi,ADCH                       ; reicht bei ADLAR und 8 bit
10
    out     PORTD,tmpi
11
    sbi     ADCSRA,ADSC                     ; 'free running' "von Hand"
12
    reti
13
14
reset:
15
    ldi     tmp0,high(RAMEND)
16
    out     SPH,tmp0
17
    ldi     tmp0,low(RAMEND)
18
    out     SPL,tmp0
19
    ldi     tmp0,$FF                        ; D komplett auf Ausgang
20
    out     DDRD,tmp0
21
22
    ldi     tmp0,(1<<REFS0)+(1<<ADLAR)      ; Ref: "AVCC with ext. cap. at AREF pin"
23
    out     ADMUX,tmp0                      ; ADC0
24
    ldi     tmp0,(1<<ADEN)+(1<<ADIE)+(1<<ADPS1)+(1<<ADPS0) ; 1 MHz /8
25
    out     ADCSRA,tmp0
26
    sei
27
    sbi     ADCSRA,ADSC                     ; und los geht das
28
29
    rjmp    pc

von BenBu (Gast)


Lesenswert?

Erst mal danke für eure Hilfe.
Leider funktioniert das alles noch nicht.
Ich habe jetzt mit einigem Probieren rausbekommen dass der Low Teil des 
AD- Signals immer 11111111 ist .... warum auch immer. ... ich denke da 
ist irgendwo das Problem. ich kann es nur nicht finden. Vielleicht kennt 
ja jemand von euch so einen Fall.

von S. Landolt (Gast)


Lesenswert?

Wie sieht das aktuelle Programm aus, und welche Spannung liegt an 
ADC0==PC0?

von BenBu (Gast)


Lesenswert?

.include "avr.h"

begin:  rjmp main
  reti
  reti
  reti
  reti
  reti
  reti
  reti
  reti
  reti
  reti
  reti
  reti
  reti
  reti
  reti
  reti
  reti
  reti

main:  ldi   r16, lo8  (RAMEND)
  out  SPL, r16
  ldi   r16, hi8  (RAMEND)
  out  SPH, r16


  sbi  DDRD,0
  sbi  DDRD,1
  sbi  DDRD,2
  sbi  DDRD,3
  sbi  DDRD,4
  sbi  DDRD,5
  sbi  DDRD,6
  sbi  DDRD,7
  ldi  r26,0b00000000
  ldi  r27,0b00000000
  ldi  r20,0b00000000
  out  PORTD,r20

  ldi  r16,0
  out  ADMUX,r16
  ldi  r25,0b11011101
  out  ADCSRA,r25

loop:  sbi  ADCSRA,ADSC
  ldi  r25,0b00000000
  out  PORTD,r25
warte:  sbic  ADCSRA,ADSC
  rjmp  warte
  in  r26,ADCL
  in  r27,ADCH

  mov  r25,r26
  out  PORTD,r25
  ldi  r19,200
warteloop1:  ldi  r18,200
warteloop:  dec  r18
  brne  warteloop
  dec  r19
  brne  warteloop1

  rjmp  loop

von BenBu (Gast)


Lesenswert?

also an AREF sind jetzt 5 Volt und PIN C 0 ist durch ein Poti 
einstellbar

von S. Landolt (Gast)


Lesenswert?

> also an AREF sind jetzt 5 Volt und PIN C 0 ist durch
> ein Poti einstellbar

Sind Sie da sicher? Also bei mir läuft Ihr Programm.
(Ich hoffe mal, dass das Ganze auch wirklich für einen ATmega8 
assembliert wird)

von BenBu (Gast)


Lesenswert?

ja also die 5 Volt sind drann (bestellte experimentier und programmier- 
Platine) und auf dem Schaltplan sind da 5 V eingezeichnet. ... 
Vielleicht tausche ich mal den atmega 8 durch einen neuen.

von BenBu (Gast)


Lesenswert?

Also ich habe jetzt den Atmega getauscht. Leider ohne Erfolg.
Ich habe ja die LEDs als ausgang geschaltet. Egal wie ich das Poti 
verstelle, sie bleiben immer alle an.

... Aber wenn das Programm funktionsfähig ist frage ich mich was ich 
falsch mache...

von S. Landolt (Gast)


Lesenswert?

Lassen Sie mal Folgendes laufen, die LEDs müssten damit hochzählen.
1
  sbi  DDRD,0
2
  sbi  DDRD,1
3
  sbi  DDRD,2
4
  sbi  DDRD,3
5
  sbi  DDRD,4
6
  sbi  DDRD,5
7
  sbi  DDRD,6
8
  sbi  DDRD,7
9
10
loop:
11
  in   r16,PORTD
12
  inc  r16
13
  out  PORTD,r16
14
warte:
15
  adiw ZL,1
16
  brne warte
17
 rjmp  loop

von BenBu (Gast)


Lesenswert?

Das Funktioniert.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

BenBu schrieb:
> begin:  rjmp main
>   reti
>   reti
>   reti
>   reti
>   reti
>   reti
>   reti
>   reti
>   reti

Gewöhn dir das am besten gleich wieder ab, denn das haut so nicht hin. 
Lies die Vektortabelle im Datenblatt, Seite 47:

The most typical and general program setup for the Reset and Interrupt 
Vector Addresses in
ATmega8 is:
1
addressLabelsCode Comments
2
$000         rjmp  RESET          ; Reset Handler
3
$001         rjmp  EXT_INT0       ; IRQ0 Handler
4
$002         rjmp  EXT_INT1       ; IRQ1 Handler
5
$003         rjmp  TIM2_COMP      ; Timer2 Compare Handler
6
$004         rjmp  TIM2_OVF       ; Timer2 Overflow Handler
7
$005         rjmp  TIM1_CAPT      ; Timer1 Capture Handler
8
$006         rjmp  TIM1_COMPA     ; Timer1 CompareA Handler
9
$007         rjmp  TIM1_COMPB     ; Timer1 CompareB Handler
10
$008         rjmp  TIM1_OVF       ; Timer1 Overflow Handler
11
$009         rjmp  TIM0_OVF       ; Timer0 Overflow Handler
12
$00a         rjmp  SPI_STC        ; SPI Transfer Complete Handler
13
$00b         rjmp  USART_RXC      ; USART RX Complete Handler
14
$00c         rjmp  USART_UDRE     ; UDR Empty Handler
15
$00d         rjmp  USART_TXC      ; USART TX Complete Handler
16
$00e         rjmp  ADC ; ADC Conversion Complete Handler
17
$00f         rjmp  EE_RDY         ; EEPROM Ready Handler
18
$010         rjmp  ANA_COMP       ; Analog Comparator Handler
19
$011         rjmp  TWSI ; Two-wire Serial Interface Handler
20
$012         rjmp  SPM_RDY        ; Store Program Memory Ready Handler
21
;
22
$013  RESET: ldi        r16,high(RAMEND); Main program start

ein rjmp <Label> hat nun mal eine andere Länge als ein 'reti' und 
deswegen zeigen deine Vektoren, wenn du sie benutzt, einfach nur in die 
Botanik.

von S. Landolt (Gast)


Lesenswert?

Dann stimmt vermutlich die Spannung an AREF und/oder ADC0 nicht. Können 
Sie diese messen?

von Mikrocon T. (-42-)


Lesenswert?

Matthias S. schrieb:
> ein rjmp <Label> hat nun mal eine andere Länge als ein 'reti'

Nööö, sind beide gleich lang. Ein JMP ist aber länger.

Trotzdem ist eine unkommentierte Sprungtabelle großer Mist und eine gute 
Fehlerquelle.

MfG

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Matthias S. schrieb:
> ein rjmp <Label> hat nun mal eine andere Länge als ein 'reti' und
> deswegen zeigen deine Vektoren, wenn du sie benutzt, einfach nur in die
> Botanik.

Oh, ich sehe gerade, das es beim Mega 8 zufällig doch passt, weil er nur 
rjmps nimmt. Bei anderen klappt das aber nicht so.

von BenBu (Gast)


Lesenswert?

DANKE... AREF war nicht 5 Volt sondern 0... Dann ist auvch der Fehler 
klar. Ich danke euch allen und werde all eure Ratschläge jetzt noch mal 
in ruhe durchsehen und verinnerlichen
DNAKE noch mal.

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.