AVR AD-omvandlingsfråga
AVR AD-omvandlingsfråga
Tja!
Jag har exakt 1V på en AD-ingång på min Atmega8. Jag kör med intern 2.56V referens med inget kopplat till AVCC eller AREF. Jag sparar den höga byten i AD-resultatet i EEPROM och skickar seriellt till datorn.
Problemet är att jag får värdet "78" vid 1V och inte "100" som jag borde få.
Dessutom om jag höjer spänningen så minskar värdet.
Vad har jag gjort fel?
Jag har exakt 1V på en AD-ingång på min Atmega8. Jag kör med intern 2.56V referens med inget kopplat till AVCC eller AREF. Jag sparar den höga byten i AD-resultatet i EEPROM och skickar seriellt till datorn.
Problemet är att jag får värdet "78" vid 1V och inte "100" som jag borde få.
Dessutom om jag höjer spänningen så minskar värdet.
Vad har jag gjort fel?
Med reservation för att jag inte är uppdaterad på ADC'n
i AVR...
Är "78" och "100" HEX eller DEC ?
Hur många bitar har ADC'n ? 10 ?
Varför borde det bli just "100" ?
Om ADC'n har 10 bitar, så kan väll "höga byten"
aldrig bli varken "78" eller "100" ?
En annan sak är att 78 (dec) delar med 2.56 är nästan exakt 200 (dec),
vet inte om det har någon betydelse dock, bara en reflexion...
> Vad har jag gjort fel?
Vi får väll konstatera att någonting *är* fel först...
EDIT : "78 (dec) gånger 2.56", skall det vara...
i AVR...

Är "78" och "100" HEX eller DEC ?
Hur många bitar har ADC'n ? 10 ?
Varför borde det bli just "100" ?
Om ADC'n har 10 bitar, så kan väll "höga byten"
aldrig bli varken "78" eller "100" ?
En annan sak är att 78 (dec) delar med 2.56 är nästan exakt 200 (dec),
vet inte om det har någon betydelse dock, bara en reflexion...

> Vad har jag gjort fel?
Vi får väll konstatera att någonting *är* fel först...

EDIT : "78 (dec) gånger 2.56", skall det vara...
Tja!
78 är i DEC.
Vart jag fick "100" ifrån är från följande resonemang:
ADC:n är på 10 bitar och har referensen 2.56V.
2.56V / 2^10 = 2,5mV minsta ändring.
Minsta ändring resulterar i att 64 skrivs i ADC:ns resultatregister.
Detta för att 10 bitar skall passa in i ett 2 x 8 bitars register.
1V / 2,5mV innebär att vi har "400" minsta ändringar x 64 = 25600 i hela 16 bitars registret.
Höga byten är 256 gånger större än låga byten vilket ger att 25600 / 256 = "100".
Men jag får 78 som sagt. Jag har grejat med ADC:n förut utan att egentligen stöta på några problem så jag är rätt konfunderad nu. Jag tror jag har fel nån annan stans i seriellöverföringen eller nåt. Kanske har fel värden i UBRRH och UBRRL.
Hur gör man sånt?
Om jag skall ha 2400 baud med 8MHz klocka så skall jag skriva in värdet 207 i UBRR. UBRR består av UBRRH och UBRRL.
I min C-kod har jag bara skrivit UBRRH = 0 och UBRRL = 207. Det kanske är fel?
78 är i DEC.
Vart jag fick "100" ifrån är från följande resonemang:
ADC:n är på 10 bitar och har referensen 2.56V.
2.56V / 2^10 = 2,5mV minsta ändring.
Minsta ändring resulterar i att 64 skrivs i ADC:ns resultatregister.
Detta för att 10 bitar skall passa in i ett 2 x 8 bitars register.
1V / 2,5mV innebär att vi har "400" minsta ändringar x 64 = 25600 i hela 16 bitars registret.
Höga byten är 256 gånger större än låga byten vilket ger att 25600 / 256 = "100".
Men jag får 78 som sagt. Jag har grejat med ADC:n förut utan att egentligen stöta på några problem så jag är rätt konfunderad nu. Jag tror jag har fel nån annan stans i seriellöverföringen eller nåt. Kanske har fel värden i UBRRH och UBRRL.
Hur gör man sånt?
Om jag skall ha 2400 baud med 8MHz klocka så skall jag skriva in värdet 207 i UBRR. UBRR består av UBRRH och UBRRL.
I min C-kod har jag bara skrivit UBRRH = 0 och UBRRL = 207. Det kanske är fel?
> Minsta ändring resulterar i att 64 skrivs i ADC:ns resultatregister.
> Detta för att 10 bitar skall passa in i ett 2 x 8 bitars register.
Fungerar verkligen ADC'n i AVR så ??
D.v.s att resultat "skalas upp" från 10 bitar till 16 bitar ?
Eller har det med left/right justering att göra ?
Normalt, om man har 10 bitar, så används 8 bitar från
den "låga" byten, och *2* bitar (de "minsta") från den "höga" byten.
Om däremot resultatet är justerat så att man använder 8 bitar
från höga delen och 2 bitar (sannolikt då de två högsta bitarna)
från den låga byten, så finns det en viss logik i det du skriver.
Men, som sagt, jag är inte helt uppdaterad på AVR ADC'n...
> Detta för att 10 bitar skall passa in i ett 2 x 8 bitars register.
Fungerar verkligen ADC'n i AVR så ??
D.v.s att resultat "skalas upp" från 10 bitar till 16 bitar ?
Eller har det med left/right justering att göra ?
Normalt, om man har 10 bitar, så används 8 bitar från
den "låga" byten, och *2* bitar (de "minsta") från den "höga" byten.
Om däremot resultatet är justerat så att man använder 8 bitar
från höga delen och 2 bitar (sannolikt då de två högsta bitarna)
från den låga byten, så finns det en viss logik i det du skriver.
Men, som sagt, jag är inte helt uppdaterad på AVR ADC'n...

