Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

Pierin PIc18 e interrupt vector

Raccolta di codici sorgenti

Moderatore: Foto UtentePaolino

0
voti

[1] Pierin PIc18 e interrupt vector

Messaggioda Foto Utentericello9 » 11 set 2013, 21:47

Ciao, sto cercando di far funzionareun display Oled con il Pierin Pic18 ma Mplax mi da un errore in fase di compilazione:
Codice: Seleziona tutto
Error - section 'LOW_INTERRUPT_VECTOR' can not fit the absolute section.
Section 'LOW_INTERRUPT_VECTOR' start=0x00000018, length=0x00001042


Da quello cha capisco il problema è l'eccessiva lunghezza "length=0x00001042" dello spazio riservato in ram al vettore dell'interrupt.
Ma come faccio a risolvere il problema?

Posto una copia del linker:
Codice: Seleziona tutto
// File: 18f47j53_g.lkr
// Generic linker script for the PIC18F47J53 processor

#DEFINE _CODEEND _DEBUGCODESTART - 1
#DEFINE _CEND _CODEEND + _DEBUGCODELEN
#DEFINE _DATAEND _DEBUGDATASTART - 1
#DEFINE _DEND _DATAEND + _DEBUGDATALEN

LIBPATH .

#IFDEF _CRUNTIME
  #IFDEF _EXTENDEDMODE
    FILES c018i_e.o
    FILES clib_e.lib
    FILES p18f47j53_e.lib

  #ELSE
    FILES c018i.o
    FILES clib.lib
    FILES p18f47j53.lib
  #FI

#FI

#IFDEF _DEBUGCODESTART
  CODEPAGE   NAME=bootloader START=0x0            END=0xFFF          PROTECTED
  CODEPAGE   NAME=vectors    START=0x1000         END=0x1029         PROTECTED
  CODEPAGE   NAME=page       START=0x102A         END=_CODEEND
  CODEPAGE   NAME=debug      START=_DEBUGCODESTART   END=_CEND        PROTECTED
#ELSE
  CODEPAGE   NAME=bootloader START=0x0            END=0xFFF          PROTECTED
  CODEPAGE   NAME=vectors    START=0x1000         END=0x1029         PROTECTED
  CODEPAGE   NAME=page       START=0x102A               END=0x1FFF7
#FI

CODEPAGE   NAME=config     START=0x1FFF8           END=0x1FFFF        PROTECTED
CODEPAGE   NAME=devid      START=0x3FFFFE          END=0x3FFFFF       PROTECTED

#IFDEF _EXTENDEDMODE
  DATABANK   NAME=gpre       START=0x0               END=0x5F
#ELSE
  ACCESSBANK NAME=accessram  START=0x0               END=0x5F
#FI

DATABANK   NAME=gpr0       START=0x60              END=0xFF
DATABANK   NAME=gpr1       START=0x100             END=0x1FF
DATABANK   NAME=gpr2       START=0x200             END=0x2FF
DATABANK   NAME=OurmVectSec      START=0x300             END=0x4FF   PROTECTED
//DATABANK   NAME=gpr4       START=0x400             END=0x4FF
DATABANK   NAME=gpr5       START=0x500             END=0x5FF
DATABANK   NAME=gpr6       START=0x600             END=0x6FF
DATABANK   NAME=OurVectSec       START=0x700       END=0x7FF    PROTECTED
//DATABANK   NAME=gpr7       START=0x700           END=0x7FF
//DATABANK   NAME=gpr8       START=0x800           END=0x8FF
//DATABANK   NAME=gpr9       START=0x900             END=0x9FF
DATABANK   NAME=gpr10      START=0xA00             END=0xAFF
DATABANK   NAME=gpr11      START=0xB00             END=0xBFF

#IFDEF _DEBUGDATASTART
  DATABANK   NAME=gpr12      START=0xC00             END=_DATAEND
  DATABANK   NAME=dbgspr     START=_DEBUGDATASTART   END=_DEND           PROTECTED
#ELSE //no debug
  DATABANK   NAME=gpr12      START=0xC00             END=0xCFF
#FI

DATABANK   NAME=gpr13      START=0xD00             END=0xDFF
DATABANK   NAME=gpr14      START=0xE00             END=0xEAF
DATABANK   NAME=sfr14      START=0xEB0             END=0xEFF          PROTECTED
DATABANK   NAME=sfr15      START=0xF00             END=0xF5F          PROTECTED
ACCESSBANK NAME=accesssfr  START=0xF60             END=0xFFF          PROTECTED

SECTION    NAME=USB_VARS        RAM=gpr10
SECTION    NAME=OurVectSec      RAM=OurVectSec
SECTION    NAME=OurmVectSec     RAM=OurmVectSec

#IFDEF _CRUNTIME
  SECTION    NAME=CONFIG     ROM=config
  #IFDEF _DEBUGDATASTART
    STACK SIZE=0x100 RAM=gpr11
  #ELSE
    STACK SIZE=0x100 RAM=gpr12
  #FI
#FI


Grazie per l'aiuto.
Marcello.
Avatar utente
Foto Utentericello9
195 1 3 7
Stabilizzato
Stabilizzato
 
Messaggi: 360
Iscritto il: 16 mar 2009, 0:13

0
voti

[2] Re: Pierin PIc18 e interrupt vector

Messaggioda Foto UtenteShockwaver » 12 set 2013, 9:32

Il codice?...
Anyone who has never made a mistake has never tried anything new
Two things are infinite: universe and human stupidity, and I'm not sure about the former
You did not really understand something unless you can explain it to your grandmother
A. Einstein
Avatar utente
Foto UtenteShockwaver
770 1 5 11
Expert
Expert
 
Messaggi: 859
Iscritto il: 3 mar 2010, 18:56

0
voti

[3] Re: Pierin PIc18 e interrupt vector

Messaggioda Foto Utentericello9 » 12 set 2013, 18:51

Il codice?...

