STM32F10X Çalışmalarım

Başlatan Mucit23, 12 Mart 2012, 11:17:48

CLR

@Mucit23
Yazdığın C fonksiyonları paylaşmışsın fakat şema olmadığı için programda kullandığın portları kullandığını ve bu yazdığın fonksiyonları main içinde yerli yerinde kullandığını varsayıyorum. Programı aşağıdaki gibi düzelt

1-) Can1 clock enable
2-) remap (gpiob8-9 kullanıyorsun galiba) 
3-) Gpio ayarları : Rx input ama GPIO_Mode_IPU  (tx kısmın doğru)

100kbit için can ayarlarını vereyim
4-) CAN_SJW_1tq
5-) CAN_BS1_8tq
6-) CAN_BS2_3tq
7-) CAN_Prescaler = 30

8-) tx 'in gönderildiğinden emin ol ve timeout koy
CAN_Transmit(CAN1,&TxMessage);
while((CAN_TransmitStatus(CAN1,TxMailBox)!=CAN_TxStatus_Ok) && (TimeOut != 0))


2515 ile haberleşe bilmen için onun bitrate'ini hesaplaman , logic analyzer ile scop ile bulman lazım.
Knowledge and Experience are Power

Mucit23

@CLR Hocam biraz geç cevap yazıyorum kusura bakmayın ancak akşamdan akşama uğraşabiliyorum.

STM32 için bahsettiğiniz düzenlemeleri gerçekleştirdim. Birçok CAN ile ilgili kod parçası inceledim ve artık STM32'nin ayarlarında bir eksiklik olduğunu düşünmüyorum.

Herneyse STM32'nin ayarları yaptıktan sonra birkaç test yaptım ve edindiğim izlenimler şöyle

Şimdi STM32'nin CANTX pini çalışıyormuş. Dünde çalışıyormuş fakat benim ilk yaptığım denemede STM32 karşı tarafa sürekli veri basıp karşı taraftan gelen veriler için interrupt oluşturmasını bekliyordum. MCP2515'de aynı şekilde STM32'ye sürekli veri basıp bir yandanda karşı taraftan gelen mesajları dinliyordu.

Ben dün akşamki ilk denememde MCP2515 ile STM32 yi aynı anda çalıştırıyordum. MCP2515 STM32'ye sürekli veri basıyordu. Şimdi Sadece STM32 yi çalıştırınca CAN_TX pininden yoğun bir şekilde veri çıktığını gördüm. Yani CAN_TX çalışıyor.

Bunu gördükten sonra MCP2515'i kontrol eden pici Mesaj göndermek yerine sadece gelen mesajları dinlemesi için programladım. Yani STM32'ye hiçbir mesaj göndermiyor. Eğer STM32'den mesaj gelirse sözde interrupt oluşturacak.

İlk önce STM32'ye enerji veriyorum. Can_TX pini çok yoğun bir şekilde veri gittiğini görüyorum skop ile. Ardında MCP2515'e enerji veriyorum ve Hattaki yoğunluk çok azalıyor. Resimlerde daha net anlaşılıyor.

MCP2515 çalışmıyorken STM32'nin CAN_TX Pini

Buda MCP2515 Çalışıyorken STM32'nin CAN_TX Pini


Eğer MCP2515'de STM32'ye veri gönderince STM32'nin komple eli ayağı birbirine dolaşıyor olsa gerekki tamamen veri göndermeyide kesiyor

Şimdi ne kadar doğru emin değilim Bu sorunun Baudrate uyumsuzluğundan kaynaklanacağını düşünüyorum. Can'da güvenlik önemli biliyoruz. Verilen her bitin karşıya ulaşması lazım. STM32 birşey gönderiyor. Baudrate uygun olmadığı için MCP gelen mesajı alamıyor. STM32'de buna karşılık ne yapıyor bilmiyorum ama karşıklı mesajlaşma olunca donup kalıyor.

