Tutorial sur SDCC 2.6.0 pour PIC18F J’ai essayé ce compilateur Open Source avec des PIC18F252 et 18F452.
Visiblement le portage des PIC16F (pic14) n’est pas encore au point car je n’arrive pas à compiler correctement mes programmes sur 16F. J’ai donc fait ce tutorial uniquement pour les PIC18F (pic16) en attendant les prochaines versions du compilo. Téléchargements :
Il faut installer le compilateur C SDCC. Ensuite il faut ajouter les UnixTools pour avoir la commande make.
SDCC : http://sdcc.sourceforge.net/ UnixTools : http://unxutils.sourceforge.net/ (extraire UnxUtils.zip et UnxUpdates.zip dans un dossier style c:\UnxUtils) Mplab 7.10 ou plus récent pour le fichier linker (GPASM http://gpasm.sourceforge.net/ : pour les fichiers linker) Il faut ajouter le path au système (Bouton droit “propriétés” sur le “Poste de travail” ; onglet “avancé”, “variables d’environnement” ; ajouter le chemin c:\UnxUtils\usr\local\wbin dans la variable PATH)
Vérification de l’installation :
Si Windows n’arrive pas à trouver le compilo ou la commande make il faut vérifier la variable d’environnement PATH. Makefile pour PIC18F452 :
Pour commencer il faut créer un fichier Makefile qui appelera le compilateur. On précise le compilateur sdcc dans la variable CC. Les options de compilations sont dans CFLAGS : -mpic16 : PIC18F -p18F452 : cible LD sert à spécifier le linker. La variable LIB précise le chemin des librairies et les librairies à linker. Le nom su projet est dans la variable PROJECT Les fichier .c sont compilés en .o automatiquement avec la règle $%.o:%.c Le fichier main.c sera donc automatiquement compilé en main.o La génération du fichier hex est réalisée à l’aide du linker, des fichiers .o et du fichier 18f452.lkr (expliqué dans le paragraphe suivant). CC=sdcc LD=sdcc CFLAGS= -mpic16 -p18F452 --fstack LIB= -IC:\appwin\langages\sdcc\lib\pic16 libio18f452.lib libc18f.lib #libsdcc.lib GPASM=gpasm -c GPLINK=gplink PROJECT=demo_sdcc SDCC_DEFINES=-DDEBUG_MODE=0OBJS= \ main.o $(PROJECT).hex: $(OBJS) $(LD) $(LDFLAGS) -Wl-s18f452.lkr --use-crt=crt0.o -mpic16 -p18f452 $(OBJS) $(LIB) -o$(PROJECT).hex $%.o: %.c $(CC) $(CFLAGS) $(SDCC_DEFINES) $< -o $@ clean: rm -rf *.o *.cod *.map *.lst *.bak |
Pour nettoyer le projet il faut appeler la commande ‘make clean’. La compilation se fait à l’aide de la commande ‘make’ Pour plus d’informations sur les makefiles : http://en.wikipedia.org/wiki/Make
Fichier linker 18f452.lkr (basé sur C:\Program Files\Microchip\MPASM Suite\LKR\ ou C:\gputils\lkr\) : Ce fichier décrit le mapping mémoire du microcontroleur : point d’entrée, adresse de la configuration, de l’eeprom. On ne touchera pas à ce fichier sauf dans le cas de l’utilisation d’un bootloader par exemple.
// $Id: 18f452.lkr,v 1.10 2006/08/19 02:50:46 craigfranklin Exp $ // File: 18f452.lkr // Sample linker script for the PIC18F452 processor // Not intended for use with MPLAB C18. For C18 projects, // use the linker scripts provided with that product. LIBPATH . CODEPAGE NAME=vectors START=0x0 END=0x29 PROTECTED CODEPAGE NAME=page START=0x2A END=0x7FFF CODEPAGE NAME=idlocs START=0x200000 END=0x200007 PROTECTED CODEPAGE NAME=config START=0x300000 END=0x30000D PROTECTED CODEPAGE NAME=devid START=0x3FFFFE END=0x3FFFFF PROTECTED CODEPAGE NAME=eedata START=0xF00000 END=0xF000FF PROTECTED ACCESSBANK NAME=accessram START=0x0 END=0x7F DATABANK NAME=gpr0 START=0x80 END=0xFF DATABANK NAME=gpr1 START=0x100 END=0x1FF DATABANK NAME=gpr2 START=0x200 END=0x2FF DATABANK NAME=gpr3 START=0x300 END=0x3FF DATABANK NAME=gpr4 START=0x400 END=0x4FF DATABANK NAME=gpr5 START=0x500 END=0x5FF ACCESSBANK NAME=accesssfr START=0xF80 END=0xFFF PROTECTED |
Exemple de main.c simple :
La documentation du compilateur SDCC (sdccman.pdf) donne déjà des informations sur les options de compilation, les interruptions et autres spécificités du compilo et du microcontroleur : se reporter au chapitre ‘The PIC16 port’ En général je définis mes broches d’entrées sorties dans un fichier port.h. La définition des registres du PIC se trouve dans le fichier : C:\appwin\langages\sdcc\include\pic16\pic18f452.h Tous les registres sont défnis à l’aide de champs de bits.
//---------------------------------------------------------------------------- /** @file port.h * @brief Input ouput port definition */ //---------------------------------------------------------------------------- #ifndef PORT_H #define PORT_H
#include "pic18f452.h" // definition des registres
#define FOSC 44236800L // 11.0592 MHz HSPLL x4
//---------------------------------------------------------------------------- // Types //---------------------------------------------------------------------------- typedef unsigned char u8; typedef signed char s8; typedef unsigned int u16; typedef signed int s16;
//---------------------------------------------------------------------------- // Push button //---------------------------------------------------------------------------- #define BP1 PORTCbits.RC5
#define LED_AFF1 PORTBbits.RB3 #define LED_AFF2 PORTBbits.RB1 #define LED_AFF3 PORTBbits.RB2 #define LED_AFF4 PORTBbits.RB4
// 1 input, 0 output 76543210 #define TRISACONF 0xFF // 11111111 #define TRISBCONF 0xC1 // 11000001 #define TRISDCONF 0x00 // 00000000 #define TRISECONF 0x00 // 00000000
#endif
|
Dans le main.c on inclut la définition des ports (port.h) ainsi que le header stdio.h Pour la configuration des fusibles il faut regarder le fichier pic18f452.h ainsi que la datasheet du PIC. La fonction init_system() configure la direction des ports d’entrée sortie. //---------------------------------------------------------------------------- /** @file main.c * @brief Exemple simple */ //---------------------------------------------------------------------------- // Includes files //---------------------------------------------------------------------------- #include <pic18fregs.h> #include "pic18f452.h" #include <stdio.h> #include <signal.h> // for interrupt
//---------------------------------------------------------------------------- // Configuration Register //---------------------------------------------------------------------------- #include "port.h"
// HS w/PLL Enabled, Clk Freq = 4xFreq Osc. //_OSC_HS_1H code char at __CONFIG1H _conf0 = _OSC_HS_PLL_1H & _OSCS_OFF_1H;
// BORDIS=brown out reset disabled, WDTDIS=watch dog timer disabled code char at __CONFIG2L _conf1 = _BODEN_OFF_2L & _PUT_ON_2L; code char at __CONFIG2H _conf2 = _WDT_OFF_2H; code char at __CONFIG4L _conf4 = _LVP_OFF_4L & _BACKBUG_OFF_4L & _STVR_OFF_4L;
//================================================= /** initialisation des parametres */ //================================================= void init_system(void){ //=============== INITIALISATION DES PORTS I/O ===============// PORTA = 0; // Sorties portA a 0 PORTB = 0; // sorties portB a 0 // PORTC = 0; // sorties portC a 0 !! NE PAS METTRE A ZERO RC6/7 UART PORTC &= 0xC0; PORTD = 0; // sorties portD a 0 PORTE = 0; // sorties portE a 0 ADCON0 = 0xC1; // RC, canal 0, GO, A/D on ADCON1 = 0x44; // left justify (8bits), RC, RA3,1,0 ANA
TRISA = TRISACONF; // '1' entree ; '0' sortie TRISB = TRISBCONF; // '1' entree ; '0' sortie TRISC = TRISCCONF; // '1' entree ; '0' sortie TRISD = TRISDCONF; // '1' entree ; '0' sortie TRISE = TRISECONF; // '1' entree ; '0' sortie
//========= CONFIGURATION DES INTERRUPTIONS ==========// }
//---------------------------------------------------------------------------- /** Main program */ //---------------------------------------------------------------------------- void main(void) { u8 i; // initialize system I/O init_system(); while(1) { for(i=0;i<255;i++); LED_AFF1 = 0; for(i=0;i<255;i++); LED_AFF1 = 1; } }
|
Exemple d’interrution sur le Timer0 :
Il faut inclure le header signal.h. La macro DEF_HANDLER permet de spécifier la fonction qui prendra en charge les interruptions sur le timer0 (signal SIG_TMR0). #include <signal.h> // for interrupt //---------------------------------------------------------------------------- // Interrupt handler //---------------------------------------------------------------------------- DEF_INTHIGH(high_int) DEF_HANDLER(SIG_TMR0, _tmr0_handler) END_DEF
SIGHANDLER(_tmr0_handler) {
// Clear interrupt flag; INTCONbits.T0IF = 0; }
|
Programmation du fichier hex :
On programmera le fichier hex généré à l’aide d’un programmateur ProPIC et de WinPIC800 par exemple.
Projet complexe : Horloge style radio |