I complimenti sono dovuti per l'ottimo articolo che hai pubblicato "Semplice mappatura della RAM nei PIC" dal quale ho tratto spunto per questo progetto.

Questo è il main:
Codice: Seleziona tutto
// File di definizione dei registri del micro.
#include "p18f47j53.h"

// File di configurazione dei fuses
#include "configurazione.h"

// Mappatura delle interrupt
#include "mappa_int.h"

// Header del main
#include "main.h"
#include "delays.h"
#include "oled.c"
#include "portb.h"
#include "one-wire.c"


//------------------------------------------------------------------------------
// Variabili globali
//------------------------------------------------------------------------------
#pragma udata

  char myString[]="12.5/"; // an array
  char TEMP[]="TEMP:";


//------------------------------------------------------------------------------
// Funzione di servizio delle interrupt ad ALTA priorità
//------------------------------------------------------------------------------
#pragma code
#pragma interrupt highPriorityInterrupt
void highPriorityInterrupt()
{

  // Verifica quale flag ha causato l' interrupt
  // Esegui la parte di codice di servizio dell' interrupt
  // Azzera il flag che ha causato l' interrupt
  // ...
}

//------------------------------------------------------------------------------
// Funzione di servizio delle interrupt a BASSA priorità
//------------------------------------------------------------------------------
#pragma interruptlow lowPriorityInterrupt
void lowPriorityInterrupt()
{
  // Verifica quale flag ha causato l' interrupt
  // Esegui la parte di codice di servizio dell' interrupt
  // Azzera il flag che ha causato l' interrupt
  // ...

}

//------------------------------------------------------------------------------
// MAIN
void main(void)
{
  EnablePullups();
 
  // Fa partire il PLL.
  // Anche se viene selezionato tramite i bit di configurazione
  // il suo funzionamento non è automatico. Ha bisogno di un comando.
  OSCTUNEbits.PLLEN = 1;
  // Attende abbastanza tempo per far stabilizzare il PLL
  Delay1KTCYx(100);
  // Da ora in poi abbiamo il PLL funzionante ed il micro con il turbo.

  // -------- Inizializzazione delle periferiche --------

  // Inizializza la PORTD
  // bit 4 input pulsante PL0
  //  "  5 input pulsante PL1
  //  "  6 output LED LED1
  //  "  7 output LED LED2
  TRISD=0b00110000;
  // Mette a 0 tutte le uscite
  LATD = 0x00;
 
  TRISB=0b00000000;
  // Mette a 0 tutte le uscite
  LATB=0x00;

  TRISA=0b00000010;
  // Mette a 0 tutte le uscite
  LATC=0x00;

  // Imposto RC7 come ingresso e RC6 come uscita per la seriale
  TRISC =0b10000000;
  // Mette a 0 tutte le uscite
  LATC=0x00;

  oled_init(); // initializing the display, to be called only once
  oled_clear();
  oled_goto(0,2);
  oled_puts(TEMP); // string example
  oled_goto(49,2);
  oled_font=FONT_BIG;
  oled_puts(myString); // s  tring example

  // -------------- Ciclo infinito di funzionamento -------------
  for(;;)
  {
     Delay1KTCYx(240);
     LATDbits.LATD7 = LATDbits.LATD7^1;

  } // for(;;)
}


Se escludo il file "one-wire.c", che utilizzo per leggere la temperatura da un DS18B20, il programma viene compilato correttamente.
Questo è one-wire.c
Codice: Seleziona tutto

#include "one-wire.h"

// resetta il bus 1-wire e rileva la presenza di dispositivi
unsigned char OWReset(void)
   {
    unsigned char ow_detect; // variabile usata per rilevare la presenza di dispositivi 1wire

      TRIS_DQ=1; // avvio con linea RC1 in alta impedenza
         LATC_DQ=0; // predispongo uscita bassa
      TRIS_DQ=0;// linea in uscita
      // linea a livello basso per 500uS
      // nota: la linea deve essere tenuta a livello basso
      // minimo 480uS
      Delay10TCYx(200);  //OK
      TRIS_DQ=1; // avvio con linea RC5 in alta impedenza
      // dopo che la linea è stata posta in alta impedenza
      // bisogna attendere dai 15 ai 60uS per una risposta
      Delay10TCYx(40);// attendo 100uS per stare tranquillo   OK
      ow_detect= PORT_DQ; // rilevo in che stato si trova la linea
      // l'impulso di presenza dura dai 60 ai 240uS
      // attendo 430uS dopo l'impulso di presenza
      Delay10TCYx(175);   //OK
      // 0 = ci sono dispositivi (OW_PRESENCE)
      // 1 = non ci sono dispositivi (OW_NO_PRESENCE)   
   // restituisco il valore ottenuto:
   return ow_detect;
    }
 



//-----------------------------------------------------------------------------
// Read 1-Wire data byte and return it
//

// leggo un byte dalla linea
int OWReadByte(void)
   {
    unsigned char i; // counter
    unsigned char value=0; // byte letto
    for(i=0; i<8; i++)
      {
        if(_OWReadBit()) // leggo un bit
         {
         // se la linea è a livello alto, sommo il bit
         // nella posizione giusta tramite lo shift
         value |= (0x01<<i);
         }
      // ritardo di 120uS per il resto del timeslot
         Delay10TCYx(48);   //OK
      }
    // restituisco il byte letto
   return value;
    }   




// scrivo un byte sulla linea
void OWWriteByte(char val)
   {
    unsigned char i; // counter
    unsigned char temp; // valore temporaneo
    for( i=0; i<8; i++) // ciclo per gli 8 bit del valore
      {
      temp=val>>i;  // sposto il byte di i posizioni per recuperare il solo bit i-esimo
        temp &= 0x01; // ottengo solo il valore 0 o 1
        _OWWriteBit(temp); // "scrivo" il bit sulla linea
        }
    // ritardo di 100uS per il resto del timeslot
      Delay10TCYx(40);   //OK
    }