Benim CCS de kullandığım MCP2515 kütüphanesi budur.
/////////////////////////////////////////////////////////////////////////
////                        mcp2515a.c     NODE A                    ////
//// CAN Library routines for Microchip's MCP2510 (and compatable)   ////
//// CAN IO expanders.                                               ////
////                                                                 ////
//// This library provides the following functions:                  ////
////  (for more information on these functions see the comment       ////
////   header above each function)                                   ////
////                                                                 ////
////    can_init - Configures the MCP2510 CAN peripheral             ////
////                                                                 ////
////    can_set_baud - Sets the baud rate control registers          ////
////                                                                 ////
////    can_set_mode - Sets the CAN module into a specific mode      ////
////                                                                 ////
////    can_set_id - Sets the standard and extended ID               ////
////                                                                 ////
////    can_get_id - Gets the standard and extended ID               ////
////                                                                 ////
////    can_putd - Sends a message/request with specified ID         ////
////                                                                 ////
////    can_getd - Returns specifid message/request and ID           ////
////                                                                 ////
////    can_kbhit - Returns true if there is data in one of the      ////
////                receive buffers                                  ////
////                                                                 ////
////    can_tbe - Returns true if the transmit buffer is ready to    ////
////              send more data                                     ////
////                                                                 ////
////    can_abort - Aborts all pending transmissions                 ////
////                                                                 ////
//// You will need a CAN transeiver to connect CANRX and CANTX       ////
//// pins to CANH and CANL bus lines.                                ////
////                                                                 ////
//// CCS provides an example, ex_can_ccs_b.c, which shows how to use ////
//// this library with CCS's CAN Prototype board.                    ////
////                                                                 ////
/////////////////////////////////////////////////////////////////////////
////                                                                 ////
//// Version History                                                 ////
////                                                                 ////
////  Jul 27 04 - can_init() uses CAN_USE_EXTENDED_ID instead of     ////
////              setting all RX filters to extended.                ////
////                                                                 ////
////  Apr 20 04 - Fixed a compling problem.                          ////
////                                                                 ////
////  Feb 24 04 - can_get_id() fixed for EID<18:20>.                 ////
////                                                                 ////
/////////////////////////////////////////////////////////////////////////
////        (C) Copyright 1996,2003 Custom Computer Services         ////
//// This source code may only be used by licensed users of the CCS  ////
//// C compiler.  This source code may only be distributed to other  ////
//// licensed users of the CCS C compiler.  No other use,            ////
//// reproduction or distribution is permitted without written       ////
//// permission.  Derivative programs created using this software    ////
//// in object code form are not restricted in any way.              ////
/////////////////////////////////////////////////////////////////////////

#include <can-mcp2510.h>

//IO pins connected to MCP2510
#ifndef EXT_CAN_CS
   #define EXT_CAN_CS   PIN_C2
   #define EXT_CAN_SI   PIN_C5
   #define EXT_CAN_SO   PIN_C4
   #define EXT_CAN_SCK  PIN_C3
   #define EXT_CAN_RESET   PIN_C0 //CCS library does not use this pin by default


//   #define EXT_CAN_TX0RTS  PIN_C4 //CCS library does not use this pin by default
//   #define EXT_CAN_TX1RTS  PIN_B4 //CCS library does not use this pin by default
//   #define EXT_CAN_TX2RTS  PIN_C2 //CCS library does not use this pin by default
#endif

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

////////////////////////////////////////////////////////////////////////
//
// can_init()
//
// Initializes MCP2510 CAN peripheral.  Sets the RX filter and masks so the
// CAN peripheral will receive all incoming IDs.  Configures both RX buffers
// to only accept valid valid messages (as opposed to all messages, or all
// extended message, or all standard messages).
//
// The constants (CAN_USE_RX_DOUBLE_BUFFER, CAN_ENABLE_DRIVE_HIGH,
// CAN_ENABLE_CAN_CAPTURE, etc) are given a default define in the can-mcp2510.h file.
// These default values can be overwritten in the main code, but most
// applications will be fine with these defaults.
//
//////////////////////////////////////////////////////////////////////////////
void can_init(void) {
   struct struct_RXB0CTRL b_rxb0ctrl;

   mcp2510_init();

   can_set_mode(CAN_OP_CONFIG);   //must be in config mode before params can be set
   can_set_baud();
   
   b_rxb0ctrl=0;
   b_rxb0ctrl.rxm=CAN_RX_VALID;
   b_rxb0ctrl.bukt=CAN_USE_RX_DOUBLE_BUFFER;
   
   mcp2510_write(RXB0CTRL, (int)b_rxb0ctrl);
   mcp2510_write(RXB1CTRL, (int)b_rxb0ctrl);
     
   //if you want to configure the TXnRTS pins, do it here.  default is off

   can_set_id(RX0MASK, CAN_MASK_ACCEPT_ALL, CAN_USE_EXTENDED_ID);  //set mask 0 (RX BUFFER 0)
   can_set_id(RX0FILTER0, 0, CAN_USE_EXTENDED_ID);  //set filter 0 of mask 0 (RX BUFFER 0)
   can_set_id(RX0FILTER1, 0, CAN_USE_EXTENDED_ID);  //set filter 1 of mask 0 (RX BUFFER 0)

   can_set_id(RX1MASK, CAN_MASK_ACCEPT_ALL, CAN_USE_EXTENDED_ID);  //set mask 1 (RX BUFFER 1)
   can_set_id(RX1FILTER2, 0, CAN_USE_EXTENDED_ID);  //set filter 0 of mask 1 (RX BUFFER 1)
   can_set_id(RX1FILTER3, 0, CAN_USE_EXTENDED_ID);  //set filter 1 of mask 1 (RX BUFFER 1)
   can_set_id(RX1FILTER4, 0, CAN_USE_EXTENDED_ID);  //set filter 2 of mask 1 (RX BUFFER 1)
   can_set_id(RX1FILTER5, 0, CAN_USE_EXTENDED_ID);  //set filter 3 of mask 1 (RX BUFFER 1)

   can_set_mode(CAN_OP_NORMAL);
}

