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->Leave CriticalSectionSPI();

port->SET_SPEED(SPEED_100k);

port->EnterCriticalSectionSPI();

port->SET_NORMAL_MODE();

port->Leave CriticalSectionSPI();

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