// legge il codice del SINGOLO dispositivo sul bus
// e lo memorizza nell'array ID passato come argomento
void OWReadRom(unsigned char *ID)
   {
   unsigned char a;
   OWReset(); // resetto la linea one-wire
   OWWriteByte(OW_READ_ROM); // invio il comando readrom, che si può usare solo se sulla linea c'è una sola sonda
   for(a=0; a<8; a++)// ciclo per leggere gli 8 bytes restituiti dal dispositivo
      {
      // eseguo la lettura del byte a-esimo:
      ID[a]=OWReadByte();
      }
   }

// funzioni di basso livello

// leggo un singolo bit dalla linea
unsigned char _OWReadBit(void)
   {
   LATC_DQ=0; // predispongo uscita bassa
   TRIS_DQ=0; // linea in uscita
   Delay1TCY();   //OK
    TRIS_DQ=1;  // pin in alta impedenza
    // Devo aspettare minimo 10uS
   Delay10TCYx(4); //corrisponde a 14 Us  OK
    return PORT_DQ; // restituisco il valore sul quale si trova la linea
    }

// scrivo un singolo bit sulla linea   
void _OWWriteBit(char bitval)
   {
    LATC_DQ=0; // predispongo uscita bassa
    TRIS_DQ=0; // linea in uscita
      Delay1TCY();   //OK
    // se il bit vale 1, porto la linea in alta impedenza
   if(bitval==1)
      {
        TRIS_DQ=1;  // pin in alta impedenza
      }
    Delay10TCYx(40); // aspetto 100uS per la fine del timeslot  OK
    TRIS_DQ=1;  // pin in alta impedenza
    }

// avvio la conversione della temperatura e leggo il valore
// nella'array TE
void OWConvertT(void)
   {
   unsigned char a;
   OWReset(); // resetto la linea one-wire
   OWWriteByte(OW_SALTA_ROM); // invio il comando readrom, che si può usare solo se sulla linea c'è una sola sonda
   OWWriteByte(OW_CONVERT_T); // invio il comando convert_t, che converte il valore temperatura
   //Delay10KTCYx(200); // aspetto un secondo   oK
   //Delay10KTCYx(220); // aspetto un secondo   ok
   }


//-----------------------------------------------------------------------------
//     FUNZIONE PER LA LETTURA DELLA TEMPERATURA CON PIU' DISPOSITIVI
//-----------------------------------------------------------------------------


float Read_Temperature(void)
{
   unsigned char get[10];
   int k;
   long temp;
   float ftemp;
   float Celsius;

//   OWConvertT();
    OWReset();
   OWWriteByte(OW_SKIP_ROM);
   OWWriteByte(OW_LEGGI_SCRAT);
   for (k=0; k<9; k++)                  // read 9 bytes from scratchpad
      get[k]=OWReadByte();
   temp = get[1] & 0x7;               // load 3 bits of the MSB, masking any sign bits
   temp = temp << 8;                  // shift the MSB left 8 bits
   temp = (temp | get[0]);               // load all 8 bits of the LSB

   if (get[1] > 0x80)                  // sign bit set, temp is negative
      temp = temp * -1;
   ftemp = temp;
   Celsius= (ftemp/16);
   return Celsius;
}

//-------------------- Write ROMCODE ---------------------
//-------- fucntion sends 64 bits (8bytes) ROMCODE ------
//-------- require 8 bytes array  ------------------------
void OWWrite_matchROM(char *pt){
     char i;
     for(i=0; i<=7; i++){
         OWWriteByte(*pt);
         *pt++;
     }
}

void conversione (void)
{
   OWConvertT();
}         

void temperatura (void)
{
   float temp;
   temp=Read_Temperature();
}


e di seguito ti metto anche l'header
Codice: Seleziona tutto
#define   DQ     RC1     // Pin dati sul quale sono collegate le linee DQ dei dispositivi 1-wire
#define   TRIS_DQ   TRISCbits.TRISC1 // Registro TRIStato relativo alla porta usata per DQ
#define LATC_DQ   LATCbits.LATC1
#define PORT_DQ PORTCbits.RC1

// comandi specifici per il bus 1-wire
#define OW_SEARCH_ROM   0xF0   // avvia la ricerca dei dispositivi sul bus 1-wire
#define   OW_READ_ROM      0x33   // da usare per leggere l'ID quando vi è un unico dispositivo sul bus
#define   OW_MATCH_ROM   0x55   // permette di comunicare con il dispositivo specifico
#define   OW_SKIP_ROM      0xCC   // permette di comunicare con tutti i dispositivi contemporaneamente   
#define OW_CONVERT_T    0x44    //avvia la conversione della temperatura
#define OW_LEGGI_SCRAT  0xBE    //permette la lettura della memoria Scratchpad. dove risiede il valore di temperatura
#define OW_SALTA_ROM    0xCC    //salta le lettura della ROM


#define   OW_PRESENCE      0x00   // livello zero se dispositivi 1wire presenti
#define OW_NO_PRESENCE   0x01   // livello 1 se nessun dispositivo 1wire presente


// prototipi funzioni

// funzioni di alto livello
unsigned char OWReset(void); // esegue il reset della linea
int OWReadByte(void); // legge un byte dalla linea
void OWWriteByte(char val); // scrive un byte sulla linea
void OWReadRom(unsigned char *ID); // memorizza nell'array ID il ROM code del SINGOLO dispositivo sulla linea
void OWConvertT(void);//avvia la conversione per catturare il valore di temperaturate
float Read_Temperature(void);
void OWWrite_matchROM(char *pt);
void WriteHexUSART(unsigned char valore);

void temperatura(void);

// funzioni di basso livello - da non usare nelle applicazioni
unsigned char _OWReadBit(void); // legge un singolo bit dalla linea
void _OWWriteBit(char bitval); // scrive un singolo bit sulla linea

char TempStr[16];

// funzioni


Ti allego anche il file oled.c
Codice: Seleziona tutto
#include "oled.h"