////////////////////////////////////////////////////////////////////////
//
// can_set_baud()
//
// Configures the baud rate control registers.  All the defines here
// are defaulted in the can-mcp2510.h file.  These defaults can, and
// probably should, be overwritten in the main code.
//
// Current defaults are set to work with CCS's CAN Prototype board and
// Microchip's MCP250xxx CAN Developers Kit if this PIC is running at 20Mhz.
//
////////////////////////////////////////////////////////////////////////
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;
   new_CNF1.sjw=CAN_BRG_SYNCH_JUMP_WIDTH;

   new_CNF2.prseg=CAN_BRG_PROPAGATION_TIME;
   new_CNF2.phseg1=CAN_BRG_PHASE_SEGMENT_1;
   new_CNF2.sam=CAN_BRG_SAM;
   new_CNF2.btlmode=CAN_BRG_SEG_2_PHASE_TS;

   new_CNF3.phseg2=CAN_BRG_PHASE_SEGMENT_2;
   new_CNF3.wakfil=CAN_BRG_WAKE_FILTER;

   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) {
   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()
//
// Configures the xxxxEIDL, xxxxEIDH, xxxxSIDL and xxxxSIDH registers to
// configure the defined buffer to use the specified ID
//
//   Paramaters:
//     addr - pointer to first byte of ID register, starting with xxxxEIDL.
//            For example, a pointer to RXM1EIDL
//     id - ID to set buffer to
//     ext - Set to TRUE if this buffer uses an extended ID, FALSE if not
//
////////////////////////////////////////////////////////////////////////
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()
//
// Returns the ID of the specified buffer.  (The opposite of can_set_id())
// This is used after receiving a message, to see which ID sent the message.
//
//   Paramaters:
//     addr - pointer to first byte of ID register, starting with xxxxEIDL.
//            For example, a pointer to RXM1EIDL
//     ext - Set to TRUE if this buffer uses an extended ID, FALSE if not
//
//   Returns:
//     The ID of the buffer
//
////////////////////////////////////////////////////////////////////////
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()
//
// Puts data on a transmit buffer, at which time the CAN peripheral will
// send when the CAN bus becomes available.
//
//    Paramaters:
//       id - ID to transmit data as
//       data - pointer to data to send
//       len - length of data to send
//       priority - priority of message.  The higher the number, the
//                  sooner the CAN peripheral will send the message.
//                  Numbers 0 through 3 are valid.
//       ext - TRUE to use an extended ID, FALSE if not
//       rtr - TRUE to set the RTR (request) bit in the ID, false if NOT
//
//    Returns:
//       If successful, it will return TRUE
//       If un-successful, will return FALSE
//
////////////////////////////////////////////////////////////////////////
int1 can_putd(int32 id, int * data, int len, int priority, int1 ext, int1 rtr)
{
   int i;
   int port;

   int TXRXBaD0;
   int TXBaCTRL;
   int TXRXBaEIDL;
   int TXBaDLC;

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

   //output_high( PIN_E2); // tx indicator

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

    // find emtpy transmitter
    //map access bank addresses to empty transmitter
   if (!b_TXB0CTRL.txreq) {
      TXRXBaD0=TXB0D0;
      TXBaCTRL=TXB0CTRL;
      TXRXBaEIDL=TXB0EIDL;
      TXBaDLC=TXB0DLC;
      port=0;
   }
   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);
   }

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

   //set tx mask
   can_set_id(TXRXBaEIDL, id, ext);

   //set tx data count
   b_TXBaDLC=len;
   b_TXBaDLC.rtr=rtr;
   mcp2510_write(TXBaDLC, (int)b_TXBaDLC);

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

   //enable transmission
   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
   //output_low( PIN_E2); //tx led status
   return(1);
}

