Mikrocontroller Vergleich
Ein paar Kriterien für den CPU-Core und die µC-Familie:
Compiler verfügbar, bzw wieviel will man dafür ausgeben?
Für AVR und MSP430 gibt es mit GCC einen guten und kostenlosen Compiler.
Für PIC und 8051 kann man entweder SDCC verwenden (über dessen Qualität mögen andere urteilen, ich kenne ihn nicht). Oder diverse Löhnwares, bis 4-stellige Beträge, teils auch als Demoversion mit Tricks.
Bei PIC sind das der PICC Lite von HI-TECH, der nur eine handvoll PIC12 und PIC16 unterstützt, und der CC5X, welcher zwar keine High-End PICs unterstützt, dafür die meisten Mid-Range; einzige Einschränkung der freien Version des CC5X ist die Limitierung auf 1024 Instruktionen pro Modul, nicht so gute Codeoptimierung und die Begrenzung von Variablen auf 16-Bit. Ein Vergleich aller C-Compiler für PIC findet sich hier: http://www.informel.de/pic/ccompiler.htm
Sind CPU-spezifische Erweiterungen in C erforderlich
8051: ja, 5-6 Speicherklassen für die diversen RAM-Varianten.
AVR, PIC: für die RAM/ROM-Problematik (s.u.) ja, sonst nein.
MSP430: nein.
Sind Daten in RAM und ROM mit dem gleichen Code benutzbar
AVR, PIC, alle übrigen Harvard-Architekturen: NEIN. Daten im ROM erfordern anderen Zugriff als Daten im RAM. Entweder versteckt das der Compiler in Runtime-Routinen für Pointerzugriffe, oder man kann Routinen nicht so schreiben, dass sie beides als Parameter verdauen können. Bei kleinen Programmen von ein paar KB kein Problem, bei grösseren jedoch schon. Bei AVR/GCC ziemlich fehlerträchtig.
MSP430: saubere von Neumann-Architektur. Problemlos.
Lineare Adressierung vom RAM?
PIC: 16-bit PIC ja, 14-, 12-bit PIC nein. RAM-Puffer die grösser sind als das RAM in einer Bank sind nur mit Klimmzügen möglich.
8051, AVR, MSP430 kein Problem.
Skalierbarkeit?
Vor allem für jene wichtig, die sich scheuen, für verschiedene Aufgaben verschiedene Lösungen zu verwenden.
AVR: 8-Pin/1KB bis 64pin/128KB, Tendenz steigend.
PIC: innerhalb der Familie verschiedene Architekturen.
8051: von klein bis ganz groß (aber jenseits von 64K wird's
hässlich).
MSP430: bei 60KB Flash ist definitiv Schluss.
Meine Empfehlung hier trotzdem: diese Klasse nur bis 40-60K verwenden, darüber auf 32bit (ARM-Core) umsteigen.
Wie komplex ist interrupt-feste Programmierung von I/O-Ports
Das ist besonders bei AVRs (außer den Typen seit 2004: ATtiny2313 usw.) ein Problem. Architekturbedingt ist nur ein Teil der Ports bitweise schaltbar, kein Port kann mehrere Bits gleichzeitig interrupt-fest schalten. Daher ist es eigentlich oft nötig, um Port-I/O herum Port-ändernde Interrupts abzuschalten, was aber kaum jemand macht. Folge: ab und zu "seltsames Verhalten", nicht reproduzierbar. Besonders gefährlich bei Software-Baukasten-Prinzip, wenn da manche Selbstverständlichkeiten eines Moduls plötzlich nicht mehr so selbstverständlich sind.
PIC, 8051, MSP430 können AND/OR/XOR zum Port hin, daher im Prinzip kein Problem - daran denken muss man aber trotzdem (auch das kommt wohl eher selten vor).
Beispiel:
port |= 0x03;
übersetzt sich in
IN r,port
ORI r,0x03
OUT port,r
wenn nun zwischen IN und OUT ein Interrupt auftritt, der ein anderes Bit des Ports verändert, dann geht mit dem OUT-Befehl diese Änderung verloren.
Bei MSP430 hingegen ist das ein einziger Befehl, somit problemlos:
OR port,#0x03
Code wie
port = (port & ~0x0F) | lcd_data;
ist grundsätzlich problematisch, weil das auf jedem Prozessor in mehrere Befehle zerlegt wird.
Priorisierte Interrupts
PIC12 & PIC16: nein (nur ein Interruptvektor).
PIC18: Jeder Interruptquelle kann separat eine niedrige oder hohe Priorität zugewiesen werden, die dann von auf zwei Interruptvektoren verzweigen. Welche Quelle den Interrupt ausgelöst hat, muß aber immer noch händisch festgestellt werden.
PIC17: Vier Interruptvektoren mit unterschiedlicher Priorität. Scheint es allerdings nur als OTP zu geben, deswegen wohl eher uninteressant.
AVR: Nein: Beim Sprung in die Interruptroutine wird implizit ein CLI ausgeführt, beim Rücksprung ein SEI. Ein "unwichtiger Interrupt" blockiert also evtl. einen "wichtigen". Immerhin haben Interruptquellen im Gegensatz zum PIC ihre eigenen Interruptvektoren, so daß keine Zeit mit der Suche nach der Quelle verbracht wird.
Um trotzdem für eine von mehreren Interruptquellen eine Reaktionszeiten im unteren Mikrosekundenbereich zu garantieren, hilft nur ein Trick: die weniger wichtigen Interruptroutinen tun nichts als eine Programmadresse auf den Stack zu PUSHen. Das RETI springt also zu dieser Adresse mit der eigentlichen Interruptbehandlung, das RET am Ende der Routine springt zur ursprünglichen Unterbruchstelle zurück; der zeitkritische Interrupt kann damit die andere Interruptbehandlung unterbrechen. Achtung: es muß gewährleistet sein, daß auch im worst case ein Interrupt sich nicht selbst unterbricht!
8051: ja.
I/O-Spannung
AVR, PIC, 8051: 3-5V problemlos (evtl. eingeschränkte µC-Auswahl?).
MSP430: nur 3V. Nicht 5V-kompatibel, 5V-Peripherie für I2C/RS485/CAN/... ist also nur mit Pegelkonvertierung einsetzbar.
Debugging in der Schaltung
Ist beispielsweise ein günstiges JTAG-Interface für In-Circuit Debugging verfügbar?
- AVR: ab 40-Pin-Devices JTAG günstig verfügbar [Evertool], darunter nicht oder mit debugWIRE arg teuer.
- 8051: Derivate mit JTAG verfügbar. ICEen gebraucht erschwinglich.
- PIC: Entweder Microchips ICD2 oder ein kompatibler Nachbau, wie z.B. http://www.stolz.de.be/
- MSP430: alle mit JTAG, Adapter sehr günstig/einfach zu bauen
Gehäuse
Mit DIP oder PLCC bastelt es sich leichter als mit *QFP. Die Domäne von AVR/PIC/i51.