#define oled_scrollstop   _oled_send(0x2E,OLED_COMMAND); // stop scroll
#define oled_on         _oled_send(0xAF,OLED_COMMAND); // turn on the panel
#define oled_off      _oled_send(0xAE,OLED_COMMAND); // turn off the panel
#define oled_nop      _oled_send(0xE3,OLED_COMMAND); // nop
#define oled_negative   _oled_send(0xA7,OLED_COMMAND); // negative display
#define oled_normal      _oled_send(0xA6,OLED_COMMAND); // non-negative display

// display initialization
void oled_init(void)
   {
   // make ports as output
   TRIS_OLCLK=0;
   TRIS_OLDIN=0;
   TRIS_OLRS=0;
   TRIS_OLRES=0;
   Delay1TCY(); //nop(1);
   Delay1TCY(); //nop(1);
   Delay1TCY(); //nop(1);
   Delay1TCY(); //nop(1);
   OLED_RESET=1;
   //Delay1KTCYx(4);//__delay_ms(1);
   Delay1KTCYx(12);//__delay_ms(1);
   OLED_RESET=0;
   //Delay1KTCYx(40); //__delay_ms(10);
   Delay1KTCYx(120); //__delay_ms(10);
   OLED_RESET=1;
   oled_off;
   _oled_send(0xD5,OLED_COMMAND); // set osc frequency...
   _oled_send(0x80,OLED_COMMAND); // ...to 0x80
   _oled_send(0xA8,OLED_COMMAND); // set mux ratio...
   _oled_send(0x3F,OLED_COMMAND); // ...to 0x3F (=63 => multiplex=64)
   _oled_send(0xD3,OLED_COMMAND); // set display offset...
   _oled_send(0x00,OLED_COMMAND); // ...to 0
   _oled_send(0x40,OLED_COMMAND); // set display start line to 0 (0x40 + 0)
   _oled_send(0x8D,OLED_COMMAND); // set charge pump...
   _oled_send(0x14,OLED_COMMAND); // ...to Vcc generated internally
   _oled_send(0xA1,OLED_COMMAND); // set segment remap (column address 127 mapped to SEG0)
   _oled_send(0xC8,OLED_COMMAND); // comm output scan direction: from left to right
   _oled_send(0xDA,OLED_COMMAND); // set comm pins configuration...
   // ...to 0x12 (alternative COM pin configuration, disable COM Left/Right remap)
   _oled_send(0x12,OLED_COMMAND); // (univision display uses 0x20)
   _oled_send(0x81,OLED_COMMAND); // set contrast control...
   _oled_send(0x7F,OLED_COMMAND); // ...to 0x7F
   _oled_send(0xD9,OLED_COMMAND); // set pre-charge period...
   _oled_send(0x22,OLED_COMMAND); // ...to 0x22
   _oled_send(0xDB,OLED_COMMAND); // set VCOMH deselect level...
   _oled_send(0x40,OLED_COMMAND); // ...to 0x40
   _oled_send(0xA4,OLED_COMMAND); // reset ram content
   _oled_send(0xA6 | OLED_NEGATIVE,OLED_COMMAND); // normal display (0xA7=negative display)
   _oled_send(0x20,OLED_COMMAND); // set memory addressing mode...
   _oled_send(0x00,OLED_COMMAND); // ...to horizontal addressing mode
   oled_clear();
   oled_on; // display on
   }

// all pixels to 0
void oled_clear(void)
   {
   int i;
   oled_goto(0,0);

   for (i=0;i<(DISPLAY_WIDTH*(DISPLAY_HEIGHT>>3));++i) // 128 (pixel width) x 8 (64 pixel height) = 1024
      {
      _oled_send(0, OLED_DATA);
      }
   curX=0;
   curY=0;
   }

// clear a row
void oled_clear_row(unsigned char row)
   {
    unsigned char u;
   oled_goto(0,row);
   
   for (u=0; u<DISPLAY_WIDTH; u++)
      {
      _oled_send(0, OLED_DATA);
      }
   curX=0;
   curY=row;
   }
   
// goto x,y

//X value must be between 0 and DISPLAY_WIDTH-1 (column)
//Y value must be between 0 and (DISPLAY_HEIGHT/8)-1 (page, not really the row)

void oled_goto(unsigned char x, unsigned char y)
   {
   _oled_send(0x00|(x&0x0F), OLED_COMMAND); // column start address - x low nibble
   _oled_send(0x10|((x&0xF0)>>4), OLED_COMMAND); // column start address - x high nibble
   _oled_send(0xB0|(y & 0x07), OLED_COMMAND); // set display ram start page to value y (0-7)
   curX=x;
   curY=y;
   }

// draw a spot
void oled_plot(unsigned char x, unsigned char y)
   {
   oled_goto(x,y>>3); // y/8 = page
   _oled_send (1<<(y%8), OLED_DATA); // y%8 = bit
   curX=x++;
   curY=y>>3;
   }

// horizontal scroll
void oled_scrollh(char direction, char delay, char rowstart, char rowend)
   {
   _oled_send(direction,OLED_COMMAND); // horizontal scroll
   _oled_send(0x00,OLED_COMMAND); // dummy byte
   _oled_send(rowstart,OLED_COMMAND); // start page
   _oled_send(delay,OLED_COMMAND); // delay value
   _oled_send(rowend,OLED_COMMAND); // end page
   _oled_send(0x00,OLED_COMMAND); // dummy byte
   _oled_send(0xFF,OLED_COMMAND); // dummy byte
   _oled_send(0x2F,OLED_COMMAND); // start scroll
   }
   
