PP2CAN Visual Studio API

(CZ  verze 0.1 )

   

    Celé API je zastřešeno třídou PP_MCP2510 název je odvozen od parallel port - MCP2510. Tato třída pak obsahuje metody pro komunikaci se zařízením PP2CAN. Rozhraní je schodné pro všechny varianty, tzn. high speed, low speed i single wire. K vytvoření objektu PP2CAN slouží konstruktor:

 

PP_MCP2510(WORD address, CAN_SPEED speed, void (*error_function)(int err_code, const char * error_string), void (*msg_receiver)(MCP2510Msg *msg),int HW_Version, bool OneShotMode /*= false*/, bool PassiveMode /*= false*/ );

 

parametry:
   

address   adresa paralelního portu, v praxi se používají hodnoty: 0x378, 0x278,  0x3BC
     
speed   nastavení komunikační rychlosti pro CAN, enum CAN_SPEED definován v pp2can.h, má tento tvar
     
   

enum CAN_SPEED {
      SPEED_10k = 0,

      SPEED_20k,
      SPEED_33_3k,
      SPEED_50k,
      SPEED_62_5k,
      SPEED_83_3k,
      SPEED_100k,
      SPEED_125k,
      SPEED_250k,
      SPEED_500k,
      SPEED_1M,
      SPEED_USR,
};

     
*error_function   ukazatel na funkci pro zpracování chybových hlášení, možno použít NULL, není však doporučeno
     
*msg_receiver   ukazatel na funkci pro zpracování přijatých zpráv, možno použít NULL, avšak doporučuje se vytvořit pro zpracování samostatné vlákno a provést vyčítání pomocí metod GET_LENGTH  a GET.
     
HW_Version   typ použitého HW, v pp2can.h jsou uvedeny tyto definice:

#define HW_HIGH_SPEED_0  0
#define HW_HIGH_SPEED_1  1
#define HW_LOW_SPEED_0   2
#define HW_SINGLE_WIRE_0 3

     
OneShotMode   Je-li true, není při selhání odeslání zprávy prováděn pokus u znovuodeslání
     
PassiveMode   Zařízení pouze přijímá zprávy, odeslání není možno
     

  

    Po vytvoření objektu je zařízení nainicializováno, je provedeno nastavení komunikační rychlosti a filtry zpráv jsou nastaveny na příjem všech standardních i rozšířených zpráv. Zařízení přijímá zprávy. Doporučuje se nepoužívat volání funkce msg_receiver a provádět vyčtení zpráv prostřednictvím volání funkcí  GET_LENGTH  (zjištění počtu zpráv v přijímacím bufferu) a GET(vyčte zprávu z přijímacím bufferu).

 

PP_MCP2510 * port = NULL;

..

..

// vytvoreni portu
port = new PP_MCP2510(0x378, SPEED_100k, WriteErrorText, NULL, HW_HIGH_SPEED_1 , false, false);
// povoluji cteni TEC a REC

port->READ_RX_ERROR(true);
port->READ_TX_ERROR(true);

..

..

// zruseni portu

delete port;

 

Máme aplikaci v MFC a ta obsahuje prvek CListBox o výšce 5 řádků. Dále bude-li pm_list globální ukazatel na tento prvek, můžeme chybová a další hlášení zapisovat takto: 

 

static void MyDialog::WriteErrorText(int error_code,const char *text)
{
    if(pm_list==NULL) return;
    pm_list->AddString((LPCTSTR)text);
    int index = pm_list->GetCount();
    if(index>5) pm_list->SetTopIndex(index-5);
};

 

Jsou definovány tyto chybové kódy:

 

