Läsa värde med ADC på AVR? (asm)
Re: Läsa värde med ADC på AVR? (asm)
Okej, jag har testat det nu, men resultatet är att alla dioder lyser hela tiden, oavsett om jag har potentiometern inkopplad eller inte. När jag mäter spänningen på mittenpinnen på potentiometern och vrider så ändras den mellan 0 och 5 Volt, så då vet man ju att det i alla fall finns en reglerbar spänning in på ADC5-pinnen.
Måste någon mer hårdvara vara inkopplad, tex motstånd, drossel eller kondensator? Eller ska det fungera med enbart GND, VCC och reglerbar spänning på ADC5?
Det här förstår jag inte riktigt:
"Voltage Reference Selections for ADC" i ADMUX?
"AREF, Internal Vref turned off" eller "AVCC with external capacitor at AREF pin"
Ska jag koppla potentiometern på VCC och GND eller ska AREF och AVCC vara med någonstans?
Måste någon mer hårdvara vara inkopplad, tex motstånd, drossel eller kondensator? Eller ska det fungera med enbart GND, VCC och reglerbar spänning på ADC5?
Det här förstår jag inte riktigt:
"Voltage Reference Selections for ADC" i ADMUX?
"AREF, Internal Vref turned off" eller "AVCC with external capacitor at AREF pin"
Ska jag koppla potentiometern på VCC och GND eller ska AREF och AVCC vara med någonstans?
Re: Läsa värde med ADC på AVR? (asm)
Det ser ut som om du fortfarande bara gör en omvandling. Du måste starta om omvandlingen (t.ex. i slutet av avbrotts-rutinen) eller köra free-running-mode som hatten sade ovan.
Re: Läsa värde med ADC på AVR? (asm)
Jasså, räcker det inte att sätta ADEN-biten(AD-enable)? Eller gör jag nått galet där när jag lägger ADCSRA i temp, kör en sbr och sedan lägger tillbaka värdet i ADCSRA? Kanske finns bättre sätt att sätta ADEN-biten?
Avbrottsrutinen ser ju ut såhär:
Avbrottsrutinen ser ju ut såhär:
Kod: Markera allt
Ultra: INTERRUPT ;Börja avbrottsrutinen med MACRO INTERRUPT
lds adc_data, ADCL ;Lagra värdet från ADCL i adc_data
lds temp, ADCSRA ;Ladda temp med ADCSRA...
sbr temp, (1<<ADEN) ;..och sätt ADENable biten
sts ADCSRA, temp ;Lägg tillbaka värdet i ADCSRA
INTERRUPT_END ;Avsluta avbrottsrutinen med MACRO INTERRUPT_END
Re: Läsa värde med ADC på AVR? (asm)
Aha! Nu ser jag en sak. Det är ju ADSC som jag ska sätta i avbrottsrutinen. Jag ska testa det efter jobbet.
Såhär:
Såhär:
Kod: Markera allt
Ultra: INTERRUPT ;Börja avbrottsrutinen med MACRO INTERRUPT
lds adc_data, ADCL ;Lagra värdet från ADCL i adc_data
lds temp, ADCSRA ;Ladda temp med ADCSRA...
sbr temp, (1<<ADSC) ;..och sätt ADSC biten
sts ADCSRA, temp ;Lägg tillbaka värdet i ADCSRA
INTERRUPT_END ;Avsluta avbrottsrutinen med MACRO INTERRUPT_END
Re: Läsa värde med ADC på AVR? (asm)
Ok. Nu har jag testat ditt program. Jag gjorde några ändringar för att det skulle fungera.
I kommentaren står Left adjusted men du sätter inte den biten. Sedan har du sagt att du skall ha AREF som referens. Har du referensspänning på den pinnen? Annars kan du använda AVCC i stället:
I huvudloopen behöver du inte ha med sei, det räcker att köra den en gång innan loopen.
Om du sedan vill ha vänsterjusterat resultat så är det nog ADCH du vill läsa i avbrottsrutinen samt, som du själv kom på när jag skrev detta, att du skall sätta ADSC i stället för ADEN:
Kod: Markera allt
;ADC - AREF(Internal Vref turned off), Left adjusted, ADC5
ldi temp, (0<<REFS1)+(0<<REFS0)+(0<<ADLAR)+0b101
Kod: Markera allt
ldi temp, (0<<REFS1)+(1<<REFS0)+(1<<ADLAR)+0b101
Om du sedan vill ha vänsterjusterat resultat så är det nog ADCH du vill läsa i avbrottsrutinen samt, som du själv kom på när jag skrev detta, att du skall sätta ADSC i stället för ADEN:
Kod: Markera allt
lds adc_data, ADCH ;Lagra värdet från ADCH i adc_data
lds temp, ADCSRA ;Ladda temp med ADCSRA...
sbr temp, (1<<ADSC) ;..och sätt ADSCable biten
sts ADCSRA, temp ;Lägg tillbaka värdet i ADCSRA
Re: Läsa värde med ADC på AVR? (asm)
Tusen tack! Det låter rätt. Nu börjar jag förstå varför det inte har fungerat.
Det är nog igentligen själva komentaren "Left adjusted" som är fel eftersom jag tänkte läsa de åtta lägsta bitarna i ADC-värdet och då ska ju ADLAR inte sättas och sedan läser man ADCL. Men man kan ju även sätta ADLAR och läsa ADCH istället, för då får man väll de åtta högsta bitarna i ADC-värdet.
Jag ska testa detta senare och återkommer med hur det gick.
Det är nog igentligen själva komentaren "Left adjusted" som är fel eftersom jag tänkte läsa de åtta lägsta bitarna i ADC-värdet och då ska ju ADLAR inte sättas och sedan läser man ADCL. Men man kan ju även sätta ADLAR och läsa ADCH istället, för då får man väll de åtta högsta bitarna i ADC-värdet.
Jag ska testa detta senare och återkommer med hur det gick.
Re: Läsa värde med ADC på AVR? (asm)
Men om du hade tänkt läsa bara de 8 lägsta bitarna så hade det blivit fel - då hade du fått ett värde från 0-255 som börjar om från noll 4 gånger när du ändrar inspänningen från 0 till 5 volt... Läser du de 8 högsta bitarna blir det rätt - dvs du får ett 8-bitars värde som motsvarar spänningen : Värde = 256*Uin/5
Re: Läsa värde med ADC på AVR? (asm)
jesse: Okej, jag tror jag förstår hur du menar. Jag kan inte använda de 8 lägsta bitarna till något vettigt när det gäller avståndsmätningen med sensorn.
Men kan man använda de 8 högsta bitarna eller måste man använda alla 10? Jag antar att det har med nogrannheten att göra och själva beräknadet för att få fram avståndet i meter.
Min tanke är att när jag fått detta att fungera så ska jag fortsätta med att skriva ut avståndet i meter på en LCD-display. I nuläget har jag ingen aning om hur man skriver ut 10-bits binärtal på LCD i decimalform men det blir en senare fråga.
Men kan man använda de 8 högsta bitarna eller måste man använda alla 10? Jag antar att det har med nogrannheten att göra och själva beräknadet för att få fram avståndet i meter.
Min tanke är att när jag fått detta att fungera så ska jag fortsätta med att skriva ut avståndet i meter på en LCD-display. I nuläget har jag ingen aning om hur man skriver ut 10-bits binärtal på LCD i decimalform men det blir en senare fråga.
Re: Läsa värde med ADC på AVR? (asm)
Du kan vänsterjustera och läsa ADCH för 8-bitarsprecision, precis som du var inne på i ett tidigare inlägg.
"If the result is left adjusted and no more than 8-bit precision is required, it is sufficient to read
ADCH. Otherwise, ADCL must be read first, then ADCH, to ensure that the content of the Data
Registers belongs to the same conversion."
"If the result is left adjusted and no more than 8-bit precision is required, it is sufficient to read
ADCH. Otherwise, ADCL must be read first, then ADCH, to ensure that the content of the Data
Registers belongs to the same conversion."
Re: Läsa värde med ADC på AVR? (asm)
> Jag kan inte använda de 8 lägsta bitarna till något vettigt
Tja, det beror ju helt på vad du menar med "något vettigt"...
Antag att du har ett 1 m måttband...
Att bara läsa de 8 *lägsta* bitarna motsvarar att bara läsa av cm-skalan
(i 0-9 cm) men inte veta om det är 5, 15, 25... cm totalt. D.v.s ditt
"mätvärde" kommer att räkna 0-9 och starta från 0 10 gånger under tiden.
0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9... o.s.v
Mycket ovanligt att man faktiskt vill göra på det sättet...
Att bara läsa de *högsta* 8 bitarna motsvarar att bara läsa av i hela dm
men inte veta hur många cm det är därimellan. D.v.s du mäter bara
0,0,0,0,0,0,0,0,0,0,10,10,10,10,10,10,10,10,10,20,20... o.s.v...
Detta är mycket vanligt när man inte behöver full upplösning.
Att läsa alla 10 bitarna motsvarar att läsa av i cm över hela skalan (0-100) cm.
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24... o.s.v
Så gör man när man både behöver hela skalan och full upplösning...
Tja, det beror ju helt på vad du menar med "något vettigt"...