// print a char from char FONT_START
void oled_putch(unsigned char c)
   {
    char i;
   #if defined USE_BIG_FONT
   // use oled_putbigch if big font selected
   if (oled_font==FONT_BIG)
      {
      oled_putbigch(c);
      }
   else
      {
   #endif
      unsigned int u; // char index in the array
      // ascii chars out of limits becomes '?'
      if ((c<FONT_START) || (c>FONT_END))
           
         {
         c='?';
         }
      u=c-FONT_START;
      u*=FONT_WIDTH;
             
      for (i=0; i<FONT_WIDTH; i++)
         {
         if (oled_inverted)
            {
            _oled_send(~(ASCII2[u+i]), OLED_DATA);
            }
         else
            {
            _oled_send(ASCII2[u+i], OLED_DATA);
            }
         }
             
      // adding a 0-page to the right if font is 5 pixel, since
      // I've not included a space in this font
      #if FONT_WIDTH==5
         _oled_send(0xFF*oled_inverted, OLED_DATA);
         curX++;
      #endif
      curX+=FONT_WIDTH;
      if (curX>(DISPLAY_WIDTH-1))
         {
         curX=curX-DISPLAY_WIDTH;
         curY++;
         if (curY>(DISPLAY_HEIGHT-1))
            {
            curY=0;
            }
         }
      #if defined USE_BIG_FONT
      } // standard font
      #endif
   }

// print a char using the font 16x15
#if defined USE_BIG_FONT
void oled_putbigch(unsigned char c)
   {
   char i;
   unsigned int u;
   // ascii chars out of limits becomes '.'
   if ((c<mFONT_START) || (c>mFONT_END))
      {
      c='.';
      }
   u=c-mFONT_START;
   u*=mFONT_WIDTH*2;
   
   // first row of the char
   for (i=0; i<mFONT_WIDTH; i++)
      {
      if (oled_inverted)
         {
         _oled_send(~(mASCII[u+i]), OLED_DATA);
         }
      else
         {
         _oled_send(mASCII[u+i], OLED_DATA);
         }
      }
   _oled_send(0xFF*oled_inverted, OLED_DATA);
   
   curY++;
   oled_goto(curX,curY);
   // second row of the char
   for (i=0; i<mFONT_WIDTH; i++)
      {
      if (oled_inverted)
         {
         _oled_send(~(mASCII[u+i+mFONT_WIDTH]), OLED_DATA);
         }
      else
         {
         _oled_send(mASCII[u+i+mFONT_WIDTH], OLED_DATA);
         }
      }
      
   _oled_send(0xFF*oled_inverted, OLED_DATA);
   curX+=mFONT_WIDTH+1;
   curY--;
   oled_goto(curX,curY);
   }
#endif

// print a string
void oled_puts(char *s)
   {
   while(*s)
      {
      oled_putch(*s++);
      }
   }

// print a string center-aligned
void oled_puts_center(char *s, unsigned char y)
   {
    char len = 0;
   char *t;
   char v; // width of a single char
   char u=(DISPLAY_WIDTH-(len*v))>>1; // division by 2
   char h=u;
   oled_goto(0,y);
    // calculate the length of the string

   t=s;
    while (*s)
      {
        s++;
        len++;
      }

   if (oled_font==FONT_STD)
      {
      v=FONT_WIDTH;
      if (v==5) {v++;}
      }
   else
      {
      v=mFONT_WIDTH;
      }

   while (h--)
      {
      _oled_send(0xFF*oled_inverted, OLED_DATA);
      }
   oled_puts(t);
   while (u--)
      {
      _oled_send(0xFF*oled_inverted, OLED_DATA);
      }
   curX=0;
   curY=y+1;
   }

// print an unsigned integer
void oled_putun(unsigned int c)
   {
   unsigned char t,i,w;
   unsigned int k;
   w=0;
   for (i=4; i>=1; i--)
      {
      switch(i)
         {
         case 4:
            k=10000;
         break;
         case 3:
            k=1000;
         break;
         case 2:
            k=100;
         break;
         case 1:
            k=10;
         break;
         }
      t=c/k;
      if((w)||(t!=0))
         {
         oled_putch(t+0x30);
         w=1;
         }
      c-=(t*k);
      }
   oled_putch(c+0x30);
   }

// print a signed integer
void oled_putsn(signed int c)
   {
   if (c<0)
      {
      oled_putch('-');
      c*=(-1);
      }
   oled_putun(c);
   }

// paint a bitmap
// height must be a multiple of 8
void oled_bitmap(const unsigned char *bitmap, unsigned char x, unsigned char y)
   {

//   bitmap[0] = width, in pixel
//   bitmap[1] = height, in pixel
   
   unsigned char wi, hi;
   unsigned int col=0;
   unsigned char height=bitmap[1]>>3; // division by 8
   if ((bitmap[1]%8) > 0)
      {
      height+=1;
      }
   
   for (hi=0; hi<height; hi++) // row scan
      {
      oled_goto(x,y);
      for (wi=0; wi<bitmap[0]; wi++) // column scan
         {
         _oled_send(bitmap[2+col],OLED_DATA);
         col++;
         }
      y+=1;
      }
   curX=x+bitmap[0];
   curY=y+height;
   oled_nop;
   }

// paint an icon
// an icon is 8 pixel high
void oled_icon(const unsigned char *icon)
   {

//   height: 8 pixel
//   width: icon[0]

   unsigned char wi;
   for (wi=0; wi<icon[0]; wi++)
      {
      _oled_send(icon[1+wi],OLED_DATA);
      }
   curX+=icon[0];
   if (curX>(DISPLAY_WIDTH-1))
      {
      curX-=DISPLAY_WIDTH;
      curY++;
      if (curY>(DISPLAY_HEIGHT-1))
         {
         curY=0;
         }
      }
   oled_nop;
   }


// LOW LEVEL FUNCTIONS

// send a byte
void _oled_send(unsigned char a, unsigned char cmd)
   {
   char i;   
   OLED_RS=cmd; // command to execute (0) or byte to display (1)
   
   for (i=0; i<8; i++)
      {
      OLED_CLOCK=0;
      if (a & (0x80>>i)) // scan single bits from left to right
         {
         OLED_DATAIN=1;
         }
      else
         {
         OLED_DATAIN=0;
         }
      OLED_CLOCK=1;
      }
   }