Error Code  Text
0  ERROR: Device PP2CAN not connect
1  WARNING: MCP2510 - Receive Buffer 1 Overflow Flag
2  WARNING: MCP2510 - Receive Buffer 0 Overflow Flag
3  WARNING: MCP2510 - Bus-Off Error Flag
4  WARNING: MCP2510 - Transmit Error-Passive Flag
5  WARNING: MCP2510 - Receive Error-Passive Flag
6  WARNING: MCP2510 - Transmit Error Warning Flag
7  WARNING: MCP2510 - Receive Error Warning Flag
8  WARNING: MCP2510 - RESET
9  ERROR: MCP2510 - Mode


 


    Je-li třeba provést změnu komunikační rychlosti nebo filtrů zpráv, je třeba uvést zařízení do konfiguračního režimu voláním metody:

 

void PP_MCP2510::SET_CONFIG_MODE(void);

     

    Po provedení změn je pak třeba provést nastavení pracovního režimu voláním:

 

void PP_MCP2510::SET_NORMAL_MODE(void);

 

    Tyto metody je pak třeba uzavřít mezi voláním:

 

void PP_MCP2510::EnterCriticalSectionSPI(void);

    a

void PP_MCP2510::LeaveCriticalSectionSPI(void);

 

    tzn. například:

 

    port->EnterCriticalSectionSPI();

    port->SET_CONFIG_MODE();

    port->LeaveCriticalSectionSPI();

   

    port->SET_SPEED(SPEED_100k);

   

    port->EnterCriticalSectionSPI();

    port->SET_NORMAL_MODE();

    port->LeaveCriticalSectionSPI();

 

    Pro změnu komunikační rychlosti slouží tyto metody:

 

void PP_MCP2510::SET_SPEED(CAN_SPEED speed);
void PP_MCP2510::SET_SPEED(unsigned char tBRP, unsigned char tSJW, unsigned char tPRSEG, unsigned char tPHSEG1, unsigned char tPHSEG2, bool tSAM);
void PP_MCP2510::SET_SPEED(unsigned char tCNF1, unsigned char tCNF2, unsigned char tCNF3);
void PP_MCP2510::SET_SPEED_PARAM(unsigned char tBRP, unsigned char tSJW, unsigned char tPRSEG, unsigned char tPHSEG1, unsigned char tPHSEG2, bool tSAM);

void PP_MCP2510::RESTART(CAN_SPEED speed, bool suspend_comunication)
 

    První metoda má jako parametr enum CAN_SPEED, v případě že je použita hodnota SPEED_USR je nutno provést nejprve volání funkce SET_SPEED_PARAM. Druhá a funkce provede je vlastně sloučení volání SET_SPEED_PARAM a první funkce s parametrem SPEED_USR. Třetí je pak obdobou druhé, parametry jsou však uvedeny v jiném formátu, podrobnosti lze najít v dokumentaci k MCP2510/2515.

 

    Upřednostňujte však metodu RESTART. Parametr suspend_comunication na true:

 

port->RESTART(SPEED_250k, true);

    nebo

port->RESTART(SPEED_250k);

    nebo

port->SET_SPEED_PARAM(BRP, SJW, PRSEG, PHSEG1, PHSEG2, SAM);
port->RESTART(SPEED_USR);

 

    U varianty PP2CAN SiWi (Single Wire) je možno používat i metody:

 

bool PP_MCP2510::SiWi_ENABLE_PIN(bool state);
bool PP_MCP2510::SiWi_GET_ENABLE_PIN(bool &state);

 

    Tyto metody jsou určeny k ovládání/čtení stavu signálu ENABLE pro nastavení normal/high speed módu. U variant zařízení high a low speed nemají tyto metody žádnou odezvu.


    K odeslání zprávy je určena metoda:

 

int PP_MCP2510::SEND(MCP2510Msg &data);

 

    Funkce zároveň vrací aktuální velikost bufferu zpráv pro odeslání. Jako parametr má funkce referenci na strukturu MCP2510Msg. Tato struktura je obrazem bufferu řadiče MCP2510/2515, je definována v pp2can.h a má tento tvar:

 

 

