CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Problem with Controller area network (CAN)

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
EL



Joined: 24 Feb 2008
Posts: 15
Location: POLSKA

View user's profile Send private message

Problem with Controller area network (CAN)
PostPosted: Thu Mar 27, 2008 12:02 pm     Reply with quote

Hi
I use from PIC16F876 MCP2515.
Bus speed: 125kb/s
I can not send data to card CAN at PC "Advantech PCL -841"

My hardware this:

16F876 MCP2515 PCA82C250
---SI---->S0-----
---S0---->SI----- ----->TX -RX-------->CANH
---SCK-->SCK-- ------>RX-TX-------->CANL
---C0---->CS----


Software this:
"can - mcp 2515x.h" and
"can - mcp 251x.c" :
Code:

/////////////////////////////////////////////////////////////////////////
////                        can-mcp2510.c                            ////
//// CAN Library routines for Microchip's MCP2510 (and compatable)   ////
//// CAN IO expanders.                                               ////
////                                                                 ////
////                                         ////
////                   PRZEROBIONE przez ERYK                        ////
/////////////////////////////////////////////////////////////////////////


#include <can-mcp251x_eryk.h>

//IO pins connected to MCP2510
#ifndef EXT_CAN_CS
   #define EXT_CAN_CS   PIN_C0
   #define EXT_CAN_SI   PIN_C5
   #define EXT_CAN_SO   PIN_C4
   #define EXT_CAN_SCK  PIN_C3
//   #define EXT_CAN_RESET   PIN_B5 //reset
#endif

#if CAN_DO_DEBUG
 #define can_debug printf
#else
 #define can_debug
#endif

#define READ 0x03
#define WRITE 0x02
#define READSTATUS 0xA0
////////////////////////////////////////////////////////////////////////
//
// can_init()
//
// Inicjalizacja MCP2515.Ustawiam tak filtry i maski by wszystkie ID's mogly byc odebrane.
// Konfiguruje bufory tak by odbieraly wszystkie wazne wiadomosci...
//
////////////////////////////////////////////////////////////////////////
void can_init(void) {
   struct struct_RXB0CTRL b_rxb0ctrl;

   mcp2510_init();

   can_set_mode(CAN_OP_CONFIG);         //tryb konfiguracyjny
   can_set_baud();            //predkosci

   b_rxb0ctrl=0;            //RXB0CTRL=0
   b_rxb0ctrl.rxm=CAN_RX_VALID;         //tryb 00 otrzymuj wszystkie wazne wiadomoĊ›ci
   b_rxb0ctrl.bukt=CAN_USE_RX_DOUBLE_BUFFER;   //gdy RXB0 pelny to przeslij do RXB1
   mcp2510_write(RXB0CTRL, (int)b_rxb0ctrl);   //przeslij do RXB0CTRL
   mcp2510_write(RXB1CTRL, (int)b_rxb0ctrl);   //przeslij do RXB1CTRL


   can_set_id(RX0MASK, CAN_MASK_ACCEPT_ALL, CAN_USE_EXTENDED_ID);  //maska 0 (RX bufor 0)   //adres=0x23h(RXM0EIDL),id=0,uzywam rozszerzonej ramki
   can_set_id(RX0FILTER0, 0, CAN_USE_EXTENDED_ID);  //filtr 0 w masce 0 (RX bufor 0)      //adres=0x03h(RXF0EIDL),id=0,uzywam rozszerzonej ramki
   can_set_id(RX0FILTER1, 0, CAN_USE_EXTENDED_ID);  //filtr 1 w masce 0 (RX bufor 0)      //adres=0x07h(RXF1EIDL),id=0,uzywam rozszerzonej ramki

   can_set_id(RX1MASK, CAN_MASK_ACCEPT_ALL, CAN_USE_EXTENDED_ID);  //maska 1 (RX bufor 1)   //adres=0x27h(RXM1EIDL),id=0,uzywam rozszerzonej ramki
   can_set_id(RX1FILTER2, 0, CAN_USE_EXTENDED_ID);  //filtr 0 w masce 1 (RX bufor 1)      //adres=0x0bh(RXF2EIDL),id=0,uzywam rozszerzonej ramki
   can_set_id(RX1FILTER3, 0, CAN_USE_EXTENDED_ID);  //filtr 1 w masce 1 (RX bufor 1)      //adres=0x13h(RXF3EIDL),id=0,uzywam rozszerzonej ramki
   can_set_id(RX1FILTER4, 0, CAN_USE_EXTENDED_ID);  //filtr 2 w masce 1 (RX bufor 1)      //adres=0x17h(RXF4EIDL),id=0,uzywam rozszerzonej ramki
   can_set_id(RX1FILTER5, 0, CAN_USE_EXTENDED_ID);  //filtr 3 w masce 1 (RX bufor 1)      //adres=0x1bh(RXF5EIDL),id=0,uzywam rozszerzonej ramki

   can_set_mode(CAN_OP_NORMAL);         //tryb normalny
}

