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