typedef union {
    unsigned char bytes[13];
    struct {
        unsigned char ID[4];
        unsigned char DLC;
        unsigned char data[8];
    } item;
} MCP2510Msg;

 

    Metoda void PP_MCP2510::SEND_LENGTH(void) vrací délku fronty zpráv čekajících na odeslání.

 

    Pro usnadnění vyplnění dat v této struktuře a zároveň pro zpětné dekódování dat z této struktury při příjmu jsou určeny tyto metody:

 

bool PP_MCP2510::MSG_get_ID(unsigned char *data, unsigned __int16 &Id1, unsigned __int32 &Id2);
bool PP_MCP2510::MSG_get_ID(unsigned char *data, unsigned __int16 *Id1, unsigned __int32 *Id2);
void PP_MCP2510::MSG_set_ID(unsigned char *data, unsigned __int16 Id1, unsigned __int32 Id2);
void PP_MCP2510::MSG_set_ID(unsigned char *data, unsigned __int16 Id1);
bool PP_MCP2510::MSG_set_DLC(unsigned char *data, bool RTR, unsigned char length);
void PP_MCP2510::MSG_get_DLC(unsigned char *data, bool &RTR, unsigned char &length);

 

    MSG_get_ID je určena k získání identifikátoru ve formátu standardní a rozšířené části. Pokud funkce vrací true, jedná se o zprávu s rozšířeným identifikátorem, v opačném případě pak jde o funkci se standardním identifikátorem. Varianta MSG_set_ID s parametry Id1 a Id2 nastavuje hodnotu rozšířeného (29-bitového) identifkátoru, varianta pouze s Id1 pak standardní (11-bitový) identifikátor. Délku zprávy a příznak rtr čteme/nastavujeme pomocí metod MSG_get_DLC/MSG_set_DLC.

   

    Fragment kódu s odesláním zprávy se standardním identifikátorem 1537, délkou dat (DLC) 4, data nastavena na hodnoty 1,2,3 a 4:

 

MCP2510Msg msg;

// nastaveni standardniho 11-bitoveho identifikatoru
port->MSG_set_ID(&msg.bytes[0], 1537);

// nastaveni rtr na false, delka zpravy 4
port->MSG_set_DLC(&msg.bytes[0], false, 4);

// vyplneni dat
msg.item.data[0] = 1;
msg.item.data[1] = 2;
msg.item.data[2] = 3;
msg.item.data[3] = 4;

// odeslani (ulozeni do bufferu k odeslani)
port->SEND(msg);

 

    Odeslání zprávy žádosti o data (RTR), rozšířený 29-bitový identifikátor (St: 1427, Ext: 145548):
 

MCP2510Msg msg;

// nastaveni rozsireneho 29-bitoveho identifikatoru
port->MSG_set_ID(&msg.bytes[0], 1427,145548);

// nastaveni rtr na true, delka zpravy 0
port->MSG_set_DLC(&msg.bytes[0], true, 0);

// odeslani (ulozeni do bufferu k odeslani)
port->SEND(msg);

 

    Odeslání zprávy se standardním 11-bitovým identifikátorem 513, v datové části uložena hodnota 123567 typu signed __int32 od DB1, v DB0 hodnota 120:
 

signed __int value = 123567;

signed __int *p;

MCP2510Msg msg;

// nastaveni standardního 11-bitoveho identifikatoru
port->MSG_set_ID(&msg.bytes[0], 513);

// nastaveni rtr na false, delka zpravy 5 (DB0 + sizeof(signed __int32)=4)
port->MSG_set_DLC(&msg.bytes[0], false, 5);

// nastavim DB0 na 120

msg.item.data[0] = 120;

// vlozim hodnotu typu signed __int32

p=(signed __int *)&msg.item.data[1];

*p = value;

// odeslani (ulozeni do bufferu k odeslani)
port->SEND(msg);

 

    Následující fragmet kódu demonstruje postup při čtení přijaté zprávy, obsah zprávy pak vypisuje na standardní výstup:

 