////////////////////////////////////////////////////////////////////////
//
// can_set_baud()
//
// Konfiguracja Baud Rate(predkosci transmisji)
// SyncSeg=1TQ   
// PropSeg=1TQ
// PhSeg1=3TQ
// PhSeg2=3TQ
// -------------
// BIT TIME=8TQ=8us
// Predkosc=1/8TQ=1/8us=125kb/s
////////////////////////////////////////////////////////////////////////
void can_set_baud(void) {
   struct struct_CNF1 new_CNF1;
   struct struct_CNF2 new_CNF2;
   struct struct_CNF3 new_CNF3;


   new_CNF1.brp=CAN_BRG_PRESCALAR;      //BRP=7 czyi TQ=2x(7+1)/16MHz=1us
   new_CNF1.sjw=CAN_BRG_SYNCH_JUMP_WIDTH;   //SJW=0 czyli 1TQ

   new_CNF2.prseg=CAN_BRG_PROPAGATION_TIME;   //PRSEG=0 czyli 1TQ
   new_CNF2.phseg1=CAN_BRG_PHASE_SEGMENT_1;   //PHSEG1=2 czyli 3TQ
   new_CNF2.sam=CAN_BRG_SAM;         //SAM=0
   new_CNF2.btlmode=CAN_BRG_SEG_2_PHASE_TS;   //BTLMODE=1

   new_CNF3.phseg2=CAN_BRG_PHASE_SEGMENT_2;   //PHSEG2=2 czyli 3TQ
   new_CNF3.wakfil=CAN_BRG_WAKE_FILTER;      //WAKFIL=1

   mcp2510_write(CNF1, (int)new_CNF1);
   mcp2510_write(CNF2, (int)new_CNF2);
   mcp2510_write(CNF3, (int)new_CNF3);
}

void can_set_mode(CAN_OP_MODE mode)       //funkcja ustawiajaca tryb w normalny
   {
   struct struct_CANCTRL old_CANCTRL;

   old_CANCTRL=mcp2510_read(CANCTRL);

   old_CANCTRL.reqop=mode;

   mcp2510_write(CANCTRL, (int)old_CANCTRL);

   do {
      old_CANCTRL=mcp2510_read(CANCTRL);
   } while (old_CANCTRL.reqop != mode);
}


////////////////////////////////////////////////////////////////////////
//
// can_set_id()
//
// Konfiguracja rejestrow xxxxEIDL, xxxxEIDH, xxxxSIDL i xxxxSIDH
// Konfiguruje zdefiniowane bufory by uzywaly odpowiednich ID
//
//   Parametry:
//     addr - wskaznik do pierwszego bajtu z ID rejestru, zaczynajac od xxxxeidl.
//           
//     id - ustawia ID w buforze
//     ext - TRUE gdy uzywam rozszerzonego ID, FALSE gdy nie.
//
////////////////////////////////////////////////////////////////////////
void can_set_id(int addr, int32 id, int1 ext) {
   int converted_id[4];
   int *ptr;

   ptr=&converted_id[3];   //3=eidl, 2=eidh, 1=sidl, 0=sidh

   if (ext) {  //extended
      //eidl
      *ptr=make8(id,0); //0:7

      //eidh
      ptr--;
      *ptr=make8(id,1); //8:15

      //sidl
      ptr--;
      *ptr=make8(id,2) & 0x03;   //16:17
      *ptr|=(make8(id,2) << 3) & 0xE0; //18:20
      *ptr|=0x08;


      //sidh
      ptr--;
      *ptr=((make8(id,2) >> 5) & 0x07 ); //21:23
      *ptr|=((make8(id,3) << 3) & 0xF8);//24:28
   }
   else {   //standard
      //eidl
      *ptr=0;

      //eidh
      ptr--;
      *ptr=0;

      //sidl
      ptr--;
      *ptr=(make8(id,0) << 5) & 0xE0;

      //sidh
      ptr--;
      *ptr=(make8(id,0) >> 3) & 0x1F;
      *ptr|=(make8(id,1) << 5) & 0xE0;
   }

   //0=eidl, 1=eidh, 2=sidl, 3=sidh
   mcp2510_write(addr--, converted_id[3]);
   mcp2510_write(addr--, converted_id[2]);
   mcp2510_write(addr--, converted_id[1]);
   mcp2510_write(addr, converted_id[0]);
}

