=================================================================

#include <C8051F040.H> 

/*type definition */
typedef unsigned char UCHAR;   
typedef unsigned short USHORT;
typedef unsigned int UINT;
typedef unsigned long ULONG;

/* funktion prototypes  */
void CanInit(void); //inicializace CAN modulu
void CanSetMsgRx(UCHAR cislo,USHORT id,UCHAR dlc); //nastaveni projimaciho objektu zprav
void CanSetMsgTx(UCHAR cislo,USHORT id,UCHAR dlc); //nastaveni vysilaciho objektu zprav
void CanTransmit(void);  //vyslani zpravy
void Port_Init (void);
void Oscilator_INIT (void);

/* index CAN registr (index in CAN0ADR)  */
#define CanControlRegistr 		0x00  // CAN0CN
#define CanStatusRegistr   		0x01  // CAN0STA
#define CanErrorCount      		0x02  // RP,REC,TEC
#define CanBitTimingRegistr     0x03  // Timing
#define CanInterruptRegistr		0x04  // interrupt identificator
#define CanTestRegistr      	0x05  // CAN0TST
#define CanExtensionBRP			0x06  // BRP Extension to 10 bits
#define CanIF1CommandRequest    0x08  // number of object
#define CanIF1CommandMask       0x09  // 
#define CanIF1LowerMask    		0x0A  // filter mask,lower bits
#define CanIF1UpperMask    		0x0B  // filter mask,higher bits
#define CanIF1LowerArbitration  0x0C  // ID, lower bits
#define CanIF1UpperArbitration  0x0D  // ID, higher bits
#define CanIF1MessageControl    0x0E  // 
#define CanIF1DataA1	    	0x0F  // data - 1 - 2 byte
#define CanIF1DataA2	    	0x10  // data - 3 - 4 byte
#define CanIF1DataB1	    	0x11  // data - 5 - 6 byte
#define CanIF1DataB2	    	0x12  // data - 7 - 8 byte
#define CanIF2CommandRequest    0x20  // Number of object
#define CanIF2CommandMask       0x21  // 
#define CanIF2LowerMask    		0x22  // filter mask,lower bits
#define CanIF2UpperMask    		0x23  // filter mask,higher bits
#define CanIF2LowerArbitration  0x24  // ID, lower bits
#define CanIF2UpperArbitration  0x25  // ID, higher bits
#define CanIF2MessageControl    0x26  // 
#define CanIF2DataA1	    	0x27  // data - 1. and 2. byte
#define CanIF2DataA2	    	0x28  // data - 3. and 4. byte
#define CanIF2DataB1	    	0x29  // data - 5. and 6. byte
#define CanIF2DataB2	    	0x2A  // data - 7. and 8. byte
#define CanTransmissionRequest1 0x40  // TRQX 1 - 16
#define CanTransmissionRequest2 0x41  // TRQX 17 - 32
#define CanNewDat1  	 		0x48  // NEWDAT 1 - 16
#define CanNewDat2  	 		0x49  // NEWDAT 17 - 32
#define CanInterruptPending1  	0x50  // INTPND 1 - 16
#define CanInterruptPending2  	0x51  // INTPND 17 - 32
#define CanMessageValid1  		0x58  // MSGVAL 1 - 16
#define CanMessageValid2  		0x59  // MSGVAL 17 - 32

/* macros for writing to CAN's registrs */
#define CanWrReg(hb,lb)  CAN0DATH=(hb); CAN0DATL=(lb);  //zapis 2 bytu dat na adr. v CAN0ADR
#define CanWrAdr(index,datah,datal) CAN0ADR=index; CanWrReg((datah),(datal)) //zapis 2 bytu dat na zadanou adresu
#define CanWrL(index,data8) CAN0ADR=index; CAN0DATL=(data8);         // zapis 1 bytu dat na zadanou adresu

/* bits CAN Control - CAN0CN*/
#define INITC 0x01
#define IEC   0x02
#define SIEC  0x04
#define EIEC  0x08
#define IFC   0x10
#define DARC  0x20
#define CCEC  0x40
#define TESTC 0x80

/* bits IF Arbitration */
#define FOR_RX 			0x00
#define FOR_TX 			0x20
#define STANDARD_FRAME	0x00
#define EXTENDED_FRAME	0x40
#define CLR_MSGVAL 		0x00
#define MSGVAL 			0x80

/* bits IF Mask  */
#define CLR_MDIR 		0x00
#define MDIR 			0x40
#define CLR_MXTD 		0x00
#define MXTD 			0x80

/* bits IF Control,config */
#define EOB 	0x80
#define TXRQST 	0x01
#define RMTEN 	0x02
#define RXIE 	0x04
#define TXIE 	0x08
#define UMASK 	0x10
#define INTPND 	0x20
#define MSGLST 	0x40
#define NEWDAT 	0x80

/* bits IF Commad Mask  */
#define CDATAB 	0x01
#define CDATAA 	0x02
#define CNEWDAT 0x04
#define CTXRQST 0x04
#define CINTPND 0x08
#define CONTROL 0x10
#define CARB 	0x20
#define CMASK 	0x40
#define CWR 	0x80
#define CRD 	0x0
  
