Λοιπόν Νίκο, το παρακάτω μου το έχει δώσει εδώ και πολλά χρόνια ένας συνάδελφος ονόματι A. David για τους TI DSP (TMS320F241 αν θυμάμαι) και τον ευχαριστώ. Στο στέλνω γιατί είναι μικρό και καλό τεστ για αρχική επικοινωνία. Μη σε απασχολεί το ότι είναι για άλλο επεξεργαστή, συνήθως οι registers για το CAN μοιάζουν πολύ από επεξεργαστή σ' επεξεργαστή.
Αρχείο: patchCan.h
Κώδικας:
/*-----------------------------------------------------------------------------
/ Structure for message box. The layout of this structure corresponds to the
/ layout of the hardware Tx buffer.
/------------------------------------------------------------------------------*/
struct t_msg
{
unsigned int id;
unsigned int DLC;
unsigned int byte10;
unsigned int byte32;
unsigned int byte54;
unsigned int byte76;
};
/*=============================================================================
/
/ Function Prototypes:::
/
/ Function and argument types are declared here for both local and external
/ use. The structs for message boxes and nodes need to be defined before the
/ prototypes can be given so that the prototypes can use the structs.
/==============================================================================*/
void init_can(void);
void init_msgboxes(int);
void ManageTx(void);
void message_long(struct t_msg *);
/*=============================================================================
/
/ Hardware definitions:::
/
/ Hardware control and signals are defined here. Refer to the TI TMS320F241
/ manual for full descriptions of the functions of the hardware control and
/ signal bits.
/
/==============================================================================*/
/*-----------------------------------------------------------------------------
/ Definitions for BusOff (BO) signal and AutoBusOn (ABO) control.
/------------------------------------------------------------------------------*/
#define BO (1<<2)
#define ABO (1<<7)
#define BusOff (CANESR & BO)
#define MaxTxErrorsPerTx 50
#define Waiting 1
#define TxSuccessful 2
#define TxFailed 4
/*-----------------------------------------------------------------------------
/ These macros clear the interrupt request hardware signals, use them to
/ clear the interrupt at the end of the ISR,
/------------------------------------------------------------------------------*/
#define _ClearVRInterrupt() CANRCR |=(1<<4)
/*-----------------------------------------------------------------------------
/ These macros enable and disable the CAN module.
/------------------------------------------------------------------------------*/
#define _DisableCAN() IMR &=~0x10
#define _EnableCAN() IMR |= 0x10
/*-----------------------------------------------------------------------------
/ E n d O f F i l e P a t c h C a n . H
/------------------------------------------------------------------------------*/
Αρχείο: patchCan.c
Κώδικας:
/*=============================================================================
/
/============================================================================*/
#include<stdlib.h>
#include<c241_c.h>
#include<w_dog.h>
#include "patchcan.h"
/************************************************************************/
/* */
/* This routine initialzes the CAN Module for 1Mbit transfer rates */
/* message box 0 is used for reception of valve responce packets */
/* message box 5 is used for transmition of demands */
/* */
/************************************************************************/
void init_can(void)
{
/* set up CAN controler */
OCRB |= 0xC0; /* I/O pins */
/* set up bit rates */
CANMCR = 0x3400; /* change configuration request */
while((CANGSR &(1<<4)) == 0); /* wait for request to be granted */
/* Set bit config as Tseg1 = 5 and Tseg2 = 2, sjw = 2 sync on falling edge only */
CANBCR1 = (1<<10) | (2<<8) | (0<<7) | (5<<3) | (2<<0);
CANBCR2 = 0x1; /* baud rate prescaler baud rate = 1M Bit 10 TQ */
CANMCR &=~(1<<12); /* clear Change configuration Bit */
CANMCR |= ABO; /* Enable AutoBusOn */
while((CANGSR &(1<<4)) != 0); /* wait for request to be granted */
}
/*===========================================================================
/ init_msgboxesMaster
/ Passed in: Nothing
/ Returned: void
/
/ Function:
/ Sets up message boxes 0 and 2 to recieve stuff.
/
/===========================================================================*/
void init_msgbox(void)
{
CANMDER = 0x00; /* disable message boxs */
CANMCR |= (1<<8); /* set Change Data Field Request */
CANMSGID0H = 0x5000; /* set ID for MSGBOX0 as 10000000000b and enable mask*/
CANLAM0_H = 0x1FC; /* set acceptance mask 1000xxxxxxxb */
CANMSGID2H = 0x4200; /* set ID for MSGBOX2 as 00010000000b and enable mask*/
CANLAM1_H = 0x1FC; /* set acceptance mask 0001xxxxxxxb */
CANMCR &= ~(1<<8); /* clear Change Data Field Request */
CANMCR |= ABO; /* Enable AutoBusOn */
CANMDER = (1<<0) | (1<<5) | (1<<2) | (1<<6); /* enable message box 5 for tx and 0 and 2 for rx */
CANIMR = (1<<8) | (1<<15) | (1<<10); /* enable low priority rx interupt on all msgboxs */
CANRCR |= 0x0F; /* don't notify if an RX message is lost */
IMR |= 0x10; /* enable Interrupt 5 */
}
/*=============================================================================
/ message_long
/ Passed in: pointer to message structure
/ Returned: void
/
/ Function:
/ Transmits a long message over the can.
/
/============================================================================*/
void message_long(struct t_msg *msg)
{
if (!BusOff)
{
CANMDER &= ~(1<<5); /* Disable message box 5*/
CANMCR |= (1<<8); /* set Change Data Field Request */
CANMSGID5H = (msg->id&0x7FF)<<2; /*Mask in the 11 bit ID */
CANMSGCTRL5 = msg->DLC;
CANMBX5A = msg->byte10;
CANMBX5B = msg->byte32;
CANMBX5C = msg->byte54;
CANMBX5D = msg->byte76;
ManageTx();
}
}
/*=============================================================================
/ ManageTx
/ Passed in: void
/ Returned: void
/
/ Function:
/
/
/============================================================================*/
void ManageTx(void)
{
int WaitingForTx;
CANMCR = (1<<10); /* clear Change Data Field Request and set DBO */
CANMCR |= ABO; /* Enable AutoBusOn */
CANMDER |= (1<<5); /* enable message box 5 */
WaitingForTx = Waiting;
CANTCR = 0x80; /* request trasmit */
while (WaitingForTx == Waiting)
{
if (CANTCR & 0x8000)
WaitingForTx = TxSuccessful;
if (CANESR & 0x003)
WaitingForTx = TxFailed;
}
if (WaitingForTx == TxSuccessful)
{
CANTCR = 0x8000;
}
else
{
CANTCR |= 1<<3;
}
}
/*===========================================================================*/
/*===========================================================================*/
/* */
/* this ISR responds to a level 5 interrupt. */
/* if the interrupt was caused by an rx in message box0, the flow data is */
/* extracted and saved in NodeQ[]; */
/* SCI is also set up to use this interrupt which has to be handled */
/* context saving is only done once */
/* */
/*===========================================================================*/
/*===========================================================================*/
interrupt void c_int_can(void)
{
int i,iRxID,iBuff,iFirstMatch;
int itemp,itemp2;
IMR &= ~0x10;
asm(" clrc INTM ");
if(_ValveResponseReceived) /* rx in mbox0 = valve responce */
{
/* do CAN module work around */
CANMDER &= ~(1<<0); /* disable message box 0 */
CANMCR |= (1<<8); /* set CDR bit */
CANMSGID0H = 0x5000; /* set ID for MSGBOX0 as 1000 0000000b and enable mask*/
CANMCR = (1<<10); /* clear Change Data Field Request and set DBO */
CANMDER |= (1<<0); /* enable msgbox0 */
_ClearVRInterrupt(); /* clear RMP bit (+ IF bit)*/
}
IFR |= 0x10;
asm(" setc INTM ");
IMR |= 0x10;
}
/*=============================================================================
/ E N D O F F I L E P A T C H C A N . C
/============================================================================*/