Antag att du har ett 1 m måttband...
Att bara läsa de 8 *lägsta* bitarna motsvarar att bara läsa av cm-skalan
(i 0-9 cm) men inte veta om det är 5, 15, 25... cm totalt. D.v.s ditt
"mätvärde" kommer att räkna 0-9 och starta från 0 10 gånger under tiden.
0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9... o.s.v
Mycket ovanligt att man faktiskt vill göra på det sättet...
Att bara läsa de *högsta* 8 bitarna motsvarar att bara läsa av i hela dm
men inte veta hur många cm det är därimellan. D.v.s du mäter bara
0,0,0,0,0,0,0,0,0,0,10,10,10,10,10,10,10,10,10,20,20... o.s.v...
Detta är mycket vanligt när man inte behöver full upplösning.
Att läsa alla 10 bitarna motsvarar att läsa av i cm över hela skalan (0-100) cm.
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24... o.s.v
Så gör man när man både behöver hela skalan och full upplösning...
Re: Läsa värde med ADC på AVR? (asm)
Yes! Nu fungerar det! Tack för all hjälp!
Här är hela den fungerande koden:
Här är hela den fungerande koden:
Kod: Markera allt
.NOLIST
.INCLUDE "m168def.inc"
.LIST
;===============================================================================================
; Avståndsmätare - TEST av ADC
;
; Programmet läser av en ultraljudssensor via ADC och visar värdet från ADCH på
; 8 st lysdioder som sitter på PortD
;
; CPU: Atmel Atmega168 (Int. Oscilator 8 MHz)
; Plattform: AVR Dragon
;
; Ver 1.0 [2009-12-16/glattnos@hotmail.com]
;===============================================================================================
.DEF temp = r16 ;Temporärt register
.DEF adc_data = r17 ;Data för digitalt ADC-värde
;-----------------------------------------------------------------------------------------------
; Macron
;-----------------------------------------------------------------------------------------------
.MACRO INTERRUPT ;Macro i början av en avbrottsrutin
push temp ;Lägg temp(1) på stacken
in temp,SREG ;
push temp ;Lägg SREG(2) på stacken
.ENDMACRO ;Slut macro
.MACRO INTERRUPT_END ;Macro i slutet av en avbrottsrutin
pop temp ;Hämta SREG(2) från stacken
out SREG,temp ;
pop temp ;Hämta temp(1) från stacken
reti ;Returnerar från avbrottet
.ENDMACRO ;Slut macro
;===============================================================================================
; AVBROTTS-VEKTORER
;===============================================================================================
.CSEG ;Följande placeras i PM
.ORG 0000 ;Avbrottsvektor för Reset
rjmp Reset
.ORG ADCCaddr ;Avbrottsvecktor för ADC
rjmp Ultra
;-----------------------------------------------------------------------------------------------
; Reset - Initieringskod för att förbereda systemet
;-----------------------------------------------------------------------------------------------
.ORG 0x0100 ;Startadress i PM för Reset
Reset:
ldi temp, LOW(RAMEND) ;Initiera stackpekare
out SPL, temp ;
ldi temp, HIGH(RAMEND) ;
out SPH, temp ;
ldi temp, 0xff ;Sätt PortD som utport
out DDRD, temp ;
;-----------------------------------------------------------------------------------------------
; ADC - Initiering
;-----------------------------------------------------------------------------------------------
;ADC - AREF(Internal Vref turned off), Left adjusted, ADC5
ldi temp, (0<<REFS1)+(1<<REFS0)+(1<<ADLAR)+(0<<MUX3)+(1<<MUX2)+(0<<MUX1)+(1<<MUX0)
sts ADMUX, temp
;ADC - ADENable, ADStartConversation, ADInterruptEnable
;ADPrescalerSelectBits 110 = System clock/64 to ADC
ldi temp, (1<<ADEN)+(1<<ADSC)+(1<<ADIE)+0b110
sts ADCSRA, temp
sei ;Sätt I-biten i SREG för att tilllåta avbrott
;========================================================================
; Main - Huvudloop
;========================================================================
Main:
mov temp, adc_data ;Sätt värdet från ADC:n...
out PORTD, temp ;...till PortD
rjmp Main ;Börja om på Main
;===============================================================================================
; AVBROTTSRUTIN - Avbrottsrutinen Ultra läser av UL-sensorn och sparar värdet
;===============================================================================================
Ultra: INTERRUPT ;Börja avbrottsrutinen med MACRO INTERRUPT
lds adc_data, ADCH ;Lagra värdet från ADCH i adc_data
lds temp, ADCSRA ;Ladda temp med ADCSRA...
sbr temp, (1<<ADSC) ;..och sätt ADStartConvertion-biten
sts ADCSRA, temp ;Lägg tillbaka värdet i ADCSRA
INTERRUPT_END ;Avsluta avbrottsrutinen med MACRO INTERRUPT_END
Re: Läsa värde med ADC på AVR? (asm)
Grattis!
Men om du ska fortsätta med det här så rekommenderar jag verkligen att du läser lite om binära talsystem, och hur man räknar med dessa. T.ex. en gymnasiebok i digitalteknik. Den går igenom det mesta du behöver veta för att sedan lära dig processorns funktioner, och att förstå hur den räknar. Biblioteket har t.ex "Digitalteknik från A till Ö" eller motsvarande...
Men om du ska fortsätta med det här så rekommenderar jag verkligen att du läser lite om binära talsystem, och hur man räknar med dessa. T.ex. en gymnasiebok i digitalteknik. Den går igenom det mesta du behöver veta för att sedan lära dig processorns funktioner, och att förstå hur den räknar. Biblioteket har t.ex "Digitalteknik från A till Ö" eller motsvarande...
Re: Läsa värde med ADC på AVR? (asm)
jesse: Okej, ja jag har väll tänkt att jag ska läsa någon bok om just digitalteknik, nu har jag bara böcker specifikt om AVR-prosessorer, "Microprosessorteknik" av Per Foyer och "Embedded C Programming and the Atmel processor".
Per Foyers bok har jag läst från pärm till pärm men den andra boken är på engelska vilket jag inte är så bra på så den har jag läst ungefär halva. Jag tycker att assembler är lättare att förstå än C så därför håller jag mig till assembler nu i början.
Men jag kan ju lika gärna fortsätta denna tråd.
Nu har jag ju fått ADC:n att fungera, och får ett 8-bitarsvärde. Nu vill jag skriva ut ett värde decimalt på min LCD. Till LCD:n kan man skicka ASCII-tecken på 8 bitar. Om jag till att börja med vill skriva ut talet från ADC:n decimalt, hur kan jag göra då?
Jag tänker såhär:
Talet från ADC:n är 1 byte som kan innehålla 0-255 binärt
Talet som ska visas på LCD:n är ju mellan 0-255 decimalt, så då behövs 3 st siffror.
Man använder 3 byte i SRAM för att lagra dessa 3 siffror i ASCII-format.
Så skickar man dessa tre byte i tur och ordning till LCD.
Frågor:
1. Är detta en bra metod eller finns det något enklare sätt?
2. Hur räknar man om det binära talet till tre ASCII-tecken(i assembler)?
Per Foyers bok har jag läst från pärm till pärm men den andra boken är på engelska vilket jag inte är så bra på så den har jag läst ungefär halva. Jag tycker att assembler är lättare att förstå än C så därför håller jag mig till assembler nu i början.
Men jag kan ju lika gärna fortsätta denna tråd.
Nu har jag ju fått ADC:n att fungera, och får ett 8-bitarsvärde. Nu vill jag skriva ut ett värde decimalt på min LCD. Till LCD:n kan man skicka ASCII-tecken på 8 bitar. Om jag till att börja med vill skriva ut talet från ADC:n decimalt, hur kan jag göra då?
Jag tänker såhär:
Talet från ADC:n är 1 byte som kan innehålla 0-255 binärt
Talet som ska visas på LCD:n är ju mellan 0-255 decimalt, så då behövs 3 st siffror.
Man använder 3 byte i SRAM för att lagra dessa 3 siffror i ASCII-format.
Så skickar man dessa tre byte i tur och ordning till LCD.
Frågor:
1. Är detta en bra metod eller finns det något enklare sätt?
2. Hur räknar man om det binära talet till tre ASCII-tecken(i assembler)?
Re: Läsa värde med ADC på AVR? (asm)
Det finns så många beskrivningar över binär -> BCD omvandling så det
är fullständigt onödigt att försöka göra ytterligare en. Det finns flera
gamla tråder här i forumet. Sök eller Googla...
är fullständigt onödigt att försöka göra ytterligare en. Det finns flera
gamla tråder här i forumet. Sök eller Googla...
Re: Läsa värde med ADC på AVR? (asm)
sodjan: Okej, jag har sökt och inte hittat något bra men det var ju inte så konstigt. Ja har sökt på "binär decimal" men när jag söker på "binär BCD" så fanns det ju massor
Men jag ställde en fråga till: 1. Är detta en bra metod eller finns det något enklare sätt?
Eftersom jag kom på metoden själv(jag har alltså inte läst det någonstans)så känns det som att det kanske finns något bättre sätt som jag inte tänkt på.

Men jag ställde en fråga till: 1. Är detta en bra metod eller finns det något enklare sätt?
Eftersom jag kom på metoden själv(jag har alltså inte läst det någonstans)så känns det som att det kanske finns något bättre sätt som jag inte tänkt på.