SDCC
23-03-2007

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.

Image

 

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=0

OBJS= \
    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


 

Dernière mise à jour : ( 23-03-2007 )