Created
August 4, 2011 13:53
-
-
Save fbstj/1125194 to your computer and use it in GitHub Desktop.
Module for communicating with C_CAN device on C8051F500 and other
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Module for communicating with C_CAN device on C8051F500 and F580. | |
*/ | |
#include "myPlatform.h" | |
#define __C_CAN_H 1 | |
# include "C_CAN.h" | |
#undef __C_CAN_H | |
// CAN0STAT masks | |
#define BOff 0x80 // Busoff Status | |
#define EWarn 0x40 // Warning Status | |
#define EPass 0x20 // Error Passive | |
#define RxOk 0x10 // Receive Message Successfully | |
#define TxOk 0x08 // Transmitted Message Successfully | |
#define LEC 0x07 // Last Error Code | |
// breaks between write-read pairs | |
#define CAN_nop() NOP();NOP();NOP();NOP() | |
#ifdef CAN0_PAGE | |
void CAN0_init(void) | |
{ | |
unsigned char SFRPAGE_save = SFRPAGE; | |
SFRPAGE = CAN0_PAGE; | |
CAN0CN = 1; // start Intialization mode | |
CAN_nop(); // wait | |
// initialize general CAN peripheral settings | |
CAN0CN |= 0x4E; // enable Error, Module and access to bit timing register | |
CAN_nop(); // wait | |
CAN0BT = 0x1402; // based on 24 Mhz CAN clock, set the CAN bit rate to 1 Mbps | |
CAN0CN |= 0x80; // enable test mode | |
CAN_nop(); // wait | |
CAN0TST = 0x04; // enalbe basic mode | |
// CAN initalization is complete | |
CAN0CN &= ~0x41; // return to Normal Mode and disable access to bit timing register | |
SFRPAGE = SFRPAGE_save; | |
} | |
void CAN0_send(CAN_message_t *m) | |
{ | |
unsigned char SFRPAGE_save = SFRPAGE; | |
unsigned short _A2, _A1; // temporary arbitration regs | |
SFRPAGE = CAN0_PAGE; | |
// message control register | |
CAN0IF1MC = 0x1480 | m->Length; | |
// command request and mask registers | |
CAN0IF1CR = 0x0000; | |
CAN0IF1CM = 0x00F3; | |
// arbitration registers | |
if (m->Extended) | |
{ // extended frame | |
m->ID &= 0x1FFFFFFF; | |
_A1 = m->ID; // lower half of id | |
_A2 = (m->ID >> 16); // upper half of id | |
_A2 |= 0x4000; // set extended flag | |
} | |
else | |
{ // standard frame | |
m->ID &= 0x000007FF; | |
_A1 = 0; | |
_A2 = (m->ID << 2); // id fits in bits 28-18 | |
} | |
if (m->Remote) | |
_A2 &= ~0x2000; // a remote frame | |
else | |
_A2 |= 0x2000; // not a remote frame | |
CAN0IF1A1 = _A1; | |
CAN0IF1A2 = _A2; | |
// data registers | |
CAN0IF1DA1H = m->Data[0]; CAN0IF1DA1L = m->Data[1]; | |
CAN0IF1DA2H = m->Data[2]; CAN0IF1DA2L = m->Data[3]; | |
CAN0IF1DB1H = m->Data[4]; CAN0IF1DB1L = m->Data[5]; | |
CAN0IF1DB2H = m->Data[6]; CAN0IF1DB2L = m->Data[7]; | |
// send message | |
CAN0IF1CM = 0x0087; // set Direction to Write TxRqst | |
CAN0IF1CR = 0x8000; // start command request | |
CAN_nop(); | |
while (CAN0IF1CRH & 0x80) {} // poll on Busy bit | |
SFRPAGE = SFRPAGE_save; | |
} | |
#ifdef CAN0_RAW | |
void CAN0_send_raw(long id, unsigned char *msg, unsigned char len) | |
{ | |
unsigned char SFRPAGE_save = SFRPAGE; | |
short idN = id & 0x07FF; | |
long idX = id & 0x1FFFFFFF; | |
unsigned short _A2, _A1; // temporary arbitration regs | |
SFRPAGE = CAN0_PAGE; | |
// message control register | |
CAN0IF1MC = 0x1480 | (len & 0x0F); | |
// command request and mask registers | |
CAN0IF1CR = 0x0000; | |
CAN0IF1CM = 0x00F3; | |
// arbitration registers | |
if (idN != id) | |
{ // extended frame | |
_A1 = idX; // lower half of id | |
_A2 = (idX >> 16); // upper half of id | |
_A2|= 0x4000; // set extended flag | |
} | |
else | |
{ // standard frame | |
_A1 = 0; | |
_A2 = (idN << 2); // id fits in bits 28-18 | |
} | |
_A2 |= 0x2000; // not a remote frame | |
CAN0IF1A1 = _A1; | |
CAN0IF1A2 = _A2; | |
// data registers | |
CAN0IF1DA1H = msg[0]; CAN0IF1DA1L = msg[1]; | |
CAN0IF1DA2H = msg[2]; CAN0IF1DA2L = msg[3]; | |
CAN0IF1DB1H = msg[4]; CAN0IF1DB1L = msg[5]; | |
CAN0IF1DB2H = msg[6]; CAN0IF1DB2L = msg[7]; | |
// send message | |
CAN0IF1CM = 0x0087; // set Direction to Write TxRqst | |
CAN0IF1CR = 0x8000; // start command request | |
CAN_nop(); | |
while (CAN0IF1CRH & 0x80) {} // poll on Busy bit | |
SFRPAGE = SFRPAGE_save; | |
} | |
#endif | |
void CAN0_ISR(void) interrupt INTERRUPT_CAN0 | |
{ // SFRPAGE is set to CAN0_Page automatically when ISR starts | |
unsigned char status; | |
long _arb; | |
CAN_message_t *m = &CAN0_receive; | |
//unsigned char Interrupt_ID; | |
status = CAN0STAT; // read status, which clears the Status Interrupt bit pending in CAN0IID | |
CAN0IF2CM = 0x007F; // read all of message object to IF2 Clear IntPnd and newData | |
CAN_nop(); | |
while (CAN0IF2CRH & 0x80) {} // poll on Busy bit | |
if (status & RxOk) | |
{ // receive completed successfully | |
_arb = ((long)CAN0IF2A2 << 16) | CAN0IF2A1; | |
m->Extended = (_arb >> 30) & 1; | |
m->Remote = (_arb >> 29) & 1; | |
if(m->Extended) | |
m->ID = (_arb & 0x1FFFFFFF); | |
else | |
m->ID = ((_arb >> 18) & 0x07FF); | |
// retreive the number of bytes in the packet (upto 8) | |
m->Length = (CAN0IF2MCL & 0x0F); | |
// copy message into CAN0rx; | |
m->Data[0] = CAN0IF2DA1L; m->Data[1] = CAN0IF2DA1H; | |
m->Data[2] = CAN0IF2DA2L; m->Data[3] = CAN0IF2DA2H; | |
m->Data[4] = CAN0IF2DB1L; m->Data[5] = CAN0IF2DB1H; | |
m->Data[6] = CAN0IF2DB2L; m->Data[7] = CAN0IF2DB2H; | |
CAN0_received = 1; // indicate recieved | |
} | |
// if an error occured, simply update the global variable and continue | |
if (status & LEC) | |
{ // the LEC bits identify the type of error, but those are grouped here | |
if ((status & LEC) != 0x07) | |
{ | |
CAN0_error = 1; | |
} | |
} | |
if (status & BOff) | |
{ | |
CAN0_error = 1; | |
} | |
if (status & EWarn) | |
{ | |
CAN0_error = 1; | |
} | |
} | |
#else // CAN0_PAGE | |
#error CAN0 not defined (check myPlatform includes the correct target definitions) | |
#endif // CAN0_PAGE |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Module for communicating with C_CAN device on C8051F500 and F580. | |
NB: make sure init.c:CAN_Init() sets the clock to below 25Mhz (and enable CAN0_interrupt) | |
USAGE: | |
to send a CAN packet, fill in CAN0_transmit with the desired state and call | |
CAN0_send(&CAN0_transmit); | |
on the arrival of a message, the interrupt will fill CAN0_receive and set CAN0_received | |
to a truthy value, which can be checked in your main loop. Example loop: | |
while(1) | |
{ | |
if(CAN0_received == 1) | |
{ | |
CAN_message_t *m = &CAN0_receive; | |
if(m->Remote == 1) | |
{ | |
m->Remote = 0; | |
CAN0_send(m); | |
} | |
CAN0_received = 0; | |
} | |
} | |
will reply to remote frames with random data. | |
*/ | |
// magic externs | |
#ifdef __C_CAN_H | |
# define EXTERN /**/ | |
#else | |
#ifdef __cplusplus | |
# define EXTERN extern "C" | |
#else | |
# define EXTERN extern | |
#endif // C++ | |
#endif // __C_CAN_H | |
typedef struct CAN_MSG{ | |
long ID; | |
unsigned char Data[8]; | |
char Length : 4; | |
char Extended : 1; | |
char Remote : 1; | |
} CAN_message_t; | |
// only define thins if there exists a C_CAN device on the processor | |
#ifdef CAN0_PAGE | |
//#define CAN0_RAW | |
// holds error state for CAN0 | |
EXTERN unsigned char CAN0_error; | |
// true if a message has been received | |
EXTERN unsigned char CAN0_received; | |
// a received message | |
EXTERN CAN_message_t xdata CAN0_receive; | |
// a message to use for sending data | |
EXTERN CAN_message_t xdata CAN0_transmit; | |
// initialise CAN0 | |
EXTERN void CAN0_init(void); | |
// send a message object | |
EXTERN void CAN0_send(CAN_message_t *message); | |
// send the `len` bytes in `*msg` with `id` as the identifier | |
EXTERN void CAN0_send_raw(long id, unsigned char *msg, unsigned char len); | |
#endif // CAN0_PAGE | |
#undef EXTERN |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This code is out of date, you should look at FallingBullets/C8051_lib for a more up-to-date version of this code