////////////////////////////////////////////////////////////////////////
//
// can_get_id()
//
// Zwraca ID z odpowiedniego bufora(odwrotnosc funkcji can_set_id())
// Uzywam tej funkcji gdy odbieram wiadomosc, widze wiadomosc i jaki ma ID.
//
//   Parametry:
//     addr - wskaznik do pierwszego bajtu z ID rejestru, zaczynajac od xxxxeidl.
//     ext - TRUE gdy uzywam rozszerzonego ID, FALSE gdy nie.
//
//   Zwraca:
//     ID z buforu
//
////////////////////////////////////////////////////////////////////////
int32 can_get_id(int addr, int1 ext) {
   int32 ret;
   int * ptr;
   int converted_id[4];

   ptr=&converted_id[3];   //3=eidl, 2=eidh, 1=sidl, 0=sidh

   converted_id[3]=mcp2510_read(addr--);
   converted_id[2]=mcp2510_read(addr--);
   converted_id[1]=mcp2510_read(addr--);
   converted_id[0]=mcp2510_read(addr);

   ret=0;


   if (ext) {
      ret=*ptr;  //eidl

      ptr--;     //eidh
      ret|=((int32)*ptr << 8);

      ptr--;     //sidl
      ret|=((int32)*ptr & 0x03) << 16;
      ret|=((int32)*ptr & 0xE0) << 13;

      ptr--;     //sidh
      ret|=((int32)*ptr << 21);
   }
   else {
      ptr-=2;    //sidl
      ret=((int32)*ptr & 0xE0) >> 5;

      ptr--;     //sidh
      ret|=((int32)*ptr << 3);
   }

   return(ret);
}

