Zum umgehen der 1k-Grenze sind folgende drei Schritte notwendig:
Die folgende Abbildung zeigt diesen prinzipiellen Vorgang
Wird also eine C-Datei so groß, dass es beim Kompilieren die 1k-Grenze überschreitet, so muss es in mehrere
C-Dateien aufgeteilt werden, wobei auch hier gilt: Jede C-Datei darf beim kompilieren die 1k-Grenze nicht
überschreiten!
Im Prinzip sieht dann das gesamte Projekt zum Beispiel folgendermaßen aus:
Hier bestehend aus zwei C-Dateien (Demo2_Teil1.C und
Demo2_Teil2.C) und einer Header-Datei (PROJEKT.H).
(Achtung: Es geht hier nur um das Prinzip, daher ist der folgende Code-Ausschnitt kein voll funktionsfähiges
Projekt!)
Erste C-Datei (z.B. Demo2_Teil1.C)
/****************************************************************************************/ /* Projekt zur Demo (Umgehung der 1k-Grenze) */ /* */ /* Entwickler: Buchgeher Stefan */ /* Entwicklungsbeginn der Software: 20. Mai 2006 */ /* Funktionsfaehig seit: 20. Mai 2006 */ /* Letzte Bearbeitung: 20. Mai 2006 */ /****************************************************************************************/ /****************** Include-Dateien *****************************************************/ #include "PROJEKT.H" #include <16CXX.H> // Ist fuer die Interrupts notwendig #include <INLINE.H> // Ist fuer Assembleranweisungen notwendig /****************** Konfigurations-Bits *************************************************/ #pragma config |= 0b.11110100111010 /****************** ISR - Timer0 ********************************************************/ /****************************************************************************************/ /* Interrupt Service Routine (ISR): */ /****************************************************************************************/ #pragma origin 4 interrupt ISR(void) // Interruptroutine { int_save_registers // W, STATUS (und PCLATH) retten // Beginn der eigentlichen ISR-Routine int_restore_registers // W, STATUS (und PCLATH) Wiederherstellen } /****************************************************************************************/ /* INIT: */ /* */ /* Aufgabe: */ /* Initialisierung des Prozessor: */ /****************************************************************************************/ void INIT(void) { // Timer-0-Interrupt TMR0 = 0; // Timer 0 auf 0 voreinstellen OPTION = 0b.1000.0011; // Pull-Up-Widerstaende am Port B deaktivieren // Timer-ISR (Vorteiler = 16) // Ports TRISA = 0xFF; // Port A und Port E muessen bei verwendung als TRISE = 0xFF; // ADC als Eingang konfiguriert werden TRISB = 0; // Port B als Ausgang definieren TRISC = 0b.1111.1001; // Port C: Bits 1 und 2 als Ausgang definieren // Port C: Bits 0 und 3 bis 7 als Eingang definieren TRISD = 0; // Port D als Ausgang definieren // ADC ADON = 1; // ADC global einschalten ADCON1 = 0b.1000.0010; // Ganzer Port A als Analog; Vref+ = Vdd, Vref- = Vss // und linksbuendig ADCS0 = 0; // Geschwindigkeit des ADC mit ADCS0 und ADCS1 ADCS1 = 1; // usw. } void delay_us(char mikro) { #asm wdh9 nop nop decfsz mikro,f goto wdh9 #endasm } /****************** Unterprogramm zur Analog-Digital-Wandlung ***************************/ /****************************************************************************************/ /* ADC: */ /* */ /* Aufgabe: */ /* Analog-Digital-Wandlung mit dem PIC-interne ADC fuer den ausgewaehlten ADC-Kanal */ /* starten, auf das Wandlungsergebnis warten und dieses dem aufrufenden Programm */ /* zurueckgeben. */ /* */ /* Uebergabeparameter: */ /* kanal: */ /* */ /* Rueckgabeparameter: */ /* 6-Bit-Ergebnis der Analog-Digital-Wandlung im EXTERNEN UEBERGABEREGISTER */ /* (tmp_uebergabe_uns16) */ /* */ /* Vorgehensweise: */ /* + ADC-Kanal auswaehlen (Bits <3:5> im Register ADCON0). Dazu muss die Kanal-Nummer */ /* an diese Position geschoben werden und mit dem Register ADCON0 verknuepft werden */ /* + ca. 50 Mikrosekunden (us) warten. Diese Zeit benoetigt der PIC um den internen */ /* Kondensator mit der zu messenden Analogspannung zu laden. */ /* + Analog-Digital-Wandlung starten. Dazu das Flag GO (im Register ADCON0) setzen. */ /* + Warten, bis der PIC mit der Wandlung fertig ist. Der PIC setzt das Flag GO auto- */ /* matisch zurueck, wenn er mit der Analog-Digital-Wandlung fertig ist. */ /* + Aus den Registern ADRESL und ADRESH das Ergebnis zusammensetzen und an das auf- */ /* rufende Unterprogramm (oder Hauptprogramm) zurueckgeben */ /* */ /* Anmerkung: */ /* Das Ausgabeformat der ADC-Wandlung, also wie die 10 Ergebnisbits in den Registern */ /* ADRESL und ADRESH abgelegt werden wird an anderer Stelle (z.B. im Unterprogramm */ /* INIT) konfiguriert. */ /****************************************************************************************/ void ADC(char kanal) { ADCON0 = ADCON0 & 0b.1100.0111; kanal = kanal << 3; ADCON0 = ADCON0 | kanal; delay_us(50); GO = 1; while(GO); tmp_uebergabe_uns16.low8 = ADRESL; // externes Uebergaberegister tmp_uebergabe_uns16.high8 = ADRESH; } /****************** Hauptprogramm *******************************************************/ void main(void) { char Wert1; INIT(); // Controller initialisieren INTCON = 0b.1010.0000; // Timer0 freigeben durch Setzen von // GIE und T0IE im Register INTCON while(1) { // aktuelle Werte einlesen Soll_Istwerte_einlesen(); // Test-Routine UNTERPROGRAMM2(); Wert1 = UNTERPROGRAMM3(123); } }
Zweite C-Datei (z.B. Demo2_Teil2.C)
/****************************************************************************************/ /* Unterprogramme zur Demo (Umgehung der 1k-Grenze) */ /* */ /* Entwickler: Buchgeher Stefan */ /* Entwicklungsbeginn der Software: 20. Mai 2006 */ /* Funktionsfaehig seit: 20. Mai 2006 */ /* Letzte Bearbeitung: 20. Mai 2006 */ /****************************************************************************************/ /****************** Projekt-Header einbinden ********************************************/ #include "PROJEKT.H" /****************** externe Register ****************************************************/ uns16 tmp_uebergabe_uns16; uns16 sollwert; uns16 istwert; /****************** weitere Unterprogramme **********************************************/ /****************************************************************************************/ /* Unterprogramm 2 */ /* */ /****************************************************************************************/ void UNTERPROGRAMM2(void) { // irgendwelche Anweisungen } /****************************************************************************************/ /* Unterprogramm 3 */ /* */ /****************************************************************************************/ char UNTERPROGRAMM3(char Parameter) { char wert; // irgendwelche Anweisungen return (wert); } /****************** Unterprogramm zur Ist- und Sollwerteingabe **************************/ /****************************************************************************************/ /* ADC: */ /* */ /* Aufgabe: */ /* Sollwert und Istwert von den analogen Eingaengen AN0 und AN1 einlesen und in den */ /* externen Registern istwert und sollwert sichern */ /****************************************************************************************/ void Soll_Istwerte_einlesen (void) { // Istwert von ADC-Eingang AN0 (Kanal 0) einlesen und in der externen Variable // istwert sichern ADC(0); istwert = tmp_uebergabe_uns16; // Sollwert von ADC-Eingang AN2 (Kanal 2) einlesen und in der externen Variable // sollwert sichern ADC(1); sollwert = tmp_uebergabe_uns16; }
Gemeinsame Header-Datei (z.B. PROJEKT.H)
/****************************************************************************************/ /* Header zur Demo (Umgehung der 1k-Grenze) */ /* */ /* Entwickler: Buchgeher Stefan */ /* Entwicklungsbeginn der Software: 20. Mai 2006 */ /* Funktionsfaehig seit: 20. Mai 2006 */ /* Letzte Bearbeitung: 20. Mai 2006 */ /****************************************************************************************/ #ifndef __PROJEKT #define __PROJEKT /****************** Pragma-Anweisungen **************************************************/ #pragma chip PIC16F877 // PICmicro Device /****************** Externe Register ***************************************************/ extern bank0 uns16 tmp_uebergabe_uns16; extern bank0 uns16 sollwert; extern bank0 uns16 istwert; /****************** Funktionsprototypen *************************************************/ /* Initialisierung des Mikrocontroller */ extern page0 void INIT(void); /* Unterprogramm zur Analog-Digital-Wandlung */ extern page0 void ADC(char kanal); /* Unterprogramm zur Ist- und Sollwerteingabe */ extern page0 void Soll_Istwerte_einlesen(void); /* Weitere Unterprogramme */ extern page0 void UNTERPROGRAMM2(void); extern page0 char UNTERPROGRAMM3(char Parameter); #endif
Im nächsten Schritt wird nun jede C-Datei (mit Hilfe des CC5X-Compilers) in eine ASM-Datei kompiliert. Diese Aufgabe übernimmt eine BAT-Datei. Dazu geht man wie folgt vor:
C:\Programme\bknd\CC5X\CC5X.EXE Demo2_Teil1.C -IC:\Programme\bknd\CC5X\ -u -r -a -r2 C:\Programme\bknd\CC5X\CC5X.EXE Demo2_Teil2.C -IC:\Programme\bknd\CC5X\ -u -r -a -r2Hinweise:
Die im vorhergehenden Schritt erzeugten Assembler-Dateien müssen nun zu einem gesamten Projekt zusammengefügt werden. Und schließlich soll daraus die zum Programmieren des PIC notwendige .HEX-Datei erzeugt werden. Dazu geht man wie folgt vor:
MPLAB starten -> Project -> Project Wizard...
Taste Weiter >
PIC auswählen (hier den PIC16F877)
Taste Weiter >
Active Toolsuite: B Knudsen Data CC5x auswählen
Taste Weiter >
Den Projektordner auswählen, wo dieses Beispiel-Projekt abgelegt werden soll. Dieser Ordner muss schon existieren!
Projektname eingeben (hier: Demo2). Anmerkung: der Projektname muss nicht identisch mit dem Ordnername sein!
Taste Weiter >
Zunächst in der rechten Spalte die Linker-Datei 16f877.lkr auswählen und die Taste Add >> anklicken. Die ausgewählte Datei erscheinen nun in die rechte Spalte. Diesen Vorgang für alle Assembler-Dateien (hier also Demo2_Teil1.asm und Demo2_Teil2.asm) und die Header-Datei PROJEKT.H wiederholen.
Taste Weiter >
Taste Fertig stellen
Project -> Build
Für jede Assembler-Datei sollte nun nacheinander die Box Assembly Successful erscheinen. Diese muss jedes Mal mit der OK-Taste bestätigt werden. Wichtig ist die Meldung BUILD SUCCEEDED am Ende der Assemblierung.