|
本帖最后由 FSL_TICS_ZJJ 于 2014-5-29 10:46 编辑
这是Freescale的HCS12处理器上面的CAN驱动源代码。支持发送、中断接收和轮询接收等操作。mycan.h文件在附件中 .
#include "mycan.h"
#include "app_cfg.h"
/* 初始化CAN
The procedure to initially start up the MSCAN module out of reset is as follows:
1. Assert CANE
2. Write to the configuration registers in Initialization Mode
3. Clear INITRQ to leave Initialization Mode and enter Normal Mode
*/
void CAN_Init(void)
{
PTM &= ~0xC;
DDRM &= ~0xC;
DDRM |= 0x8;
CAN1CTL1_CANE = 1 ;
CAN1CTL0_INITRQ = 1 ; // initial request, start to initial
while (CAN1CTL1_INITAK != 1 ) ;
CAN1CTL1_LISTEN = 0 ; // not listen mode
CAN1CTL1_CLKSRC = 1 ; // bus clock, 8MHz?
// CAN1CTL1_CLKSRC = 0 ; // crystal clock, 16MHz?
CAN1BTR0_BRP = 1 ; // prescale = 2 or 4
CAN1BTR1_SAMP = 0 ; // once per bit
CAN1BTR1_TSEG_10 = 4 ; // 5tq
CAN1BTR1_TSEG_20 = 1 ; // 2tq
// bit rate = ftq / num-of-tq = fclk / prescale / (syncSeg + tSeg1 + tSeg2)
// = 8MHz / 4 / (1 + 5 + 2) = 250Kbps
CAN1IDAC_IDAM = 0 ; // never choose 3(close filter), or no message will be received!!!
CAN1IDAR0 = 0xff ;
CAN1IDAR1 = 0x18 ;
CAN1IDAR2 = 0x3f ;
CAN1IDAR3 = 0xff ;
CAN1IDAR4 = 0xff ;
CAN1IDAR5 = 0x18 ;
CAN1IDAR6 = 0x3f ;
CAN1IDAR7 = 0xff ;
CAN1IDMR0 = 0xff ;
CAN1IDMR1 = 0x00 ;
CAN1IDMR2 = 0x3f ;
CAN1IDMR3 = 0xff ;
CAN1IDMR4 = 0xff ;
CAN1IDMR5 = 0x00 ;
CAN1IDMR6 = 0x3f ;
CAN1IDMR7 = 0xff ;
CAN1CTL0_INITRQ = 0 ; // stop initialization, start can
while (CAN1CTL1_INITAK != 0 ) ;
while (CAN1CTL0_SYNCH != 1) ;
CAN1RIER = 0 ; //disable Receiver Interrupt
CAN1TIER = 0 ; //disable Transmitter Interrupt
CAN1RIER_RXFIE = 1 ; CAN1RIER_OVRIE = 1 ; //enable receiver interrupt
CPU_INT_EN(); //interrupt must be enabled!!!!
}
INT8U CAN_PollFrame(CAN_frame *canframe)
{
INT8U *pdata ;
INT32U tempID ;
if (0 == CAN1RFLG_RXF)
{
return FALSE ;
}
pdata = &(CAN1RXDSR0) ;
memcpy(canframe->data, pdata, 8) ;
canframe->datalen = CAN1RXDLR & 0x0f;
canframe->id = 0 ;
tempID = *(INT32U *)&(CAN1RXIDR0) ; // because it's big-endian!!
if (CAN1RXIDR1_IDE) // ext frame
{
if (CAN1RXIDR3_RTR)
canframe->type = FRAME_EXT_REMOTE ;
else
canframe->type = FRAME_EXT_DATA ;
canframe->id = ((tempID >> 1) & 0x03ffff) | ((tempID >> 21) << 18) ;
}
else // std frame
{
if (CAN1RXIDR1_SRR)
canframe->type = FRAME_STD_REMOTE ;
else
canframe->type = FRAME_STD_DATA ;
canframe->id = (tempID >> 21) ;
}
CAN1RFLG_RXF = 1 ;
return TRUE ;
}
static CAN_frame canbuf[FRAME_BUF_NUM] ;
static INT8U indexR = 0 ;
static INT8U indexW = 0 ;
CAN_frame RecvedCANframe ; // to save push-stack time
ISR (CAN_RecvISR)
{
INT8U retval ;
OSEKPrintString("========== recv interrupt ====\n") ;
retval = CAN_PollFrame(&RecvedCANframe) ;
if (TRUE == retval)
{
/* OSEKPrintString("poll ok\n") ;
displayCAN(&RecvedCANframe) ;
OSEKPrintString("indexW = ") ;
OSEKPrintInt((INT32U)indexW) ;
OSEKPrintString("indexR = ") ;
OSEKPrintInt((INT32U)indexR) ;
if ((indexW + 1) % FRAME_BUF_NUM == indexR)
{
}
else
{
indexW = (indexW + 1) % FRAME_BUF_NUM ;
canbuf[indexW] = RecvedCANframe ;
} */
SetEvent(Task1, EventCAN) ;
}
else
{
OSEKPrintString("poll failed\n") ;
}
}
INT8U CAN_GetFrame(CAN_frame *canframe)
{
OSEKPrintString("GetFRame() :\nindexW = ") ;
OSEKPrintInt((INT32U)indexW) ;
OSEKPrintString("indexR = ") ;
OSEKPrintInt((INT32U)indexR) ;
if (indexR == indexW)
{
return FALSE ;
}
else
{
indexR = (indexR + 1) % FRAME_BUF_NUM ;
*canframe = canbuf[indexR] ;
return TRUE ;
}
}
INT8U CAN_SendFrame(CAN_frame *canframe)
{
INT32U tempID, idr32 ;
if (0 == CAN1TFLG) // no available tx register buffer
{
return FALSE ;
}
tempID = canframe->id ;
switch(canframe->type)
{
case FRAME_STD_DATA :
idr32 = (tempID << 21) ;
break ;
case FRAME_STD_REMOTE :
idr32 = (tempID << 21) | 0x00100000 ;
break ;
case FRAME_EXT_DATA :
idr32 = ((tempID << 1) & 0x0007fffe) | ((tempID << 3) & 0xffe00000) | 0x00180000 ;
break ;
case FRAME_EXT_REMOTE :
idr32 = ((tempID << 1) & 0x0007fffe) | ((tempID << 3) & 0xffe00000) | 0x00180001 ;
break ;
default :
return FALSE ;
}
// OSEKPrintString("CAN1TFLG = ") ; OSEKPrintInt((INT32U)CAN1TFLG) ;
// OSEKPrintString("CAN1TBSEL = ") ; OSEKPrintInt((INT32U)CAN1TBSEL) ;
CAN1TBSEL = CAN1TFLG ; // choose the available TX Buffer. see <<S12MSCANV2.pdf>> page 31 //获得缓冲区
// if you display CAN1TBSEL here , you will always see just one "1" is set
/* setting the tx registers */
// *(INT32U *)&(CAN1RXIDR0) = idr32 ;
// memcpy(&(CAN1RXDSR0), canframe->data, 8) ;
// the above does not get right result, use the following.
// the following steps are equal to the 2 lines above, but use the above 2 lines gets error!!
CAN1TXIDR0 = idr32 >> 24 ;
CAN1TXIDR1 = idr32 << 8 >> 24 ;
CAN1TXIDR2 = idr32 << 16 >> 24 ;
CAN1TXIDR3 = idr32 << 24 >> 24 ;
CAN1TXDSR0 = canframe->data[0] ;
CAN1TXDSR1 = canframe->data[1] ;
CAN1TXDSR2 = canframe->data[2] ;
CAN1TXDSR3 = canframe->data[3] ;
CAN1TXDSR4 = canframe->data[4] ;
CAN1TXDSR5 = canframe->data[5] ;
CAN1TXDSR6 = canframe->data[6] ;
CAN1TXDSR7 = canframe->data[7] ;
//
CAN1TXDLR = canframe->datalen ;
CAN1TXTBPR = 0x1234 ; // NOT USED
/* setting the tx registers */
// CAN1TFLG &= ~CAN1TBSEL ; // set the corresponding bit to ZERO, so that MSCAN start to send it //释放缓冲区
CAN1TFLG = CAN1TBSEL ; // clear TXE in order to send data in TX Buffer. see <<S12MSCANV2.pdf>> page 28
DelayTime(20) ;
return TRUE ; // send OK
}
void displayCAN(CAN_frame *canframe)
{
CAN_frame f = *canframe ;
INT8U i ;
OSEKPrintString("displayCAN:\nid = ") ;
OSEKPrintInt(f.id) ;
OSEKPrintString("\ntype = ") ;
OSEKPrintInt((INT32U)f.type) ;
OSEKPrintString("\nlen = ") ;
OSEKPrintInt((INT32U)f.datalen) ;
OSEKPrintString("\ndata = ") ;
for (i=0; i<8; i++)
{
OSEKPrintChar(f.data) ;
OSEKPrintChar(' ') ;
}
OSEKPrintString("\nCAN displayed\n") ;
}
void DelayTime(INT16U cycle)
{
INT16U i ;
for (i=0; i<cycle; i++)
;
}
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
阿莫论坛20周年了!感谢大家的支持与爱护!!
你熬了10碗粥,别人一桶水倒进去,淘走90碗,剩下10碗给你,你看似没亏,其实你那10碗已经没有之前的裹腹了,人家的一桶水换90碗,继续卖。说白了,通货膨胀就是,你的钱是挣来的,他的钱是印来的,掺和在一起,你的钱就贬值了。
|