////////////////////////////////////////////////////////////////////////
//
// can_putd()
//
// Funkcja wysylania danych na magistrali CAN
//
//   Parametry:
//       id - identyfikator
//       data - wskaznik danych
//       len - dlugosc danych wysylanych
//       priority - Priorytet wiadomosci(od 0-najnizszy do 3-najwyzszy)
//                 
//       ext - TRUE gdy uzywam rozszerzonego ID, FALSE gdy nie.
//       rtr - TRUE ustawia RTR (prosba/zadanie) bit w ID, FALSE nie.
//
//    Zwraca:
//       Gdy SUKCES TRUE
//       GDy PORAZKA FALSE
//
////////////////////////////////////////////////////////////////////////
int1 can_putd(int32 id, int * data, int len, int priority, int1 ext, int1 rtr) {
   int i;
   int port;

   int TXRXBaD0;      //pole danych (8 bitow)
   int TXBaCTRL;      //rejestr konfiguracyjny
   int TXRXBaEIDL;      //rejestry identyfikatorow
   int TXBaDLC;         //rejestr dlugosci danych (RTR + 4 bity DLC)

   struct txbNctrl_struct b_TXBaCTRL;
   struct rxbNdlc_struct b_TXBaDLC;
   struct txbNctrl_struct b_TXB0CTRL, b_TXB1CTRL, b_TXB2CTRL;

   b_TXB0CTRL=mcp2510_read(TXB0CTRL);      //odczyt z TXB0CTRL i zapis do b_TXB0CTRL
   b_TXB1CTRL=mcp2510_read(TXB1CTRL);      
   b_TXB2CTRL=mcp2510_read(TXB2CTRL);

    // znajduje wolny nadajnik
    // mapowanie dostepnych bankow adresow
   if (!b_TXB0CTRL.txreq) {
      TXRXBaD0=TXB0D0;            //dane
      TXBaCTRL=TXB0CTRL;         //bity kontrolne
      TXRXBaEIDL=TXB0EIDL;         //identyfikator
      TXBaDLC=TXB0DLC;            //dl.danych
      port=0;               //bufor0
   }
   else if (!b_TXB1CTRL.txreq) {
      TXRXBaD0=TXB1D0;
      TXBaCTRL=TXB1CTRL;
      TXRXBaEIDL=TXB1EIDL;
      TXBaDLC=TXB1DLC;
      port=1;
   }
   else if (!b_TXB2CTRL.txreq) {
      TXRXBaD0=TXB2D0;
      TXBaCTRL=TXB2CTRL;
      TXRXBaEIDL=TXB2EIDL;
      TXBaDLC=TXB2DLC;
      port=2;
   }
   else {
      #if CAN_DO_DEBUG
         can_debug("\r\nCAN_PUTD() FAIL: NO OPEN TX BUFFERS\r\n");
      #endif
      return(0);
   }

   //***PRIORYTET***

   b_TXBaCTRL=mcp2510_read(TXBaCTRL);
   b_TXBaCTRL.txpri=priority;
   mcp2510_write(TXBaCTRL, (int)b_TXBaCTRL);

   //***ustawiam maski TX***

   can_set_id(TXRXBaEIDL, id, ext);

   //**ustawiam dlugosc danych***

   b_TXBaDLC=len;
   b_TXBaDLC.rtr=rtr;
   mcp2510_write(TXBaDLC, (int)b_TXBaDLC);

   //***zapis do bufora***

    for (i=TXRXBaD0; i<(TXRXBaD0 + len); i++) {
      mcp2510_write(i,*data);
      data++;
    }

   //***ENABLE transmisja***

   b_TXBaCTRL=mcp2510_read(TXBaCTRL);
   b_TXBaCTRL.txreq=1;
   mcp2510_write(TXBaCTRL, (int)b_TXBaCTRL);

   #if CAN_DO_DEBUG
            can_debug("\r\nCAN_PUTD(): BUFF=%U ID=%LX LEN=%U PRI=%U EXT=%U RTR=%U\r\n", port, id, len, priority, ext, rtr);
            if ((len)&&(!rtr)) {
               data-=len;
               can_debug("  DATA = ");
               for (i=0;i<len;i++) {
                  can_debug("%X ",*data);
                  data++;
               }
               can_debug("\r\n");
            }
   #endif

   return(1);
}