////////////////////////////////////////////////////////////////////////
//
// can_getd()
//
// Gets data from a receive buffer, if the data exists
//
//    Returns:
//      id - ID who sent message
//      data - pointer to array of data
//      len - length of received data
//      stat - structure holding some information (such as which buffer
//             recieved it, ext or standard, etc)
//
//    Returns:
//      Function call returns a TRUE if there was data in a RX buffer, FALSE
//      if there was none.
//
////////////////////////////////////////////////////////////////////////
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);

   b_RXB0CTRL=mcp2510_read(RXB0CTRL);
   b_RXB1CTRL=mcp2510_read(RXB1CTRL);
   b_EFLG=mcp2510_read(EFLG);

    if (b_CANINTF.rx0if) {
        stat.buffer=0;

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

        if (b_RXB0CTRL.bukt) {
         stat.filthit=b_RXB0CTRL.filhit0;
        }

        RXBaDLC=RXB0DLC;
        TXRXBaSIDL=RXB0SIDL;
        RXBaD0=RXB0D0;
    }
    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);
    }

   //get count
    b_RXBaDLC=mcp2510_read(RXBaDLC);
    len = b_RXBaDLC.dlc;
    stat.rtr=b_RXBaDLC.rtr;

   //was it extended or standard?
    b_TXRXBaSIDL=mcp2510_read(TXRXBaSIDL);
    stat.ext=b_TXRXBaSIDL.ext;
    id=can_get_id(TXRXBaSIDL + 2,stat.ext);

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

    stat.inv=b_CANINTF.merrf;
    if (b_CANINTF.merrf) {
      b_CANINTF.merrf=0;
    }

    if (stat.buffer) {
      b_CANINTF.rx1if=0;
    }
    else {
      b_CANINTF.rx0if=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()
//
// Returns TRUE if there is data in the receive buffers
//
//////////////////////////////////////////////////////////////////////////////
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()
//
// Returns TRUE if the transmit buffers are empty and ready to transmit data
//
//////////////////////////////////////////////////////////////////////////////
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()
//
// Aborts all pending tranmissions.
//
//////////////////////////////////////////////////////////////////////////////
void can_abort(void) {
   struct struct_CANCTRL b_CANCTRL;

   b_CANCTRL=mcp2510_read(CANCTRL);
   b_CANCTRL.abat=1;
   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);
}

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);
}


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);
}

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);
}

void mcp2510_init(void) {
   output_high(EXT_CAN_CS);
   output_low(EXT_CAN_SCK);

   #ifdef EXT_CAN_TX0RTS
    output_high(EXT_CAN_TX0RTS);
   #endif
   #ifdef EXT_CAN_TX1RTS
    output_high(EXT_CAN_TX1RTS);
   #endif
   #ifdef EXT_CAN_TX2RTS
    output_high(EXT_CAN_TX2RTS);
   #endif

  #ifdef EXT_CAN_TX0RTS
   output_high(EXT_CAN_RESET);
   output_low(EXT_CAN_RESET);
   output_high(EXT_CAN_RESET);
   delay_ms(5);
  #endif

   mcp2510_command(0xC0);   //reset
   delay_ms(5);
}


Hocam Burada can_set_baud() diye bir fonksiyon var ve can_init() fonksiyonu içerisinde bu fonksiyon çağrılıyor. Şimdi STM32'yi 100Kbit için ayarladık. MCP2515'i de 100Kbit için ayarlamam gerekiyor.
Daha önce bu enteğre ile çalışan arkadaşların yardımına ihtiyacım var. Yukarıdaki kütüphanede, can_init() fonksiyonunda göze çarpan bir hata varmı? Sorun baudrate ile ilgilimidir? MCP2515'de Baudrate hesabı nasıl yapılıyor? Yardım ederseniz sevinirim.


