Krijg ADC niet aan de gang in ATTINY85

fripster

Golden Member

Hallo Allemaal,

Ik zit ff vast. Ik heb een simple LED blinker voor de ATTINY85 van het internet aangepast en dat werkt prima. Er zit een wachtlus in het programma die de snelheid van knipperen regelt. Werkt ook prima. Nou als extra heb ik een potmeter aangesloten op een analoge input. En die wil ik de wachtlus (= knippersnelheid) variëren naargelang de stand van de potmeter. En dat lukt dus niet. Ik wil de hoogste 8 bits van de 10bit ADC gebruiken. Die zou in register ADCH moeten staan. Ik denk dat ik alle setup bits goed heb staan. Kan iemand van jullie zien waarom dit niet werkt? De LED knippert wel, maar de snelheid is niet aanpasbaar.

tinyblink3.asm

tn85def.inc

;Tinyblink3: can I blink an ATTINY85 and use pot input for speed?
;picked off the internet and changed/cleaned up
;
;18-10-2024 MP

        .include "tn85def.inc"

        ; setup the registers and their names for this program
        .def    mask    = r16           ; mask register (OUT can only work with registers :-(   )
        .def    ledR    = r17           ; led register
        .def    oLoopR  = r18           ; outer loop register
        .def    work    = r19           ; work register for setups in registers
        .def    iLoopR  = r24           ; inner loop register
        .def    sLoopR  = r25           ; super loop register

        ;setup my local constants and their names
        .equ    oVal    = 0xFF          ; outer loop value 
        .equ    iVal    = 0xFF          ; inner loop value
        .equ    sVal    = 0x20          ; super loop value

        ;indicate start of code segment and originating address
        .cseg
        .org    0x00

        ;setup the analog input for free running use
        ; We're going to use ADC1 on PB2 on pin 7 of the ATTINY85
        ; ADMUX: REFS1 REFS0 ADLAR REFS2 MUX3 MUX2 MUX1 MUX0
        ;          0     0     1     0     0    0    0   1   single ended, 5V ref, input single ended on pb2 on pin7, left aligned
        ldi     work,0b00100001
        out     ADMUX,work
        ;Now setup the ADCSRA register: 128 prescaler, enabled, free running
        ; ADCSRA: ADEN ADSC ADATE ADIF ADIE ADPS2 ADPS1 ADPS0
        ;         1    1    1     0    0    1     1     1
        ldi     work,0b11100111
        out     ADCSRA,work
        ; make sure ADCSRB is cleared to make the thing really free running
        clr     work
        out     ADCSRB,work

        ; Setup the DIDR0 register: disable the digital pin 2 (ADC1) to be used as analog
        ; DIDR0: --- --- ADCD ADC2D ADC3D ADC1D AIN1D AIN0D
        ;         x   x    0    0     0     1     0     0
        ldi     work,(1<<ADC1D)
        out     DIDR0,work

        ;this is the main program itself
        clr     ledR                    ; clear led register
        ldi     mask,(1<<0)             ; load 00000001 into mask register	(a 1 zero times shifted left)
        out     DDRB,mask               ; set PINB0 to output

        ;actual LED toggle action here:
mainlp: eor     ledR,mask               ; toggle PINB0 in led register using mask
        out     PORTB,ledR              ; write led register to PORTB

        ;nested waiting loop with 3 nested loops: 3x8 bits per loop
        ldi     sLoopR,sVal				; initialize super loop count
super:  in      oLoopR,ADCH              ; initialize outer loop count with ADCH value
outer:  ldi     iLoopR,iVal			    ; intialize inner loop count in innerloop register
inner:  dec     iLoopR                  ; decrement inner loop registers
        brne    inner                   ; branch to 'inner' label if iLoop register is not 0
        dec     oLoopR                  ; decrement outer loop register
        brne    outer                   ; branch to 'outer' label if outer loop register is not 0
        dec     sLoopR 					; decrement super loop register
        brne    super                   ; branch to 'super' label if outer loop register is not 0

        ; jump back to begin and do the blinkenlights again and again and...
        rjmp    mainlp                   ; jump back to start
Eens een wirehead,altijd een wirehead.... gopher://fripster.ydns.eu

Ik weet niet of het hier relevant is, maar ik meen me te herinneren dat je soms verplicht beide registers moet lezen, vanwege een mechanisme dat ervoor moet zorgen dat je altijd 2 resultaten krijgt die bij elkaar horen.

Een manager is iemand die denkt dat negen vrouwen in één maand een kind kunnen maken

Volgens mij moet je ADCL en ADCH beide lezen en dan ADCL als eerste.

Nee, hoeft niet. Alleen als je ADCL leest moet je ook ADCH lezen.

Expres om te voorkomen dat je een nieuwe ADC waarde binnen krijgt tussen het lezen van ADCL en ADCH. Nu weet je zeker dat de 2 bytes bij elkaar horen.

Ik zie zo gauw eigenlijk niks fout gaan hier. Zou volgens mij moeten werken.

[Bericht gewijzigd door deKees op vrijdag 18 oktober 2024 15:23:09 (15%)

PE9SMS

Golden Member

Staan in ADCH niet alleen maar de 2 hoogste bits? Even in de datasheet gekeken, volgens mij wel. Je moet specifiek left adjusted instellen m.b.v. ADLAR = 1 in register ADMUX. Zie 17.13.1 en 17.13.3 in de datasheet.

edit: oops, die staat op 1 zie ik nu.

This signature is intentionally left blank.
fripster

Golden Member

ik zal morgen eens het issue isoleren door de ADCH bitwise naar buiten te klokken op een pin, en met de scoop te zien of de bitjes wel veranderen als ik aan de pot draai.

Als iemand nog iets vindt houd ik me aanbevolen...

Eens een wirehead,altijd een wirehead.... gopher://fripster.ydns.eu

Ter info: IK ben bekend met attiny, alhoewel ik de "tiny44" gebruik.

Maar op dit topic kijk ik NIET naar de code omdat ik al dertig jaar geen zin heb om naar assembly te kijken. Als je C code had gepost dan had ik het regel voor regel gecontroleerd wat er mis gaat.

Je hebt nu behoorlijk veel efficientere code dan wanneer je C had gebruikt. En dat levert dus op dat je nu nog wat anders kan doen met de 99.3 % die nog vrij is. Joepie!

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/