////////////////////////////////////////////////////////////////////////
//
// can_getd()
//
// Odczyt danych z biufora odbioru (jezeli sa tam dane)
//
//    Parametry:
//      id - ID
//      data - wskaznik danych
//      len - dlugosc(liczba) danych
//      stat - struktura z informacjami (ktory bufor odbiera, ext czy standard, itp)
//
//    Zwraca:
//      Funkcja wywoluje TRUE jesli cos jest w buforze odbioru,FALSE gdy nie
//
////////////////////////////////////////////////////////////////////////
int1 can_getd(int32 & id, int * data, int & len, struct rx_stat & stat)
{
    int i;

   struct struct_RXB0CTRL b_RXB0CTRL;
   struct struct_RXB1CTRL b_RXB1CTRL;
   struct struct_EFLG b_EFLG;

   int RXBaDLC;
   struct rxbNdlc_struct b_RXBaDLC;

   int TXRXBaSIDL;
   struct struct_TXRXBaSIDL b_TXRXBaSIDL;


   int RXBaD0;
   struct struct_CANINTF b_CANINTF;

   b_CANINTF=mcp2510_read(CANINTF);      //odczyt rejestru CANINTF(

   b_RXB0CTRL=mcp2510_read(RXB0CTRL);      //odczyt rejestrow kontrolnych poszczegolnych buforow
   b_RXB1CTRL=mcp2510_read(RXB1CTRL);
   b_EFLG=mcp2510_read(EFLG);         //odczyt flagi EFLG(flaga bledu)

    if (b_CANINTF.rx0if) {         //jezeli jest wiadomosc w buforze 0
        stat.buffer=0;

        stat.err_ovfl=b_EFLG.rx0ovr;      //informuje czy bufor 0 jest pelny
        b_EFLG.rx0ovr=0;         //nie jest pelny
        mcp2510_write(EFLG, (int)b_EFLG);   //przeslij do EFLG

        if (b_RXB0CTRL.bukt) {         //jezeli BUKT=1, czyli gdy RXBO jest pelny to dane sa przesylane do RXB1
         stat.filthit=b_RXB0CTRL.filhit0;   //filtry
        }

        RXBaDLC=RXB0DLC;         //dlugosc pola danych
        TXRXBaSIDL=RXB0SIDL;         //maskowanie
        RXBaD0=RXB0D0;            //dane
    }
    else if (b_CANINTF.rx1if)
    {
        stat.buffer=1;

        stat.err_ovfl=b_EFLG.rx1ovr;
        b_EFLG.rx1ovr=0;
        mcp2510_write(EFLG, (int)b_EFLG);


        stat.filthit=b_RXB1CTRL.filhit0;
        RXBaDLC=RXB1DLC;
        TXRXBaSIDL=RXB1SIDL;
        RXBaD0=RXB1D0;
    }
    else {
      #if CAN_DO_DEBUG
         can_debug("\r\nFAIL ON CAN_GETD(): NO MESSAGE IN BUFFER\r\n");
      #endif
      return (0);
    }

   //***odczyt dlugosci pola danych***

    b_RXBaDLC=mcp2510_read(RXBaDLC);      //odczyt RXBaDLC i wpisanie do zmiennej b_RXBaDLC
    len = b_RXBaDLC.dlc;         //len (dlugosc danych)
    stat.rtr=b_RXBaDLC.rtr;         //rtr (ramka danych czy ramka zdalna)

   //***extended czy standard?***

    b_TXRXBaSIDL=mcp2510_read(TXRXBaSIDL);
    stat.ext=b_TXRXBaSIDL.ext;
    id=can_get_id(TXRXBaSIDL + 2,stat.ext);

   //***odczyt danych***

    for ( i = RXBaD0; i < (RXBaD0 + len); i++ ) {
         *data=mcp2510_read(i);
        data++;
    }

    stat.inv=b_CANINTF.merrf;         
    if (b_CANINTF.merrf) {         //gdy MERRF=1 to nastapil blad (oczekiwanie na przerwanie)
      b_CANINTF.merrf=0;         //zerowanie
    }

    if (stat.buffer) {            //jezeli bufor 1
      b_CANINTF.rx1if=0;         //nie oczekuje na przerwanie od przepelnienia bufora 1
    }
    else {
      b_CANINTF.rx0if=0;         //nie oczekuje na przerwanie od przepelnienia bufora 0
    }
    mcp2510_write(CANINTF, (int)b_CANINTF);

    #if CAN_DO_DEBUG
       can_debug("\r\nCAN_GETD(): BUFF=%U ID=%LX LEN=%U OVF=%U ", stat.buffer, id, len, stat.err_ovfl);
       can_debug("FILT=%U RTR=%U EXT=%U INV=%U", stat.filthit, stat.rtr, stat.ext, stat.inv);
       if ((len)&&(!stat.rtr)) {
          data-=len;
          can_debug("\r\n    DATA = ");
          for (i=0;i<len;i++) {
            can_debug("%X ",*data);
            data++;
          }
       }
       can_debug("\r\n");
    #endif

    return(1);
}

////////////////////////////////////////////////////////////////////////
//
// can_kbhit()
//
// Zwraca TRUE jezeli w buforze odbioru sa jakies dane
//
//////////////////////////////////////////////////////////////////////////////
int1 can_kbhit(void) {
   struct struct_CANINTF b_CANINTF;

   b_CANINTF=mcp2510_read(CANINTF);
   if (b_CANINTF.rx0if || b_CANINTF.rx1if)
      {return(1);}

   return(0);
}

////////////////////////////////////////////////////////////////////////
//
// can_tbe()
//
// Zwraca TRUE jesli bufory transmisji sa puste i gotowe do transmitowania danych
//
//////////////////////////////////////////////////////////////////////////////
int1 can_tbe(void) {
   struct txbNctrl_struct b_TXB0CTRL, b_TXB1CTRL, b_TXB2CTRL;

   b_TXB0CTRL=mcp2510_read(TXB0CTRL);
   b_TXB1CTRL=mcp2510_read(TXB1CTRL);
   b_TXB2CTRL=mcp2510_read(TXB2CTRL);

   if (!b_TXB0CTRL.txreq || !b_TXB1CTRL.txreq || !b_TXB2CTRL.txreq)
      {return(1);}

   return(0);
}

