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 -r2
Hinweise:
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.