e il file oled.h
Codice: Seleziona tutto
/ **********************************************************************
// STANDARD FONT - INCLUDE ONLY ONE!
// **********************************************************************

#include "font8x5.h"
//#include "font8x8.h"

// **********************************************************************
// HARDWARE SETTINGS
// **********************************************************************

// Display lines to ORbit16 lines
#define   OLED_RS         LATDbits.LATD0      // Register Select   RS/DC
#define   OLED_RESET      LATDbits.LATD1      // Reset         RES
#define   OLED_CLOCK      LATBbits.LATB5      // Clock         D0/SCLK
#define OLED_DATAIN      LATBbits.LATB6      // Data in         D1/SDIN/MOSI

// TRIS ports to OLED ports
#define TRIS_OLRS      TRISDbits.TRISD0   // Register Select   RS/DC
#define TRIS_OLRES      TRISDbits.TRISD1   // Reset         RES
#define TRIS_OLCLK      TRISBbits.TRISB5      // Clock         D0/SCLK
#define TRIS_OLDIN      TRISBbits.TRISB6   // Data in         D1/SDIN/MOSI

// NOTE!!! Hardwire Chip Select (CS) to GND
// **********************************************************************
//   PHYSICAL CONNECTIONS
// **********************************************************************
//
//  3V3 => VERDE   => Vcc
//  RS  => MARRONE => PIN2
//  CS  => BLU     =>
//  RES => BIANCO  =>
//  GND => BLU     =>
//  D0  => ARANCIO =>
//  D1  => NERO    =>
//
// **********************************************************************
// DISPLAY PREFERENCES
// **********************************************************************

#define OLED_NEGATIVE   0      // 1 if you want to use negative display
#define DISPLAY_WIDTH   128      // panel width, in pixel
#define DISPLAY_HEIGHT   64      // panel height, in pixel
#define USE_BIG_FONT         // comment if you don't want the big font

// **********************************************************************
// CONSTANTS USED FOR SOME SYMBOLS, ADD YOURS IF YOU WANT
// **********************************************************************
#define DEG      0x5C
#define ARROW_L      0x7E
#define ARROW_R    0x7F


// **********************************************************************
// DON'T TOUCH-ZONE!
// **********************************************************************
#define OLED_COMMAND   0
#define   OLED_DATA      1
#define FONT_STD      0
#define FONT_BIG      1

// scroll delays from smaller value (fast) to higher value (slow)
#define SCROLL_DELAY_1   7   // 2 frames
#define SCROLL_DELAY_2   4   // 3 frames
#define SCROLL_DELAY_3   5   // 4 frames
#define SCROLL_DELAY_4   0   // 5 frames
#define SCROLL_DELAY_5   1   // 64 frames
#define SCROLL_DELAY_6   2   // 128 frames
#define SCROLL_DELAY_7   3   // 256 frames

// scroll direction
#define SCROLL_RIGHT   0x26
#define SCROLL_LEFT      0x27

#ifndef NOP
   #define NOP {__asm__ volatile ("nop");}
#endif

#ifndef STANDARD_FONT
   #error No standard font defined!
#endif

#if defined USE_BIG_FONT
   #include "font16x15.h"
#endif

char oled_inverted=0;      // write in normal(0) or negative(1)
char oled_font=FONT_STD;   // use standard(0) of big(1) font
unsigned char curX=0;      // current value of X
unsigned char curY=0;      // current value of Y


// Function prototypes
void oled_init(void);
void oled_clear(void);
void oled_clear_row(unsigned char row);
void oled_goto(unsigned char x, unsigned char y);
void oled_scrollh(char direction, char delay, char rowstart, char rowend);
void oled_putch(unsigned char c);
void oled_puts(char *s);
void oled_puts_center(char *s, unsigned char y);
void oled_putun(unsigned int c);
void oled_putsn(signed int c);
void oled_plot(unsigned char x, unsigned char y);
void oled_bitmap(const unsigned char *bitmap, unsigned char x, unsigned char y);
void oled_icon(const unsigned char *icon);
#if defined USE_BIG_FONT
void oled_putbigch(unsigned char c);
#endif
// Low-level function prototypes
void _oled_send(unsigned char a, unsigned char cmd);


Grazie per l'aiuto
Avatar utente
Foto Utentericello9
195 1 3 7
Stabilizzato
Stabilizzato
 
Messaggi: 360
Iscritto il: 16 mar 2009, 0:13

0
voti

[4] Re: Pierin PIc18 e interrupt vector

Messaggioda Foto UtenteShockwaver » 13 set 2013, 17:04

Sì, ma se non mi fai vedere la mappatura che fai in mappa_int.h.... :D
Comunque alcune cose posso già dirtele:

1) Il codice (anche quello degli interrupt) risiede nella memoria PROGRAMMA e non in quella DATI (RAM), quindi in questo caso, nella flash.

2) Se non ti ci entra vuol dire che hai troppo codice nella isr è questo non è mai un bene. 1042 bytes di isr, anche se low, sono tanti, in linea di massima troppi per un pic18.
Non mi stancherò mai di dirlo: a meno di esigenze di timing crtiticissime ( :mrgreen: ) gli interrupt devono essere usati per il "flaggaggio" ( :mrgreen: ) di alcune condizioni: entri, resetti il flag dell'interrupt, flagghi l'evento (qualunque sia il modo, variabile incrementata, booleana cambiata) se vuoi copi un buffer (non troppo grosso) o cambi lo stato di una porta, ma poi basta, esci.
Il grosso del codice relativo ad un interrupt deve essere gestito nel main loop del programma che sarà in "ascolto" delle variabili di flag che usi nelle isr.

3) Se invece vuoi far risiedere una isr da qualche altra parte in memoria (cosa che cerco sempre, quando possibile, di evitare), puoi provare ad usare le direttive #pragma code, magari anche giocando con le sezioni nel linker script, QUELLE RELATIVE AL CODICE NON AI DATI, ad es:
Codice: Seleziona tutto
void low_isr (void);

