Stránka 1 z 1

mega8 ADC nedokončí převod

Napsal: 15 úno 2013, 19:41
od Jenda_KL
Občsas, tak jednou za dvě hodiny přestane převodník číst a pomůže jenom reset.
Řekl bych, že nedojde k tomu přerušení od ADC.
Je ještě použito TIM0 a v mainu je jen SLEEP.
Řešenim je kontrolovat časovačem, ale rád bych našel příčinu.
kód je zřejmě ok, ale stalo se mi to už u druhé aplikace.

//INIT ADC
admux = $0C0 //internal 2.56Vref,chan0
adcsra = $0C8 //ADEN,ADSC,ADIE

Kód: Vybrat vše

ADCCC:
  ldi XL,low(ip1)   //$08-$0D (ip1-ip6) reg s hodnotou, celkem 6
  ldi XH,high(ip1)   //$01 (ip1-ip6)
  lds a,muxpos    //offset 0-5 ; a=r16 b=r17
  add XL,a
  in  b,ADCL
  st  X,b
  in  b,ADCH     //naprazdno
  inc a
  cpi a,6
  brne muxok
   ldi a,0    //reset offsetu
  muxok:
  sts muxpos,a
  ori a,$0C0
  ldi b,$0C8
  out admux,a
  out adcsra,b
RETI

Napsal: 15 úno 2013, 19:45
od Andrea
To tam tak vesele měníš v přerušení registry a flagy, aniž bys je ukládal a obnovoval?

Napsal: 15 úno 2013, 20:28
od Jenda_KL
Ukádal a obnovoval ? nikde jinde se nepoužívají.
Je problém zápis 0 do ADIF ? To je jediný flag co tam je.
Zápisem C8 se změní jen ADSC 0->1, ADIF zůstává 0
Nějak nerozumím tomu "Alternatively,
ADIF is cleared by writing a logical one to the flag. Beware that if doing a Read-Modify-
Write on ADCSRA, a pending interrupt can be disabled."
Ale to by se mělo týkat zápisu do ADCSRA mimo rutinu, když je hotová konverze a čeká se na ISR, což tady není.

Napsal: 15 úno 2013, 20:33
od Andrea
No jak myslíš. A měla jsem na mysli flagy v SREG.

Napsal: 15 úno 2013, 20:40
od Jenda_KL
jasně, jde ale vždy jen ADCCC nebo TIM0, jak zůstane SREG při návratu do spánku (po RETI) musí být přeci jedno.

Napsal: 15 úno 2013, 21:23
od Andrea
Když to říkáš, já ten zbytek programu nevidím.

Napsal: 15 úno 2013, 21:39
od Jenda_KL

Kód: Vybrat vše

.include "m8def.inc"
//dale definice registru
.cseg
.org $0    RJMP init
.org $09 RJMP tim0
.org $0E RJMP adccc
.org $30 RETI

ADCCC uz tu bylo

// ===============  TIMER 0 ISR / 31.25kHz
TIM0:
inc rpwm    //=r22

lds  b,ip1         ;chan1 reset
lds  a,dpwm1
andi a,$1F
lsl  a
lsl  a
lsl  a
ori  a,$07
cp   b,a
brlo ex_c1
  cbi portd,pd0
  cbi portd,pd1
  ex_c1:
// ---- dalsi kanaly

cpi rpwm,$1E
brlo texit
  ldi rpwm,$0FF

  lds a,dpwm1   ;chan1 set ano nebo ne
  sbrc a,7
  sbi portd,pd0
  sbrs a,7
  cbi portd,pd0
  sbrc a,6
  sbi portd,pd1
  sbrs a,6
  cbi portd,pd1

// ---- dalsi kanaly
texit:
RETI
// =============== INIT
INIT:
ldi a,low(RAMEND)
ldi b,high(RAMEND)
out sph,b
out spl,a

ldi a,0b10000000         //SE SM2 SM1 SM0 ISC11 ISC10 ISC01 ISC00
out MCUCR,a
//dale porty,adc a vychozi hodnoty registru, smazani RAM

;TIMER 0
ldi a,1
out tccr0,a
;INT
ldi a,1
out timsk,a

sei
// =============== MAIN
loop:
SLEEP
rjmp loop

Napsal: 17 úno 2013, 16:01
od Jenda_KL
Napadla mě věc kterou jsem se nedočetl.
Je potřeba ADC vypínat při změně kanálu, čiže ADEN 1->0 , změnit kanál, ADEN 0->1 ?

Napsal: 18 úno 2013, 10:32
od Jenda_KL
Ne, přepnutí kanálu tímto způsobem toreticky nevadí, ale nějaký vliv má, protože bez přepínání to neudělá.
Je to skutečně tak, že se nenastaví ADIF a taky se nesnuluje ADSC. Otázka - vzhledem k tomu že to točí motůrkama je tu možnost takového rušení že to resetne jen ADC?

Asi to vzdávám, kombinace 555+LM393+4013 to jistí.

Napsal: 18 úno 2013, 11:24
od Andrea
A zkusil jsi to bez sleepu?
Mimochodem, jak zjišťuješ, jestli se nastavil ADIF a shodil ADSC nebo ne?

Napsal: 18 úno 2013, 14:20
od Jenda_KL
Tady to zjišťuju tak, že ADCSRA čtu v INT_TIM0 a posílám bity na volné výstupy, jinak to asi nejde.

V té druhé aplikaci to je bez sleepu a bez přerušení od ADC a to tak, že v hlavní smyčce se testuje kdy zmizí ADSC. Tam se problém se "zatuhnutím" měřených hodnot vyskytoval občas taky.