MCP2510Msg *data =NULL;
unsigned __int16 Id1;
unsigned __int32 Id2;
bool rtr;
unsigned char length;

..

..

// je-li v bufferu nejaka zprava

while(port->GET_LENGTH()>0)

{

   

    // a byla-li vyctena, provedu dekodovani

    if(port->GET(&data))

    {

        // rozsireny identifikator

        if(port->MSG_get_ID(&data->bytes[0],Id1,Id2))
            cout << "Ext " << (unsigned int)Id1 << '\t' << (unsigned int)Id2 << endl;

        // standardni identifikator
        else

            cout << "St " << (unsigned int)Id1 << '\t' << "0" << endl;

 

        // zjistim delku zpravy a priznak rtr (remote transfer request)
        port->MSG_get_DLC(&data->bytes[0],rtr,length);

 

        // datova zprava
        if(!rtr)
        {
            cout << (unsigned int)length << endl;

            // vypisu data
            for(int i=0;i<8;i++)
            {
                 cout << (unsigned int)data->item.data[i] << '\t';
            }

            cout << endl;
        }

        // rtr - zadost o data
        else
        {
            cout << "rtr-" << (unsigned int)length << endl;
        }

        // musim smazat - volani funkce API, ne delete !!!

        port->DELETE_MSG(data);

    }

}

..

..


    Ke čtení TEC (Transmit Error Counter) a REC (Receive Error Counter) jsou určeny metody:

 

unsigned char PP_MCP2510::READ_TX_ERROR(void);
void PP_MCP2510::READ_TX_ERROR(bool enable);

unsigned char PP_MCP2510::READ_RX_ERROR(void);
void PP_MCP2510::READ_RX_ERROR(bool enable);

 

   Metody READ_TX_ERROR(bool enable) a void READ_RX_ERROR(bool enable) povolují nebo zakazují čtení registrů TEC a REC. V případě, že je povoleno jejich čtení, je možno získat jejich hodnotu voláním unsigned char READ_TX_ERROR(void) nebo unsigned char READ_RX_ERROR(void).

 

    Dále je možno zjistit počet restartů CAN řadiče v důsledku nastavení příznaku Bus-off apod. voláním metody:

 

unsigned int PP_MCP2510::GET_RST(void);

 


    V následujícím textu budou uvedeny metody, které je možno použít pouze mezi voláním EnterCriticalSectionSPI a LeaveCriticalSectionSPI. Jejich použití je však možné pouze v ojedinělých případech a jejich volání se v praxi nepoužívá ani nedoporučuje. Nicméně jsou uživateli přístupné a popis je uveden pouze pro úplnost.

 

unsigned char PP_MCP2510::STATUS(void);

void PP_MCP2510::SEND_MESSAGE(unsigned char TX_buffer, unsigned char *data);
void PP_MCP2510::GET_MESSAGE(unsigned char RX_buffer, unsigned char *data);
unsigned char PP_MCP2510::GET_TX_ERROR(void);

unsigned char PP_MCP2510::GET_RX_ERROR(void);

 

STATUS - vyčtení stavu řadiče (ve kterých bufferech je přijata zpráva a které jsou prázdné a je je možno použít k odeslání zprávy), popis v dokumentaci k MCP2510/2515.

SEND_MESSAGE - vloží zprávu k odeslání do řadiče MCP2510/2515 mimo vlákno pro komunikaci s HW PP2CAN. Parametr TX_buffer může mít hodnoty 0, 1 nebo 2. Použití společně s metodou STATUS.

GET_MESAGE - vyčtení přijaté zprávy, Parametr RX_buffer může mít hodnoty 0 nebo 1.  Použití společně s metodou STATUS.

GET_TX_ERROR - vyčtení TEC

GET_RX_ERROR - vyčtení REC