////////////////////////////////////////////////////////////////////////
//
// can_abort()
//
// Odrzuca wszystkie oczekujace transmisje
//
//////////////////////////////////////////////////////////////////////////////
void can_abort(void) {
   struct struct_CANCTRL b_CANCTRL;

   b_CANCTRL=mcp2510_read(CANCTRL);
   b_CANCTRL.abat=1;            //ABAT=1,odrzucenie transmisji
   mcp2510_write(CANCTRL, (int)b_CANCTRL);

   delay_ms(5);
   b_CANCTRL.abat=0;            
   mcp2510_write(CANCTRL, (int)b_CANCTRL);
}




///////////////////
///
//
// SPI CODE
//
///
//////////////////

//data clocked in on rising edge
//data driven out on falling edge
/*
int mcp2510_read(int address)
{
   int command[2];
   int i;
   int data;

   command[1]=0x03;
   command[0]=address;

   output_low(EXT_CAN_CS);

   for (i=0;i<16;i++)
   {
      output_bit(EXT_CAN_SI, shift_left(&command[0],2,0));
      output_high(EXT_CAN_SCK);
      output_low(EXT_CAN_SCK);
   }
   for (i=0;i<8;i++)
   {
      shift_left(&data,1,input(EXT_CAN_SO));
      output_high(EXT_CAN_SCK);
      output_low(EXT_CAN_SCK);
   }

   output_high(EXT_CAN_CS);

   return(data);
}
*/

////////////////kod ERYK//////////////////////

int mcp2510_read(int address)
{
   int data;

   output_low(EXT_CAN_CS);    //zalaczenie MCP2515
   spi_write(READ);       //wyslanie instrukcji odczytu
   spi_write(address);       //odczyt z rejestru
   data = spi_read(0x00);    //odczyt z rejestru do data
   output_high(EXT_CAN_CS);    //SPI koniec

   return(data);
}

////////////////KONIEC kod ERYK//////////////////////
/*
int mcp2510_status(void) {
   int command;
   int data;
   int i;

   command=0xA0;

   output_low(EXT_CAN_CS);

   for (i=0;i<8;i++) {
      output_bit(EXT_CAN_SI, shift_left(&command,1,0));
      output_high(EXT_CAN_SCK);
      output_low(EXT_CAN_SCK);
   }
   for (i=0;i<8;i++) {
      shift_left(&data,1,input(EXT_CAN_SO));
      output_high(EXT_CAN_SCK);
      output_low(EXT_CAN_SCK);
   }
   for (i=0;i<8;i++) {
      output_high(EXT_CAN_SCK);
      output_low(EXT_CAN_SCK);
   }

   output_high(EXT_CAN_CS);

   return(data);
}
*/
////////////////kod ERYK//////////////////////

int mcp2510_status(void)
{
   int data;
   
   output_low(EXT_CAN_CS);    //zalaczenie MCP2515
   spi_write(READSTATUS);    //wyslanie instrukcji statusu
   data = spi_read(0x00);    //odczyt z rejestru do data
   output_high(EXT_CAN_CS);    //wylaczenie MCP2515

   return(data);
}

////////////////KONIEC kod ERYK//////////////////////
/*
void mcp2510_write(int address, int data) {
   int command[3];
   int i;

   command[2]=0x02;
   command[1]=address;
   command[0]=data;

   output_low(EXT_CAN_CS);

   for (i=0;i<24;i++) {
      output_bit(EXT_CAN_SI, shift_left(&command[0],3,0));
      output_high(EXT_CAN_SCK);
      output_low(EXT_CAN_SCK);
   }

   output_high(EXT_CAN_CS);
}
*/
////////////////kod ERYK//////////////////////
void mcp2510_write(int address, int data)
{
   output_low(EXT_CAN_CS);    //zalaczenie MCP2515
   spi_write(WRITE);       //wyslanie instrukcji zapisu
   spi_write(address);       //adres
   spi_write(data);       //dana
   output_high(EXT_CAN_CS);    //SPI koniec
}
////////////////KONIEC kod ERYK//////////////////////
/*
void mcp2510_command(int command) {
   int i;

   output_low(EXT_CAN_CS);

   for (i=0;i<8;i++) {
      output_bit(EXT_CAN_SI, shift_left(&command,1,0));
      output_high(EXT_CAN_SCK);
      output_low(EXT_CAN_SCK);
   }

   output_high(EXT_CAN_CS);
}
*/
////////////////kod ERYK//////////////////////
void mcp2510_command(int command)
{
   output_low(EXT_CAN_CS);    //zalaczenie MCP2515
   spi_write(command);       //wyslanie komendy
   output_high(EXT_CAN_CS);    //SPI koniec
}
////////////////KONIEC kod ERYK//////////////////////