#pragma code low_int_vector=0x18
void low_interrupt (void) {
    _asm GOTO low_isr _endasm
}
#pragma code

#pragma interruptlow low_isr

#pragma code myaddr=0x334
void low_isr (void) {
    .
    .
    .
}
#pragma code

in questo modo hai l'ingresso dell'interrupt a 0x18 com'è giusto che sia per gli interrupt low, l'uscita dall'isr come RETFIE invece che RETURN (#pragma interruptlow low_isr) e infine il codice vero e proprio, raggiunto dal GOTO in asm, all'indirizzo 0x334, o qualunque indirizzo preferisci fuori dalle zone di programma "critiche".

Comunque fammi vedere il file mappa_int.h così magari possiamo far luce perché c'è quell'errore di linker nello specifico.
O_/
Anyone who has never made a mistake has never tried anything new
Two things are infinite: universe and human stupidity, and I'm not sure about the former
You did not really understand something unless you can explain it to your grandmother
A. Einstein
Avatar utente
Foto UtenteShockwaver
770 1 5 11
Expert
Expert
 
Messaggi: 859
Iscritto il: 3 mar 2010, 18:56

0
voti

[5] Re: Pierin PIc18 e interrupt vector

Messaggioda Foto Utentericello9 » 13 set 2013, 19:38

Ciao questo è il codice del file mappa_int:
Codice: Seleziona tutto
//******************************************************************************
// Sezione per la mappatura delle interrupt.
// Questo file di configurazione serve per edirezionare opportunamente
// Le interrupt sia nei casi in cui si usa il bootloader o meno.
// QUESTA PARTE DEL FILE NON DEVE ESSERE MODIFICATA!
//******************************************************************************
// Interrupt function prototypes
void highPriorityInterrupt();
void lowPriorityInterrupt();

   
#if defined(USE_HID_BOOTLOADER)
   #define REMAPPED_RESET_VECTOR_ADDRESS         0x1000
   #define REMAPPED_HIGH_INT_VECTOR_ADDRESS   0x1008
   #define REMAPPED_LOW_INT_VECTOR_ADDRESS   0x1018
#else   
   #define REMAPPED_RESET_VECTOR_ADDRESS      0x00
   #define REMAPPED_HIGH_INT_VECTOR_ADDRESS   0x08
   #define REMAPPED_LOW_INT_VECTOR_ADDRESS    0x18
#endif

#if defined(USE_HID_BOOTLOADER)
  extern void _startup (void);        // See c018i.c in your C18 compiler dir
  #pragma code REMAPPED_RESET_VECTOR = REMAPPED_RESET_VECTOR_ADDRESS
  void _reset (void)
  {
    _asm goto _startup _endasm
  }
#endif

#pragma code REMAPPED_HIGH_INT_VECTOR = REMAPPED_HIGH_INT_VECTOR_ADDRESS
void Remapped_High_ISR (void)
{
  _asm goto highPriorityInterrupt _endasm
}

#pragma code REMAPPED_LOW_INT_VECTOR = REMAPPED_LOW_INT_VECTOR_ADDRESS
void Remapped_Low_ISR (void)
{
   _asm goto lowPriorityInterrupt _endasm
}

#if defined(USE_HID_BOOTLOADER)
//Note: If this project is built while one of the bootloaders has
//been defined, but then the output hex file is not programmed with
//the bootloader, addresses 0x08 and 0x18 would end up programmed with 0xFFFF.
//As a result, if an actual interrupt was enabled and occured, the PC would jump
//to 0x08 (or 0x18) and would begin executing "0xFFFF" (unprogrammed space).  This
//executes as nop instructions, but the PC would eventually reach the REMAPPED_RESET_VECTOR_ADDRESS
//(0x1000 or 0x800, depending upon bootloader), and would execute the "goto _startup".  This
//would effective reset the application.

//To fix this situation, we should always deliberately place a
//"goto REMAPPED_HIGH_INT_VECTOR_ADDRESS" at address 0x08, and a
//"goto REMAPPED_LOW_INT_VECTOR_ADDRESS" at address 0x18.  When the output
//hex file of this project is programmed with the bootloader, these sections do not
//get bootloaded (as they overlap the bootloader space).  If the output hex file is not
//programmed using the bootloader, then the below goto instructions do get programmed,
//and the hex file still works like normal.  The below section is only required to fix this
//scenario.
#pragma code HIGH_INTERRUPT_VECTOR = 0x08
void High_ISR (void)
{
  _asm goto REMAPPED_HIGH_INT_VECTOR_ADDRESS _endasm
}
#pragma code LOW_INTERRUPT_VECTOR = 0x18
void Low_ISR (void)
{
  _asm goto REMAPPED_LOW_INT_VECTOR_ADDRESS _endasm
}
#endif   //end of "#if defined(PROGRAMMABLE_WITH_USB_HID_BOOTLOADER)"


2) Se non ti ci entra vuol dire che hai troppo codice nella isr è questo non è mai un bene. 1042 bytes di isr, anche se low, sono tanti, in linea di massima troppi per un pic18.


Se non sbaglio entrambe le routine ISR sono vuote.

Grazie
Marcello
Avatar utente
Foto Utentericello9
195 1 3 7
Stabilizzato
Stabilizzato
 
Messaggi: 360
Iscritto il: 16 mar 2009, 0:13

0
voti

[6] Re: Pierin PIc18 e interrupt vector

Messaggioda Foto UtenteShockwaver » 13 set 2013, 21:26

