Atmega32 ADC-Wert nicht genau

Ich habe versucht, auf Proteus ADC mit Potentiometer zu simulieren und den Messwert zu erhalten, um den Gleichstrommotor mit PWM zu steuern, es funktioniert, aber das Problem ist, dass der ADC-Wert nicht genau ist. ADCH erreicht den Maximalwert, bevor das Potentiometer 100 % erreicht. Ich weiß nicht, warum dieses Verhalten. Hoffe, Sie können es mir erklären. Hier ist der Code.

#include <avr/io.h>
#define F_CPU 1000000UL
#include <util/delay.h>
void pwm_init()
{
DDRB |= (1<<PB3);
TCCR0 |= (1<<WGM00) | (1<<WGM01) | (1<<COM01) | (1<<CS01);
OCR0 = 0x00;
}

void adc_init()
{
DDRA =0x00;
ADMUX |= (1<<REFS0);// AVCC ref
ADCSRA |= (1<<ADEN) | (1<<ADPS2) | (1<<ADLAR) | (1<<ADATE); // 1MHZ With 
prescaler 8 gives adc freq 125 khz
}

uint8_t adc_read()
{
ADCSRA |= (1<<ADSC);
while(!(ADCSRA && (1<<ADIF)));
ADCSRA |= (1<<ADIF);
return ADC;
}

int main(void)
{
pwm_init();
adc_init();
while (1) 
{
    OCR0 = adc_read();
}
}

Sie können auch im unteren Bild sehen, dass der Arbeitszyklus fast 100 % beträgt, während das Potentiometer nur 12 % beträgt.Simulation

Welche Platine verwendest du? Sind Sie sicher, dass keine anderen On-Board-Geräte/Sensoren an den PA0-Pin angeschlossen sind?
@Ali Chen Ich benutze keine Boards, ich simuliere es auf Proteus auf Atmega32
Welche Spannungen liegen an RV4(2), VCC und AVCC an? Bitte zeigen Sie die gesamte Schaltung.
Warum führen Sie diese logische UND-Operation durch: while(!(ADCSRA && (1<<ADIF))); statt bitweisem UND: while( !( ADCSRA & (1<<ADIF)) ) ; ??

Antworten (2)

Wenn ADLAR = 1, dann wird gemäß dem Datenblatt (Abschnitt 26.8.4, siehe Anhang) das ADC-Ergebnis linksbündig mit dem 16-Bit-Paar ADCH-ADCL ausgerichtet.

Ihre Funktion adc_read()gibt eine 8-Bit-Ganzzahl zurück. ADCLDaher wird nur das (siehe Abbildung) zurückgegeben , da die oberen 8 Bits bei der Konvertierung uint_16->uint_8 verloren gehen.

Mit anderen Worten, wenn A0 oder A1 1 sind, erhalten Sie einen großen Arbeitswert, da der von zurückgegebene Wert adc_read()zwischen 0x40 und 0xC0 liegt.

Lösung: In Ihrer Funktion nur adc_read()return .ADCH

Außerdem muss das Potentiometer an eine Spannungsquelle mit AREF Volt angeschlossen werden, wobei AREF die ADC-Referenzspannung ist. Wenn Sie die interne Referenz verwenden, schließen Sie das Potentiometer nicht direkt an den AREF-Pin an, da dieser Pin eine sehr geringe Ausgangsstromkapazität hat.

Geben Sie hier die Bildbeschreibung ein

Danke für den Hinweis. Ich habe den Code so bearbeitet, dass adc_read() nur ADCH zurückgibt, aber leider zeigte die Simulation einen Arbeitszyklus von fast Null und es passiert keine Änderung, wenn der Potentiometerwert geändert wird.
Bitte zeigen Sie dann die vollständigen Schaltpläne in Ihrem Beitrag! Es ist durch das Zielfernrohr verdeckt! Außerdem, was ist RV4(2)? Ist es eine Spannung gleich AREF?
RV4 ist nur eine Bezeichnung für das Potentiometer.
Sie müssen einen Spannungsgenerator mit dem Wert AREF auf den oberen Pin des Potentiometers legen. Andernfalls ist die Spannung an PA0 immer 0.
Dieses Dreieck über dem Potentiometer ist die Gleichspannungsversorgung mit 5 V wie aref
Kannst du uns den kompletten Schaltplan zeigen?
Tut mir leid, dass ich jetzt nicht in der Nähe meines Laptops bin. Ich werde es hochladen, sobald ich Zugriff darauf habe

Danke Jungs für eure Hilfe

Ich habe das Problem gefunden.

Ich habe ADLAR im ADCSRA-Register eingestellt und es sollte in ADMUX eingestellt werden. Ich habe das behoben und alles hat gut funktioniert.