void mcp2510_init(void)
{
   output_high(EXT_CAN_CS);
   mcp2510_command(0xC0);   //reset
   delay_ms(5);
}
///////////////KONIEC/////////////////////////////////


main:
Code:

#include <16F876.h>
#include <F876.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

#define CAN_DO_DEBUG TRUE

#include <can-mcp251x.c>
void main()
{
   struct rx_stat rxstat;
   int32 rx_id;
   int buffer[8];
   int rx_len;
   int data=0x05;

   int i;

trisc_0=0;       
trisc_1=0;                   
trisc_2=0;                   
trisc_3=0;                   
trisc_4=0;                     
trisc_5=1;                   
trisc_6=0;                     
trisc_7=0;

//Tryb MASTER,czestowliowsc 1MHz
//SSPCON=00100000(SSPEN=1),SSPSTAT=1000000(SMP=1,CKP=0,CKE=0)
setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_4 | SPI_SAMPLE_AT_END);

   for(i=0;i<8;i++) {
   buffer[i]=0;
   }

   can_init();
while(TRUE)
   {
     
      can_putd(0x202, &data, 1,1,1,0);     //put data on transmit buffer
      delay_ms(1000);
    }
}

What do I do bad?
I thank for help
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Mar 27, 2008 3:42 pm     Reply with quote

Your question is really how to convert the CCS MCP2515 driver from
using software SPI to using hardware SPI.
Quote:

trisc_0=0;
trisc_1=0;
trisc_2=0;
trisc_3=0;
trisc_4=0;
trisc_5=1;
trisc_6=0;
trisc_7=0;

CCS handles setting the TRIS for you. You don't have to do this.
If you use "standard i/o" mode (the default mode of the compiler)
and if you use CCS i/o functions (such as output_low(), etc.), then
the compiler will automatically set the correct TRIS for you.
Also, if you use CCS built-in functions such as setup_spi(), the compiler
will automatically setup the correct TRIS for the SDO, SDI, and SCK pins.
Delete those lines above.


Quote:

setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_4 | SPI_SAMPLE_AT_END);

This is wrong. You're setting the wrong SPI mode. Here is a list of
SPI mode definitions. You're setting mode 1, with sample at end.
Code:

#define SPI_MODE_0_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_0_1  (SPI_L_TO_H)
#define SPI_MODE_1_0  (SPI_H_TO_L)
#define SPI_MODE_1_1  (SPI_H_TO_L | SPI_XMIT_L_TO_H)

Look on page 63 of the MCP2515 data sheet:
http://ww1.microchip.com/downloads/en/DeviceDoc/21801e.pdf
It tells you the correct SPI mode to use:
Quote:
12.0 SPI INTERFACE
12.1 Overview
The MCP2515 is designed to interface directly with the
Serial Peripheral Interface (SPI) port available on many
microcontrollers and supports Mode 0,0 and Mode 1,1.


Add those #define statements to your program and then change the
setup_spi() statement to this:
Code:
setup_spi(SPI_MASTER | SPI_MODE_0_0 | SPI_CLK_DIV_4);


Also make sure you connect a 120 ohm termination resistor across the
CANH and CANL lines next to the PCA82C250 on your PIC board.
You need a termination resistor on your board and also on the PCL-841.
The Advantech PCL-841 board has terminator resistors on it for each
CAN bus connector. But you must install a jumper on the board (JP9 or
JP10) to enable the resistors. Make sure you do that.
EL



Joined: 24 Feb 2008
Posts: 15
Location: POLSKA

View user's profile Send private message

PostPosted: Fri Mar 28, 2008 3:50 am     Reply with quote

I thank PCM programmer Smile
I will check this all really on Monday because I will be then dust card CAN.
You assured me in conviction from these TRIS'es.thanks
I will improve also settings SPI and resistor (120 ohm) I have on single board only I forgot about inserting jumper.
Salute:)
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group