CLR

@Mucit23

Aslında programından can tx pininden data çıktığını anlamıştım ama yazmak istemedim çünkü şema koymadığın için belki remap olayında hata yapıyor olabilirdin veya başka bir ölçüm veya donanım hatan olabilirdi diye ilk açıklamayı yazdım.

Şimdi bilmen gereken şu var.

Can busta sadece bir tane tranmitter veya transceiver varsa yani karşıda alıcı can device yoksa, transmitter aynı datayı sürekli gönderir çünkü karşıdan ack bekler. Senin durumunda da o var, ilk başta stm32 ardışık datayı gönderir çünkü alıcı yok sonra alıcı devreye girince sadece gönderim zamanlarında data gönderir veya alır ama bitrate'leri uymuyorsa error counter saymaya başlar.

mcp2515'li devre eğer 100kbit haricinde haberleşiyorsa stm32 ve mcp2515 içindeki error counter sürekli artar, belirli sayıları aştığında bus light, bus heavy ve bus off durumları oluşur bu nedenle bitrate ayarı kritiktir.

Ben CCS C'den anlamam verdiğin source code içerinde tanımlı olması gereken tanımlamaları vereyim

Mc2515  : 16mhz'de çalışıyorsa!!!!,  100kbit için aşağıdaki değerleri kullanabilirsin

CAN_BRG_PROPAGATION_TIME =1tq
CAN_BRG_PHASE_SEGMENT_1 = 8tq
CAN_BRG_SEG_2_PHASE_TS = 6tq
CAN_BRG_SYNCH_JUMP_WIDTH = 1tq
Knowledge and Experience are Power

Mucit23

#303
Hocam yok haberleşmeyi sağlayamadım. Biraz Canımı sıkacak bu konu.  Değerleri o şekilde yapınca yine STM veri göndermeyi kesiyor. Ne yapacam bilmiyorum.

Şuandaki hedefim tek yönlü haberleşmeyi sağlamak. Yani şimdilik STM'den sabit sizin verdiğiniz 100Kbit init kodlarıyla sürekli Veri basıyorum. Tek Hedefim karşı tarafta Mesaj geldi kesmesini oluşturmak. Acaba tam tersinimi yapayım. MCP'den sabit data yollayıp STM'de kesme oluşturmaya çalışayım. Emin değilim.

Hocam CAN Baudrate nasıl hesaplanır derken microchip'in bir toolunu buldum.
http://www.intrepidcs.com/support/mbtime.htm
MCP2515 için doğrudan Register değerlerini açıklamalı olarak veriyor.

Bu programla aldığım değerleri birde deniyeyim. Sonucu Tekrardan yazarım.

İlginiz için teşekkürler.



mesaj birleştirme:: 14 Ağustos 2014, 01:05:10

Evet Denedim

Bahsetiğim o Programın 16Mhz osilatör ve 100KBit için verdiği çıktı şöyle.


Bu program sayesinde Bit Timing olayını biraz anladım. Ama PHASE_SEGMENT gibi değerleri teker teker girmemek için CNF1, CNF2 ve CNF3 registerlerine doğrudan programın verdiği Hex değerleri yazdım.

   mcp2510_write(CNF1, 0x03);
   mcp2510_write(CNF2, 0xBA);
   mcp2510_write(CNF3, 0x07);


Sonuç olarak scop ile STM32'nin CAN_TX pinine Baktığımda bir önceki mesajımdaki 2. Resmi görüyorum. Yani eğer sizin yorumladığınız gibiyse hala baudrateler uyuşmayıp error counter artıyor.

Hocam Şemada bir problem olacağını sanmıyorum. STM32 tarafında deney kitinde çalışıyorum. STM32'nin PB8 ve PB9 pinleri doğrudan SN65HVD230'a bağlı.

MCP2515 tarafında ise seed studionun Arduino için üretmiş olduğu can bus shield'ini kullanıyorum
http://www.seeedstudio.com/wiki/CAN-BUS_Shield
MCP2515'in haberleşme bacaklarını yine başka bir deney kitinde bulunan Pic18F886'ya bağladım. Bunun yazılımıyla oynuyorum.