Se le isr sono quelle che vedo nel main con solo dei commenti al loro interno, sì sono vuote.
Ma vedendo il file di mappatura mi accorgo che, se non usi il bootloader USB, eliminando gli #ifdef che non passano, e i commenti questo si traduce in:
Codice: Seleziona tutto
    void highPriorityInterrupt();
    void lowPriorityInterrupt();
    #define REMAPPED_RESET_VECTOR_ADDRESS      0x00
    #define REMAPPED_HIGH_INT_VECTOR_ADDRESS   0x08
    #define REMAPPED_LOW_INT_VECTOR_ADDRESS    0x18

    #pragma code REMAPPED_HIGH_INT_VECTOR = REMAPPED_HIGH_INT_VECTOR_ADDRESS
    void Remapped_High_ISR (void)
    {
      _asm goto highPriorityInterrupt _endasm
    }

    #pragma code REMAPPED_LOW_INT_VECTOR = REMAPPED_LOW_INT_VECTOR_ADDRESS
    void Remapped_Low_ISR (void)
    {
       _asm goto lowPriorityInterrupt _endasm
    }

Non chiudere il primo #pragma code, così,
Codice: Seleziona tutto
#pragma code REMAPPED_HIGH_INT_VECTOR = REMAPPED_HIGH_INT_VECTOR_ADDRESS
    void Remapped_High_ISR (void)
    {
      _asm goto highPriorityInterrupt _endasm
    }
#pragma code
mi può anche andare bene (anche se io li chiudo sempre, è buona norma), perché subito dopo c'è un nuovo #pragma code che definisce un nuovo reindirizzamento per il codice.

Ma non chiudere il secondo è un errore, perché tutto ciò che c'è dopo (il contenuto degli altri file) continua ad essere indirizzato nella stessa sezione che include appunto
Codice: Seleziona tutto
REMAPPED_LOW_INT_VECTOR_ADDRESS
definito qualche riga sopra in una #define come 0x18, da cui, credo, l'errore in fase di linking.

Prova a terminare la seconda direttiva pragma così:
Codice: Seleziona tutto
#pragma code REMAPPED_LOW_INT_VECTOR = REMAPPED_LOW_INT_VECTOR_ADDRESS
    void Remapped_Low_ISR (void)
    {
       _asm goto lowPriorityInterrupt _endasm
    }
#pragma code


Fammi sapere
O_/
Anyone who has never made a mistake has never tried anything new
Two things are infinite: universe and human stupidity, and I'm not sure about the former
You did not really understand something unless you can explain it to your grandmother
A. Einstein
Avatar utente
Foto UtenteShockwaver
770 1 5 11
Expert
Expert
 
Messaggi: 859
Iscritto il: 3 mar 2010, 18:56

0
voti

[7] Re: Pierin PIc18 e interrupt vector

Messaggioda Foto Utentericello9 » 13 set 2013, 23:27

Prova a terminare la seconda direttiva pragma così:

Codice: Seleziona tutto
    #pragma code REMAPPED_LOW_INT_VECTOR = REMAPPED_LOW_INT_VECTOR_ADDRESS
        void Remapped_Low_ISR (void)
        {
           _asm goto lowPriorityInterrupt _endasm
        }
    #pragma code


Ho pravato il tuo suggerimento sulla chiusura dei #pragma code ma il compilatore mi dava errore.

Ha questo punto come mi hai suggerito ho eliminato tutte le parti riguardanti il bootloader ed inoltre ho messo la chiusura hai #pragma code e sembra funzionare.

Questo è il codice completo:
Codice: Seleziona tutto
void highPriorityInterrupt();
void lowPriorityInterrupt();

#define REMAPPED_RESET_VECTOR_ADDRESS      0x00
#define REMAPPED_HIGH_INT_VECTOR_ADDRESS   0x08
#define REMAPPED_LOW_INT_VECTOR_ADDRESS    0x18


#pragma code REMAPPED_HIGH_INT_VECTOR = REMAPPED_HIGH_INT_VECTOR_ADDRESS
void Remapped_High_ISR (void)
{
  _asm goto highPriorityInterrupt _endasm
}
#pragma code


#pragma code REMAPPED_LOW_INT_VECTOR = REMAPPED_LOW_INT_VECTOR_ADDRESS
void Remapped_Low_ISR (void)
{
   _asm goto lowPriorityInterrupt _endasm
}
#pragma code


Grazie per l'aiuto e la pazienza
Avatar utente
Foto Utentericello9
195 1 3 7
Stabilizzato
Stabilizzato
 
Messaggi: 360
Iscritto il: 16 mar 2009, 0:13

0
voti

[8] Re: Pierin PIc18 e interrupt vector

Messaggioda Foto UtenteShockwaver » 14 set 2013, 0:05

Lo stesso errore di prima? ?%
Ma hai un
Codice: Seleziona tutto
#define USB_HID_BOOTLOADER
da qualche parte nel codice?
Anyone who has never made a mistake has never tried anything new
Two things are infinite: universe and human stupidity, and I'm not sure about the former
You did not really understand something unless you can explain it to your grandmother
A. Einstein
Avatar utente
Foto UtenteShockwaver
770 1 5 11
Expert
Expert
 
Messaggi: 859
Iscritto il: 3 mar 2010, 18:56

0
voti

[9] Re: Pierin PIc18 e interrupt vector

Messaggioda Foto Utentericello9 » 14 set 2013, 22:03

Lo stesso errore di prima? ?%
Ma hai un

Codice: Seleziona tutto
#define USB_HID_BOOTLOADER

da qualche parte nel codice?


Ho fatto una ricerca e nel progetto non ho nessun #define USB_HID_BOOTLOADER
Avatar utente
Foto Utentericello9
195 1 3 7
Stabilizzato
Stabilizzato
 
Messaggi: 360
Iscritto il: 16 mar 2009, 0:13

0
voti

[10] Re: Pierin PIc18 e interrupt vector

Messaggioda Foto UtenteShockwaver » 14 set 2013, 23:10

Scusa, volevo dire USE_HID_BOOTLOADER
Anyone who has never made a mistake has never tried anything new
Two things are infinite: universe and human stupidity, and I'm not sure about the former
You did not really understand something unless you can explain it to your grandmother
A. Einstein
Avatar utente
Foto UtenteShockwaver
770 1 5 11
Expert
Expert
 
Messaggi: 859
Iscritto il: 3 mar 2010, 18:56

Prossimo

Torna a Firmware e programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 10 ospiti