/*global variables*/
UCHAR id;
USHORT h;

/* IDs and DLCs */
#define ID_SPEED 0x280		// ID for velocity	
#define ID_SPIN 0x320		// ID for speed
#define DLC_SPEED 8			// DLC for Velocity
#define DLC_SPIN 8			// DLC for Speed


/*------------------------------------------------------ 
       MAIN 
------------------------------------------------------*/ 
void main (void) 
{
  WDTCN = 0xde;
  WDTCN = 0xad;						// Watchdog off
  
  Port_Init ();						// port Init
  Oscilator_INIT ();				// oscilator init
  CanInit ();
  while (1)
  {
  }
}

/*------------------------------------------------------ 
       Initialize CAN 
------------------------------------------------------*/ 
void CanInit(void)  
{
    unsigned char i;    
    SFRPAGE=CAN0_PAGE;
    CAN0CN=CCEC|INITC;								// for setup BTR
    CAN0STA=0;
    CanWrAdr(CanBitTimingRegistr, 0x7D,0xC0)   		// SETUP of BitTimmingRegistr 
    CanWrL (CanIF1CommandMask,0xFF)
    CanWrAdr(CanIF1UpperArbitration,CLR_MSGVAL,0)
    for(i=1;i<33;i++)
    	{
    	CanWrL (CanIF1CommandRequest,i)	            	// reset of all MSGVALs (unused)
   	 	}
    CanSetMsgRx(1,ID_SPEED,DLC_SPEED);					// nastaveni objektu 1: rychlost
    CanSetMsgRx(2,ID_SPIN,DLC_SPIN);					// nastaveni objektu 2: otacky

    CanWrL (CanIF1CommandMask,CONTROL|CINTPND|CNEWDAT|CDATAA|CDATAB)  // mask for receive objects

    CAN0CN=IEC;										// Interrupt in CAN core enabled
    EIE2=0x20;										// Interrupt in MCU from CAN core enabled
	EA = 1;											// Global interrupt enabled
}

/*------------------------------------------------------ 
       SETUP receive object 
------------------------------------------------------*/ 

void CanSetMsgRx(unsigned char cislo,USHORT id,unsigned char dlc)
{
    CanWrL (CanIF1CommandMask,CWR|CMASK|CARB|CONTROL)  // write, mask, ID, control
	//autoincrement CANOADR
	CanWrReg(0xFF,0xFF);                               // lower mask
	//autoincrement CANOADR
	CanWrReg(0xFF,0xFF);                               // higher maska
	//autoincrement CANOADR
	CanWrReg(0,0);                                     // lower ID
	//autoincrement CANOADR
    CanWrReg(MSGVAL|FOR_RX|(unsigned char)(id>>8),(unsigned char)(id))	// MSGVAL,receive,higher ID 
	//autoincrement 
    CanWrReg(RXIE,EOB|dlc)
	//autoincrement	                           // control: povoleni preruseni, delka
    CanWrL (CanIF1CommandRequest,cislo)				   // write to RAM object
}

/*------------------------------------------------------ 
       ISR for CAN core 
------------------------------------------------------*/ 

void CanInterrupt(void) interrupt 19
{
 SFRPAGE  = CAN0_PAGE; 
 while(1)				
 {
   CAN0ADR= CanInterruptPending1;		// indication of source of interrupt
   id = CAN0DATL;
   if(id==0) break;						// bRake if no request
   if(id & 1)
   {									// object 1: velocity
     CanWrL(CanIF2CommandRequest, 1)	// data from RAM to IF registru
     CAN0ADR= CanIF2DataB1;				// value of velocity  is on 4th and 5th byte
     h=CAN0DATH>>1;						// bits 15 - 1 
     CAN0ADR= CanIF2DataA2;
     h|=(CAN0DATL<<7);
   }
   if(id & 2)
   {// object 2: engine speed
     CanWrL(CanIF2CommandRequest,2)// data from RAM to IF registr
     CAN0ADR= CanIF2DataA2;// value of speed is on 3rd and 4th byte
     h=(CAN0DATH<<8);	// new value: bits 15 - 0
     h+=CAN0DATL;    
    }
 }

}

/*---------------------------------------------------------
Init procedures
----------------------------------------------------------*/
void Oscilator_INIT (void)
{
  int n;                        // local variable used in delay FOR loop.
  SFRPAGE = CONFIG_PAGE;        // switch to config page to config oscillator
  OSCXCN  = 0x77;               // ext. osc - 22.1 MHz Crystal
                                // system clock is 11.05 MHz
  for (n=0;n<3000;n++);         // delay about 1ms
  while ((OSCXCN & 0x80) == 0); // wait for oscillator to stabilize
  CLKSEL |= 0x01;               // switch to external oscillator
}

void Port_Init (void)
{
  SFRPAGE  = CONFIG_PAGE;        
  XBR3     = 0x80;     			 // CAN TX - push-pull 
  P1MDOUT |= 0x40;     			 // P1.6 - push-pull (LED)
  XBR2     = 0x40;     			 // Enable Crossbar/low ports
}
=================================================================