Donanım kabaca böyle. Bağlantılarıda 3-4 defa kontrol ettim. STM32'den gelen veri MCP2515'in CAN_RX pinine ulaşıyor. Bunu scop ile görebiliyorum.

Daha önce Can-Bus ile uğraşmış arkadaşların problem hakkında fikir ve önerilerini almak isterim.
@CLR Hocam ne yapmamı tavsiye edersiniz?

Mucit23

Konu güncel arkadaşlar. Konuyla ilgili çözüm önerilerisi bekliyorum.

CLR

#305
@Mucit23
Aslında bu sorun komplex bir sorun değil, çözmeni beklerdim ama mesajlarından telaşlanmış gibi görünüyorsun. Çözüm yollarını söylüyeyim, sen hangisini beğenirsen uygula.

1) Logic analyzer'in yoksa scop ile mcp2515'in çıkışındaki sinyalin bit genişliğine bakıp bitrate'ni hesaplayacaksın veya varsa zaten o hesaplıyor.
2) Ayrıca ikinci bir stm32 module varsa onuda kullanabilirsin. Aynı değerleri atarsan aynı bitrate'e sahip olur.
3) Aynı RS485'teki gibi karşıdaki transceiver'in RX ve TX pinlerini birbirine bağlasan stm32 kendine yayın yapar.
4) Veya daha kolayı stm32 tek başına şöyle deneye bilirsin loopback modunda çalıştıracaksın bu durumda kendi kendine yayın yapacak. Hem data almasından hemde göndermesinden emin olursun. Normal modda değil loopback modda çalıştır. Loopback modunda STM'nin tx pini içeriden rx pinine bağlanır. 
Knowledge and Experience are Power

Mucit23

Anladım hocam. Bu hafta sonuna kadar ilk haberlesmemi yapsam benim için çok iyi olacak. Stm32 ve Mcp2515de bit timing ayarlarını öğrendim sayılır. Birde 125kbit de deneme yapmayı düşünüyorum.

Ben biraz stm32 üzerinde çalışacağım.  Loopback modunda birkac test yapayım.  Lojik analyserimda var. Bu akşam bu işi çözmeyi hedefliyorum. Sanırım stm32 loopback modunda kendi gönderdiğim mesajla kendi kendine mesaj geldi kesmesi oluşturur herhalde. Bunu stm32 ile yapabilirsem aynısını mcp2515 ile yapacam.  Sonrasında zaten baudrateler uyuyorsa haberleşmeyi sağlarım.

mesaj birleştirme:: 14 Ağustos 2014, 13:04:09

Anladım hocam. Bu hafta sonuna kadar ilk haberlesmemi yapsam benim için çok iyi olacak. Stm32 ve Mcp2515de bit timing ayarlarını öğrendim sayılır. Birde 125kbit de deneme yapmayı düşünüyorum.

Ben biraz stm32 üzerinde çalışacağım.  Loopback modunda birkac test yapayım.  Lojik analyserimda var. Bu akşam bu işi çözmeyi hedefliyorum. Sanırım stm32 loopback modunda kendi gönderdiğim mesajla kendi kendine mesaj geldi kesmesi oluşturur herhalde. Bunu stm32 ile yapabilirsem aynısını mcp2515 ile yapacam.  Sonrasında zaten baudrateler uyuyorsa haberleşmeyi sağlarım.

Mucit23

Hocam iki gündür STM32ile uğraşıyorum. LoopBack Modunda denemeler yapıyorum.

Şuanda interrupt olmadan LoopBack modunda Mesaj gönderip alabiliyorum. Ama interrupt'u aktif ettiğim zaman (  CAN_ITConfig(CAN1,CAN_IT_FMP0, ENABLE);) STM32 Mesaj gönderme aşamasında takılıp kalıyor. (CAN_Transmit(CAN1,&TxMessage))

Kesme vektörünü Nvic Ayarlarını felan defalarca kontrol ettim. Bir türlü anlam veremedim. Sizin başınıza böyle birşey geldimi?

CLR

Açıkçası loopback modunda interruptı açıp açmadığımı hatırlamıyorum,

2007'de ilk kez can bus ile uğraşırken loopback kullandım. Sonra bir daha gerek kalmadı.

Ama mantıken loopback modunda da interrupt kullanabiliyor olman lazım.
Knowledge and Experience are Power

Mucit23