Ett adc-resultat i AVR blir aldrig mer än just 10 bitar.
Vid left adjust ligger de 8 mest signifikanta bitarna i höga registret och de två minst signifikanta bitarna ligger i de två msb i det låga registret.
vid right adjust ligger de två mest signifikanta bitarna på de två minst signifikanta positionerna i det höga registret och resten ligger i det låga registret.
Vid left adjust ligger de 8 mest signifikanta bitarna i höga registret och de två minst signifikanta bitarna ligger i de två msb i det låga registret.
vid right adjust ligger de två mest signifikanta bitarna på de två minst signifikanta positionerna i det höga registret och resten ligger i det låga registret.
Jo, jag håller med er om att så där står det i databladet och jag kan inte förstå varför det inte verkar fungera så.
Testa att koppla upp en lcd och se vad som kommer ut från ADCL respektive ADCH när ni varierar spänningen på ingången.
ADCL kommer att visa värden "0, 64, 128, 192" och
ADCH "0 - 255"
0 i ADCH är 0V och 255 är när ingången blir samma som AREF.
Detta är när jag har vänsterjusterat resultat och det kanske är en slump att det blir så här men jag skulle gärna vilja veta varför för jag är klart förbryllad...
Kanske har att göra med hur man läser ut resultatet? Efter en adomvandling tar jag ut värdet till 2 globala unsigned int med:
adc_lagbyte=ADCL;
adc_hogbyte=ADCH;
Testa att koppla upp en lcd och se vad som kommer ut från ADCL respektive ADCH när ni varierar spänningen på ingången.
ADCL kommer att visa värden "0, 64, 128, 192" och
ADCH "0 - 255"
0 i ADCH är 0V och 255 är när ingången blir samma som AREF.
Detta är när jag har vänsterjusterat resultat och det kanske är en slump att det blir så här men jag skulle gärna vilja veta varför för jag är klart förbryllad...
Kanske har att göra med hur man läser ut resultatet? Efter en adomvandling tar jag ut värdet till 2 globala unsigned int med:
adc_lagbyte=ADCL;
adc_hogbyte=ADCH;
karlstedt, helt logiskt och stämmer precis med hur PIC'arna justerar resultatet.
Mitt intryck är att *right* adjust är det vanligaste om man vill ha alla 10 bitarna.
Left adjust är praktiskt om man bara vill ha en 8-bitars resultat, eftersom
de 8 högsta bitarna hamnar direkt i höga registret, däremot är left adj lite
opraktiskt om man vill ha alla 10 bitarna...
mrhedin > Detta är när jag har vänsterjusterat resultat och det kanske är en
slump att det blir så här men jag skulle gärna vilja veta varför för jag är klart
förbryllad...
Vad är förbryllande ?
Men som sagt, om du *vill* använda alla *10* bitarna så är det betydligt mer
logiskt att använda right adjust...
Mitt intryck är att *right* adjust är det vanligaste om man vill ha alla 10 bitarna.
Left adjust är praktiskt om man bara vill ha en 8-bitars resultat, eftersom
de 8 högsta bitarna hamnar direkt i höga registret, däremot är left adj lite
opraktiskt om man vill ha alla 10 bitarna...
mrhedin > Detta är när jag har vänsterjusterat resultat och det kanske är en
slump att det blir så här men jag skulle gärna vilja veta varför för jag är klart
förbryllad...
Vad är förbryllande ?
Men som sagt, om du *vill* använda alla *10* bitarna så är det betydligt mer
logiskt att använda right adjust...
Jag tycker det känns extremt logiskt att om man vill ha 10 bitars upplösning så kör man högerjustering och så läser man direkt ur 16-bitars-registret och får då ett tal mellan 0-1023.
(För att få tag i vilket spänningsnivå detta motsvarar tar du helt enkelt kvoten mellan det utlästa värdet och 1023 och multiplicerar med referensspänningen.)
Obs om du programmerar direkt i assembler! Tänk på att du måste läsa det höga registret först om du vill vara säker på att det ska bli rätt, detta för att AVR:en latchar 16-bitars-registrets låga byte då den höga läses. Läser du i omvänd ordning kommer den låga byten från föregående sample att ligga kvar till nästa och det kan ställa till det lite.
(För att få tag i vilket spänningsnivå detta motsvarar tar du helt enkelt kvoten mellan det utlästa värdet och 1023 och multiplicerar med referensspänningen.)
Obs om du programmerar direkt i assembler! Tänk på att du måste läsa det höga registret först om du vill vara säker på att det ska bli rätt, detta för att AVR:en latchar 16-bitars-registrets låga byte då den höga läses. Läser du i omvänd ordning kommer den låga byten från föregående sample att ligga kvar till nästa och det kan ställa till det lite.