Computerarchitektur
Blockschaltbild
eines PIC
Welche
Anschlüsse hat ein PIC
Was sind
Ports eines PIC?
Programmspeicherorganisation
Datenspeicherorganisation (RAM)
Daten-EEPROM
weiter zu direkter und indirekter Adressierung
weiter zum Lesen und Beschreiben des EEPROM und des FLASH
weiter zu digital Input/Output, USART, I2C , ADC , PWM , Capture/Compare
Wer sich noch nie mit den Interna eines Computers oder einer CPU beschäftigt hat, kann gleich zum nächsten Punkt übergehen. Wer aber schon mal mit CPUs, Assembler und Ähnlichem gekämpft hat, der hatte es in der Regel mit einer "von Neumann Architektur" zu tun.
In einem "von Neumann Computer" liegen Programmcode und
Daten in einem gemeinsamen Speicher. Ein typisches
Beispiel ist ein normaler Personalcomputer: Programme werden von der Festplatte in den RAM (Speicher) geladen, und dort ausgeführt. Im selben Speicher werden auch alle Daten abgelegt. Selbst BIOS-Chips (z.B. von Mainboard, Grafikkarte oder Netzwerkkarte) werden in den einzigen Speicherbereich eingeblendet. In der heutigen Virenverseuchten Computerumwelt
offenbart dieses Design Schwächen. Da Programm und Daten
nicht sauber getrennt sind, kann der Code eines Virus
oder eines Trojaners als Daten in den PC gelangen, und
dann unter Ausnutzung von Softwarebugs (stack overflow)
als Programmcode ausgeführt werden. |
Ein PIC ist nach der "Harvard Architektur"
aufgebaut. Dabei sind Programmspeicher und Datenspeicher
(RAM) vollständig getrennt. Das ist aus mehreren Gründen
sinnvoll. Da in einem Microcontroller das Programm selten ausgetauscht wird (im Gegensatz zu einem PC, mit dem man jede Minute was anderes erledigt) wird als Programmspeicher ein nichtflüchtiger Speicher (z.B. FLASH) eingesetzt. Der RAM beruht aber auf ganz anderen Technologien. Da ist eine komplette Trennung logisch. Um PICs preiswert herzustellen, sind die meisten PICs
nur auf die Verarbeitung von 8-Bit-Daten ausgelegt.
Folglich sind Datenbus und Datenspeicher nur 8 Bit
breit. Nur 8 Bit sind aber für einen komplexen
Programmbefehl nicht ausreichend. Wollte man das
Programm in einem 8-Bit-organisierten Speicher ablegen,
so müsste man Befehle immer auf jeweils 2 Speicherzellen
verteilen, die dann beide einzulesen sind. Das
verlangsamt aber die Abarbeitung des Programms. (Es gibt inzwischen auch PICs mit 16 Bit breiten Daten-, die aber einen 24 Bit breiten Programmspeicher haben.) Natürlich gibt es nun die gleichen Adressen sowohl im
Programmspeicher, wie auch im Datenspeicher (und sogar
noch mal im EEPROM). Das mag anfänglich verwirren, aber
die Adresse 20h im Programmspeicher hat mit der Adresse
20h im Datenspeicher natürlich gar nichts zu tun.
|
Während ein richtiger Computer aus vielen Baugruppen
zusammengebaut werden muss, vereinigt ein Microcontroller
viele dieser Baugruppen in einem Chip.
Das Zentrum bildet ein relativ einfacher Prozessorkern, der den Controller steuert, und einfache Berechnungen (Addition, Subtraktion...) und Vergleiche (größer, kleiner ...) durchführen kann. Das Programm, das der Kern abarbeitet, liegt im Flash-Programmspeicher. Daten kann der Kern im RAM speichern. Der Inhalt des RAM geht aber beim Abschalten der Betriebsspannung verloren. Auch im EEPROM können Daten
abgelegt werden, was aber vergleichsweise kompliziert
und zeitraubend ist. Dafür bleiben dort die Daten auch
nach dem Abschalten der Betriebsspannung erhalten. Nicht
alle PICs haben einen EEPROM. Eine Taktversorgung liefert den Arbeitstakt für den Kern. Oft wird ein externes Bauelement (Resonator, Quarz) für die Takterzeugung benötigt. Input/Output-Ports dienen dazu, einzelne Pins des Controllers auf High (5V) oder Low (0V) zu setzen und damit extern angeschlossene Schaltungen zu steuern oder den von außen angelegten, digitalen Pegel an einem Pin abzufragen. Spezielle Peripherie sind z.B. serielle oder parallele Komunikationsports (RS232, I2C, USB , CAN), Messschaltungen für Pulse (Capture), Pulserzeugungsschaltungen (Compare , PWM), AD-Wandler, Referenzspannungsquellen, analoge Komparatoren, Timerschaltungen ... Da die Zahl der Pins oft nicht für alle Funktionen
ausreicht, größere Gehäuse aber die Preise explodieren
ließen, muss man einzelnen Pins mehrere Funktionen
zuweisen, und über einen Multiplexer die Funktion des
Pins je nach Bedarf umschalten. |
VDD | Betriebsspannungsanschluss (+ 5 V) |
VSS | Masseanschluss ( 0 V) |
MCLR | Resetanschluss (Wird dieser Pin kurz mit Masse verbunden wird der PIC in den Ausgangszustand versetzt) |
OSC1/2 | Anschlüsse für den Taktgenerator |
Rxy | die eigentlichen Ports des PIC |
(Einige besonders kleine PICs verzichten auf MCLR, OSC1 und
OSC2.)
Die Anzahl der Port-Pins (Rxy) ist je nach PIC-Typ verschieden. Der 16F84 besitzt z.B. 13 Portpins, der 16F876 dagegen 21. Ein PIC18F8722 bringt es auf 70 Port-Pins, ein PIC10F200 hat geradeeinmal 4. |
Jedem Bit (0 .. 7) des Registers ist jeweils genau ein Port-Pin zugeordnet. Bei der Bezeichnung des Pins wird "Port" mit dem Buchstaben "R" ersetzt. Dadurch ergeben sich die Pin-Bezeichnungen: so ist RB3 z.B. das Pin, das mit dem Bit 3 des Registers PORTB verbunden ist.
Eine Besonderheit des Ports A ist, dass ihm in vielen PICs die höchstwertigen 3 Pins fehlen. Es gibt also oft nur RA0 bis RA4. Die Bits 5 bis 7 des Registers PORTA sind funktionslos. (Einige modernere PICs haben ein PortA mit bis zu 7 Pins.)
In/Out
Natürlich kann so ein Pin nicht gleichzeitig Ein- und Ausgang sein. Man muss zwischen
den beiden Funktionen umschalten. In der Grundeinstellung sind die
Ports Eingänge. Will man sie zu Ausgängen machen, so muss man im
Programm das interne Register TRISA (für PORTA), TRISB (PORTB)
bzw. TRISC (PORTC) u.s.w. verändern. Jedes Bit der TRIS-Register
ist einem Port-Pin zugeordnet. Ist das Bit auf "1" gesetzt, dann
funktioniert das zugehörige Pin als Eingang. Wird das Bit auf "0"
gesetzt, dann ist das zugehörige Pin bis auf Weiteres ein Ausgang,
und hat den Pegel, den das zugehörige Bit im Port-Register (z.B.
PORTA) hat.
Beim Reset und beim Einschalten des PIC werden alle Bits der die
TRIS-Register auf "1" gesetzt. Damit ergibt sich "Eingang" als
Grundfunktion der Pins.
Eine genauere Erläuterung befindet sich
hier.
Spezial
Einige Port-Pins besitzen zusätzliche Funktionen (z.B. spezielle Input/Output-Hardware). So kann
RA4 als Zählereingang für den Timer0 des PIC benutzt werden, Pins
des Port C können als serielle Schnittstellen dienen (z.B. 16F87x)
und die Pins des Port A können als analoge Spannungsmesseingänge
dienen (z.B. 16F87x). Einzelne Bits spezieller interne Register
schalten die Pins auf die Spezialfunktion um, womit sie dann nicht
mehr Bestandteil des normalen Ports sind.
Die Pins des Port A von PICs mit ADC (z.B. des 16F876) sind nach dem Einschalten des PIC oder nach Reset als analoger Eingang konfiguriert! Will man diese Pins als digitale Bits des Port A nutzen, muss man ihre Funktion zuerst umschalten.
Der Programmspeicher eines PIC ist ein Speicherblock, der an der
Adresse 0000h beginnt. Die Programmspeichergröße ist typabhängig.
Da der ProgramCounter (PC) aber nur 13-Bit lang ist, ist die
größte adressierbare Programmspeicherzelle die Zelle 8191 (1FFFh).
Kein PIC der Serien PIC12F.../PIC16F... kann also mehr als 8191
(8k) Befehle speichern. Was dem Windows-Nutzer wenig erscheint,
ist aber schon eine ganze Menge. Selbst umfangreiche Projekte
füllen bei mir meist nur einen kleinen Bruchteil des vorhandenen
Flash-Speichers. Wer wirklich mehr Programmspeicher braucht, kann
auf die PICs der Serie PIC18F...
ausweichen.
Typ | Programmspeichergröße [Worte] | 1. Adresse | letzte Adresse |
PIC12F629/675 | 1k | 0000h | 03FFh |
PIC16F84 | 1k | 0000h | 03FFh |
PIC16F873 | 4k | 0000h | 0FFFh |
PIC16F876 | 8k | 0000h | 1FFFh |
Zwei Zellen des Programmspeichers haben eine feste Funktion:
Adresse | Name | Funktion |
0000h | Startvektor | an dieser Stelle beginnt der PIC die Programmabarbeitung nach dem Einschalten oder dem Reset |
0004h | Interruptvektor | hierhin springt der PIC bei der Auslösung eines Interrupt |
Zur Verwaltung des Programmspeicher dienen der Programcounter (PC), der die Adresse des nächsten auszuführenden Befehls enthält, und ein Stack (8 Worte groß) in dem bei Unterprogrammaufrufen der PC des rufenden Programmteils gespeichert wird.
Aufteilung des Programmspeichers in Bänke
(Pages) zu je 2k (2048 Befehle) ( siehe auch hier ! )
Da die Sprungbefehle CALL und GOTO (wie alle Befehle) nur 14-Bit
lang sind, können sie keine kompletten 13-Bit langen Adressen
enthalten. Stattdessen enthalten sie nur die unteren 11 Bit des
Sprungziels. Die oberen beiden Bits werden beim Sprung aus den
Bits 3&4 des Registers PCLATH entnommen. Daraus ergibt sich
automatisch eine Aufteilung des Programmspeichers in 4 Bänke zu je
2k-Adressen. Innerhalb einer Bank kann man problemlos mit den
Sprungbefehlen arbeiten. Will man aber in eine andere Bank
springen (also mehr als 2k-Programmspeicher nutzen), dann muss man
dafür die Bits des Registers PCLATH setzen oder löschen und
danach einen Befehl ausführen, der den PC verändert (z.B. CALL, GOTO oder ADDWF PCL). Dabei
werden die beiden obersten Bits aus PCLATH benutzt, und man
springt in die andere Programmspeicher-Bank.
Das Ganze ist natürlich nur dann von Bedeutung, wenn der
verwendete PIC mehr als 2k-Worte Flash-Speicher hat.
Der Datenspeicher des PIC ist vergleichsweise kompliziert aufgebaut. Er besteht aus bis zu 4 Bänken, und teilt sich den Adressbereich mit den Steuerregistern des PIC. Daten- und Programmspeicher sind völlig unabhängig, so dass in beiden Speichern die gleichen Adressen benutzt werden können.
Der Datenspeicher wird mit 7-Bit langen Adressen verwaltet. Damit sind 128 Speicherzellen adressierbar (00h .. 7Fh). Diese 128 Adressen bilden eine Bank. Durch das Setzen zweier spezieller Steuerbits im STATUS-Register (RP0, RP1) kann man zwischen den Bänken 0, 1, 2 und 3 umschalten. (Dieses Steuerregister ist sinnvollerweise in allen Bänken an der selben Stelle (Adresse) zu finden.) Damit stehen insgesamt 512 Adressen zur Verfügung. Jede Speicherzelle ist 1 Byte groß. ( Details siehe hier ! )
Allerdings sind bei weitem nicht alle Adressen auch mit Speicherzellen verknüpft.
Die folgende Tabelle zeigt exemplarisch die vorhandenen
RAM-Zellen einiger PIC-Typen:
Typ | Gesamtgröße | immer zugänglich | nur in Bank 0 | nur in Bank 1 | nur in Bank 2 | nur in Bank 3 |
PIC12F629/675 | 64 Byte | 64 Byte (20h - 5Fh) |
- | - | nicht vorhanden | nicht vorhanden |
PIC16F84 | 68 Byte | 68 Byte (0Ch - 4Fh, 8Ch - CFh) |
- | - | nicht vorhanden | nicht vorhanden |
PIC16F873 | 192 Byte | - | 96 Byte (20h - 7Fh) |
96 Byte (A0h - FFh, 20h - 7Fh) |
greift auf Bank 0 zu | greift auf Bank 1 zu |
PIC16F876 | 368 Byte | 16 Byte (70h - 7Fh, F0h - FFh, 170h - 17Fh, 1F0 - 1FFh) |
80 Byte (20h - 6Fh) |
80 Byte (A0h - EFh, 20h - 6Fh) |
16 Byte (110h - 11Fh) und 80 Byte (120h - 16Fh, 20h - 6Fh) |
16 Byte (190h - 19Fh) und 80 Byte (1A0h - 1EFh, 20h - 6Fh) |
Für diesen Zweck besitzt der PIC einige EEPROM-Speicherzellen,
die ihre Daten auch beim Abschalten der Stromversorgung halten.
Jede Speicherzelle ist 1 Byte groß. Das Schreiben und Lesen dieser
Speicherzellen erfolgt indirekt und benötigt deshalb mehrere
Befehle. Auch ist das Schreiben langsam (ca. 4 ms pro Byte).
Typ | Anzahl der EEPROM-Zellen (Bytes) |
PIC12F629/675 | 128 |
PIC16F84 | 64 |
PIC16F873 | 128 |
PIC16F876 | 256 |
Der Hersteller gibt für die PICs je nach Typ eine Lebensdauer von
100 000 EEPROM-Schreibzyklen (ältere Typen) bzw. 1 Million
EEPROM-Schreibzyklen (neuere Typen) an.
Einige wenige Typen-Typen (z.B. PIC16F7x sowie alle PIC18FxxJ /
PIC24 / dsPIC33) enthalten keinen Daten-EEPROM.
Wie man im Programm auf den EEPROM zugreift,
ist hier erläutert.
Wie man EEPROM-Daten schon im
Assemblerquelltext festlegt, ist hier erläutert.
Autor: sprut
erstellt: 2000
letzte Änderung: 26.06.2007