#309
Hocam deney kartımın örnek programı var. Onda çalışıyor aslında. Fakat Kodlar ST'nin Eski Firmwaresine göre yazılmış. Bendeki daha güncel.

Aradaki tek fark Firmware güncellemesinden kaynaklanan değişiklikler....

Örnek programdaki uygulamayı olduğu gibi kendi programıma import etmeye çalışacağım. Birde böyle deniyeyim. Kesinlikle interrupt oluşması lazım.

mesaj birleştirme:: 16 Ağustos 2014, 13:04:40

Ben bu işi çözeceğim ama çözene kadar ağzımdan emdiğim süt burnumdan gelecek.  >:(

Hocam yok benim bu mcu'da birşeyler var benimle oyun oynuyor resmen. Interruptları aktif ettiğimde Data gönderiken program donuyor....

LoopBack Modunda interrupta çalışıyor çünkü deney kitimin örnek programında interupt kullanılıyor.

Aynı programı benim kendi programıma import ettiğimde çalışmıyor. Şu zincirleri bir kırabilsem herşey yerli yerine oturacak.  >:(

CLR

Yedeklerime baktım, evet loopback modunda Rx ve Tx interrupt birlikte kullanmışım, aşağıdaki gibi ama ben ST library'yi kullanmadım o zaman kendim bir library hazırlamıştım. Gerçi halada mix olarak kullanıyorum.
Ayrıca ben hem loopback hemde silent modunu kullanmışım yani tx pininden sinyal çıkışı yok, herşey içeride gerçekleşiyor

void
Can_Testmodu(void){
    can_btr.bits.SILM=1;            // silent modu
    can_btr.bits.LBKM=1;            // loopback modu
}

// tx interrup
void 
USB_HP_CAN_TX_IRQHandler(void) {
    if(can_tsr.bits.RQCP0){
        can_tsr.bits.RQCP0=1;       // 1 yapılarak clear edilir
        can_ier.bits.TMEIE=0;        // interrupt clear
        Can_Flags.TxReady=1;
    }
}

// rx interrupt, USB_LP_CAN_RX0_IRQHandler
void 
USB_LP_CAN_RX0_IRQHandler(void) {
    if(can_rf0r.bits.FMP0) {         // data gelmiş  mi?
        Can_Msg_Rd(&Can_Rx_Msg);
        Can_Flags.RxReady=1;
    }
}
Knowledge and Experience are Power

Mucit23

Hocam bilmiyorum. ST'nin kütüphanesindede problem olabilir.
Aşağıdaki kod çalışınca Program kafayı yiyor.

  CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);

ST foruma mesaj attım. Bakalım oradan ne cevap gelecek. Birde STD lib kullanılmadan keilin kendi CANBUS kodları var. Onlarıda denemeyi düşünüyorum.

Biraz ara vereyim. Sakin kafayla tekrardan bakacağım.

CLR

STM32 can modulü ilgili olarak ile hemde kendi kütüphanemi, hem keilinkini hemde ST libi kullandım, hepsi sorunsuz çalışıyor. Şimdiki can projelerimi ST V3.5 ile yapıyorum yani problemlem yok, kütüphane otuşmuş ve kütüphanede hata olacağını sanmıyorum.
Knowledge and Experience are Power

Mucit23

#313
Hocam anlamadığım şey neden kesmeyi açınca program çalışmaz hale geliyor.  Ne oluyor anlamıyorum bir türlü. 

Kesme için Nvic ayarları gibi birçok ayarı yapıyorum.

Siz olsaydınız boyle bir sorunu çözmek için ne yapardınız? Elinizde StdLib kullanilarak yapılmış örnek uygulama varmı?

CLR

Can ile 10 kadar proje yaptım , bir kısmı çalıştığım firmalar için yaptığım projeler, geri kalan kısmı freelance olarak sözleşmeli proje yaptığım firmaların ticari projeleri.

Ama sana şöyle yardımcı olabilirim, Projende, varsa şirketine veya sana özel kısımlarını silip içinde sadece CAN projesi kalacak ve compile edilecek şekilde projeni bir yere upload edersen yardımcı olmaya çalışırım. Şematiğinde sadece can pinlerinin ve driver'ının olduğu yapıyı görsel olarak eklemen lazım.

OK ise Linki ister buraya yükle istersen bana özel mesaj atabilirsin.
Knowledge and Experience are Power