Allgemeines
ADC einschalten
I/O-Pin Einstellung
Eingangsauswahl
ADC-Geschwindigkeit
Ergebnisformat
ADC starten
Arbeitspause
Messgenauigkeit
Beispiel
Viele PICs besitzen einen ADC (Analog-Digital-Converter), der eine analoge Eingangsspannung (von 0V...5V) in einen 10-Bit Zahlenwert von 0 bis 1023 umwandelt. Dadurch lassen sich PICs für analoge Messaufgaben einsetzen.
Obwohl der PIC nur einen ADC besitzt, haben
Der ADC wird mit einem internen Schalter
jeweils mit genau einem dieser Eingänge verbunden. Durch Umstellen
dieses Schalters (per Software) lassen sich die Spannungen an allen
Eingängen
nacheinander messen.
Auf dieser Seite
beziehe ich mich auf die PIC16F87x-Familie. Die ADCs anderer PICs
funktionieren
ähnlich, allerdings können die Eingangspins sowie die
Adressen
der ADC-Steuerregister abweichen.
Neben dem hier
verwendeten
10-Bit-33kHz-ADC gibt es in anderen PICs auch ADCs
anderer Auflösung und Geschwindigkeit.
Referenzspannung
Ein ADC benötigt präzise
Referenzspannungen für den Minimalwert (Vref-)und den
Maximalwert
(Vref+) der zu wandelnden Eingangsspannung. Jede Schwankung dieser
Referenzspannungen
verfälscht das Messergebnis. Für eine 10-Bit-Messung
sollten
die Referenzspannungen um weniger als 0,1% schwanken. Der PIC benutzt
normalerweise
Vss und Vdd (also Masse und Betriebsspannung des PIC) als Referenz.
Eine
Eingangsspannung, die Vss entspricht wird als 0 interpretiert, eine
Spannung
die Vdd entspricht wird in den Wert 1023 gewandelt. Alle dazwischen
liegenden
Spannungen werden dementsprechend in einen Zwischenwert gewandelt.
Bei einer Betriebsspannung von 5V hat
der ADC also einen Arbeitsbereich von 0V...5V.
Sollte die Betriebsspannung nicht stabil genug sein, kann man externe Referenzspannungen für 0 und 1023 anlegen. Dafür werden die Pins verwendet, die normalerweise als analoge Eingänge AN2 (Vref-) und AN3 (Vref+) verwendet werden. Diese Eingänge stehen dann für Messungen nicht mehr zur Verfügung. Der PIC hat dann nur noch 3 bzw. 6 analoge Eingänge.
Legt man als untere und obere Referenzspannung andere Werte als 0V und 5V an, ändert man damit auch den Wandlerbereich des ADC. Dabei ist aber zu beachten:
Steuerregister
Zum ADC gehören 4 Register im PIC.
Über die Register ADCON0 (1Fh) und ADCON1 (9Fh)
wird
der ADC eingestellt und gesteuert. In den Registern ADRESH und ADRESL
findet man nach erfolgreicher Wandlung das 10-Bit Messergebnis.
ADCON0: ADC CONTROL REGISTER 0 (ADDRESS 1Fh):
bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 | |
Name: | ADCS1 | ADCS0 | CHS2 | CHS1 | CHS0 | GO/DONE | - | ADON |
ADCON1: ADC CONTROL REGISTER 1 (ADDRESS 9Fh):
bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 | |
Name: | ADFM | - | - | - | PCFG3 | PCFG2 | PCFG1 | PCFG0 |
Außerdem sind die Register TRISA (& TRISE) für die I/O-Pin-Einstellung sowie INTCON , PIR1 und PIE für die Interrupteinstellung (falls Interrupt benutzt werden soll) zu beachten
Der ADC des PIC lässt sich generell aus- und einschalten. Das ist als Stromsparfunktion zu verstehen. Ein eingeschalteter, aber nicht benötigter ADC verbraucht Strom, was sich durch Ausschalten vermeiden lässt. Will man den ADC benutzen, muss er natürlich eingeschaltet sein. Das erreicht man durch setzen des Bits 0 im Register ADCON0.
; ADC einschalten
BSF
ADCON0, 0 ; ADON=1
Nach power-on oder Reset ist der ADC ausgeschaltet. Das Einschalten ist also zwingend nötig.
Natürlich war es nicht möglich Pins am, PIC-Gehäuse exklusive für den ADC zu reservieren. Die ADC-Eingänge sind Pins der Ports A und E. Diese können entweder als digitale I/O-Pins oder als analoge Eingänge verwendet werden. Will man Spannungen messen, muss man die zu verwendenden Pins zunächst auf 'analog' umschalten. Dies geschieht mit den Bits 0 bis 3 des ADCON1 -Registers. Nach einem Reset (oder nach dem Einschalten) sind diese Bits auf 0 gesetzt, wodurch automatisch alle vorhandenen Eingange als analoge Eingänge eingestellt sind.
ADCON1: ADC CONTROL REGISTER 1
(ADDRESS
9Fh):
bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 | |
Name: | ADFM | - | - | - | PCFG3 | PCFG2 | PCFG1 |
|
|
|
|
|
|
Die folgende Tabelle zeigt in
Abhängigkeit
der Bits 3..0, welche Eingänge dem ADC zur Verfügung stehen,
und welche Referenzspannungen benutzt werden.
PCFG3- PCFG0 |
AN7- RE2 |
AN6- RE1 |
AN5- RE0 |
AN4- RA5 |
AN3- RA3 |
AN2- RA2 |
AN1- RA1 |
AN0- RA0 |
Vref+ | Vref- |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
|||||
|
|
|
|
|
||||||
|
|
|
||||||||
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
|||||
|
|
|
|
|
||||||
|
|
|
|
|||||||
|
|
|
|
Im TRISA / TRISE-Register sind die verwendeten analogen Eingänge als input einzustellen. Also müssen die den Pins zugeordneten TRIS-Bits auf 1 gesetzt werden. Ist ein analoger Eingang versehentlich als Ausgang programmiert, so misst der ADC den an diesem Pin erzeugten logischen Pegel (high/low), was ziemlich sinnlos wäre. Nach Reset und power-on sind alle TRIS-Bits auf 1 gesetzt, so dass man sich hier eventuell Arbeit sparen kann.
Vor der Messung muss der ADC mit dem richtigen Eingang verbunden werden. Das geschieht mit den Bits 5 ..3 des Registers ADCON0.
ADCON0: ADC CONTROL REGISTER 0
(ADDRESS
1Fh):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Die folgende Tabelle zeigt in
Abhängigkeit
der Bits 5..3, welcher Eingang dem ADC zugeschaltet ist:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Soll z.B. der analoge Eingang AN0 verwendet werden, ist in alle drei Bits der Wert 0 einzutragen.
; ADC-Eingang AN0 auswählen
BCF
ADCON0, 5 ; ADCHS2=0
BCF
ADCON0, 4 ; ADCHS1=0
BCF
ADCON0, 3 ; ADCHS0=0
Wichtig,
und oft vergessen: die "acqisition time"
Nach der Wahl des Eingangs wird der
interne
Kondensator am ADC-Eingang mit der am analogen Pin anliegenden Spannung
geladen. Gemessen wird später die Spannung in diesem Kondensator.
Deshalb muss man dem PIC nun genügend Zeit einräumen,
den
Kondensator komplett auf die neue Spannung aufzuladen, bevor man die
eigentliche
Messung auslöst. Wie lange diese 'acquisition time' dauern sollte,
hängt von mehreren Parametern ab (z.B. vom Innenwiderstand der zu
messenden Spannungsquelle). Typischerweise reichen 40
µs Pause aus. Wer es genau wissen will, findet in der
Dokumentation zum PIC-Typ eine Formel zur Berechnung dieser Wartezeit.
Wird der Eingang zwischen zwei
Messungen
nicht gewechselt, dann ist auch eine Acquisition Time nötig, damit
der Kondensator sich auf die geänderte Eingangsspannung aufladen
kann.
Da die Spannungsänderung zwischen zwei Messungen dabei aber
vergleichsweise
gering ausfallen wird, kann eine kürzere Acquisition Time (z.b. 10
µs) ausreichen.
Der ADC benötigt für die Wandlung einen Arbeitstakt, der mit einem Frequenzteiler aus dem Takt des PIC abgeleitet wird. Der PIC-Takt kann aber zwischen wenigen kHz und 20 MHz liegen. Deshalb muss man je nach verwendetem PIC-Takt ein Frequenzverhältnis zwischen ADC-Takt und PIC-Takt einstellen. Das erfolgt mit den Bits 7 & 6 des Registers ADCON0. Die folgende Tabelle gibt an, welche Einstellung bis zu welcher Maximalfrequenz möglich ist. Die Einstellung '10' funktioniert z.B. bis zu einem PIC-Takt von 20MHz. Wird sie aber z.B. bei 1MHz verwendet, arbeitet der ADC 20 mal langsamer als bei 20 MHz. Deshalb sollte dann auf '00' umgeschaltet werden, was den ADC 16 mal schneller arbeiten lässt. Damit ist der ADC bei 1 MHz etwa gleich schnell wie bei 20 MHz.
Verwendet man aber '00' in einem mit 20
MHz getakteten PIC, wird der ADC mit einem Takt betrieben, bei dem der
Wandler nicht mehr funktioniert.
PIC Takt | ADCS1 | ADCS0 |
|
|
|
|
|
|
|
|
|
|
|
|
Wird jeweils der schnellstmögliche PIC-Takt verwendet (also z.B. 5 MHz bei Einstellung '01' oder 20 MHz bei Einstellung '10') dann benötigt der ADC 19,2 µs (12 ADC-Takte) für die Wandlung, und anschließend 3,2 µs Pause (2 ADC-Takte).
Soll sofort eine neue Messung der Spannung erfolgen, dann folgt aber zuerst etwas Zeit (Acquisition Time 10 .. 40 µs, je nach Typ und Eingangsbeschaltung), in der der interne Kondensator auf die inzwischen geänderte Eingangsspannung geladen wird. Erst danach kann der ADC wieder gestartet werden. Das ergibt eine maximale Samplefrequenz von immerhin 33 kHz bis 16 kHz (je nach acqisition time). Bei einem langsamerem Takt wird der ADC proportional langsamer.
; ADC speed für 20 MHz einstellen
BSF
ADCON0, 7 ; ADCS1=1
BCF
ADCON0, 6 ; ADCS0=0
Andere Typen als der 16F876
Der technische Fortschritt geht auch am
ADC nicht vorbei. Neue PICs haben oft einen kürzere Acquisition
Time
oder einen höheren zulässigen ADC Takt als der 16F876.
Dafür
hier einige Beispiele:
Das 10-Bit-Messergebnis wird in
den
Registern ADRESH & ADRESL abgelegt, die zusammen
aber
16 Bit lang sind. Mit dem Bit 7 des Registers ADCON1
lässt
sich auswählen, ob die 10 Bit in den 16 Bit linksbündig oder
rechtsbündig abgelegt werden. Nachfolgende Tabelle illustriert
beide
Möglichkeiten:
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
|
|
; Daten linksbündig
BSF
STATUS,RP0 ; Bank1
BCF
ADCON1, 7 ; ADFM=0
BCF
STATUS,RP0 ; Bank0
Die unbenutzten Stellen werden in der
Regel mit
Nullen
gefüllt.Es gibt aber Ausnahmen. Beim 16F684 haben die
"freien" Bits bei rechtsbündiger Ausgabe den Wert des Bits 9. Man
sollte sie also mit einem AND-Befehl ausblenden.
Ist alles vorbereitet, kann der ADC gestartet werden. Dafür setzt man das Bit 2 des Registers ADCON0 auf 1. Ist der ADC mit der Wandlung fertig, löscht er dieses Bit wieder. Durch zyklisches Abfragen dieses Bits kann man also herausbekommen, wann der ADC fertig ist.
;Eingangsspannung wandeln
BSF
ADCON0, 2 ; ADC
starten
loop
BTFSC ADCON0,
2 ; ist der ADC
fertig?
GOTO
loop
;
nein,
weiter
warten
Nach getaner
Arbeit
braucht der ADC eine kleine Verschnaufpause, bevor er wieder benutzt
werden
kann. Wie lange, das hängt von der eingestellten
ADC-Geschwindigkeit
ab. Folgende Tabelle gibt die nötige Mindestpause in PIC-Takten
an:
(Tosc ist eine Schwingung des PIC-Taktes am Pin OSC1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Da ein typischer PIC-Befehl in 4 Tosc abgearbeitet wird, entspricht diese Wartezeit je nach Einstellung 1 ... 16 Befehlen. Oft wird deshalb diese Verzögerung im Programm sowieso auftreten. Nur wenn in der 20-MHz-Einstellung ('10') der ADC pausenlos abgefragt wird, könnte es zu einer Unterschreitung der Wartezeit kommen, und der ADC würde ungenaue Messwerte liefern. In diesem Fall ist eine kleine Warteschleife einzufügen.
Eine Messung ist sinnlos, wenn man nichts über ihre Genauigkeit weiß. Ein 10-Bit-ADC kennt 1024 Abstufungen zwischen Minimum und Maximum, was seine Messgenauigkeit auf 0,1% limitiert. Da kein Bauteil perfekt ist, muss man noch mit 4..5 Stufen Linearitäts- und Offset-Fehler rechnen (näheres im Datenblatt). Damit kann der ADC aber immer noch 0,5% Genauigkeit im gesamten Messbereich garantieren.
Die Messung kann nicht genauer sein, als die Referenzspannung, auf deren Erzeugung entsprechend Aufmerksamkeit verwendet werden sollte. Wer die Referenzspannung aus der Betriebsspannung des PIC ableitet, sollte diese also gut stabilisieren. Ein 7805-Regulator kann 1% Genauigkeit erreichen.
Oft ist die zu messende Spannung selbst mit einer Schwingung verunreinigt. Dass passiert, wenn sie z.B. mit einem Schaltregler oder aus dem 50-Hz-Stromnetz (Trafo & Gleichrichter) erzeugt wurde. In diesen Fällen kann es von Vorteil sein, die Messung mit der Schwingung zu synchronisieren.
Eine unsaubere Eingangsspannung lässt sich durch Mittelwertbildung aus vielen Messungen "glätten". Wenn man die Eingangsspannung 64 mal misst, und alle 10-Bit-Messergebnisse zusammenaddiert, bekommt man ein 16-Bit-Ergebnis. Die oberen 10-Bit davon sind die "gesiebte" Eingangsspannung.
Wer die Genauigkeit des ADC maximal ausnutzen will, sollte den PIC während der Messung nicht weiterarbeiten lassen, da sein schwankender Stromverbrauch den ADC stören könnte. Besser ist es den PIC nach dem Start des ADC sofort mit einem SLEEP-Befehl schlafen zu legen. Der ADC muss dann so konfiguriert werden, dass er am Ende der Messung sein Interrupt-Flag ADIF setzt, um den PIC wieder zu wecken. Damit das Aufwachen klappt müssen außerdem ADIE (im Register PIE1) und PEIE (im Register INTCON) auf 1 gesetzt sein (aber nicht GIE). Da im SLEEP-Modus der Takt nicht mehr zur Verfügung steht, muss als ADC-Taktquelle der interne RC-Oszillator gewählt werden!
Reichen die 10-Bit des ADC nicht aus, kann man auf 2 Wegen eine höhere Genauigkeit erreichen.
Beispiel (identisch mit diesem Lernbeispiel)
Das folgende Beispielprogramm für einen mit 20 MHz getakteten PIC16F876 wandelt die am AN0/RA0 liegende Spannung in einen 10-Bit-Wert um, und zeigt die oberen 8 Bit des Ergebnisses an PortB an (LEDs). Als Referenz wird Vdd und Vss verwendet.
;**************************************************************
;* ;* Pinbelegung ;* ---------------------------------- ;* PORTA: 0 analoger Eingang ;* 1 ;* 2 ;* 3 ;* 4 ;* PORTB: 0 LED ;* 1 LED ;* 2 LED ;* 3 LED ;* 4 LED ;* 5 LED ;* 6 LED ;* 7 LED ;* PORTC: 0 ;* 1 ;* 2 ;* 3 ;* 4 ;* 5 ;* 6 ;* 7 ;* ;************************************************************** ; ; sprut (zero) Bredendiek 04/2002 ; ; ADC-Lernbeispiel: ; ; 16F876 wandelt die an RA0 anliegende Spannung in einen ; 10-Bit-Wert um ; die oberen 8 Bit des Wertes werden an PortB angezeigt ; ; Prozessortakt: 20 MHz ; Eingangsspannung: 0V ... 5V (Vss ... Vdd) ; ;************************************************************** ; Includedatei für den 16F876 einbinden list p=16f876
ERRORLEVEL -302 ;SUPPRESS BANK SELECTION MESSAGES ;********************************************************** ; Variablen ; Anfangsinitialisierung init ; ADC einschalten ; ADC-Eingang AN0 auswählen
; ADC speed für 20 MHz
einstellen ; Daten linksbündig
;**********************************************************
Main ; Wert nach PortB schreiben
; Warten, damit der ADC sich erholen
kann goto Main end |
Autor: sprut
erstellt: 10.04.2002
letzte Änderung: 07.08.2012