⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mycan.c

📁 Freescale的HCS12处理器上面的CAN驱动。支持发送、中断接收和轮询接收等操作。在CodeWarrior中开发的。
💻 C
字号:
#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[i]) ;
                OSEKPrintChar(' ') ;
            }

            OSEKPrintString("\nCAN displayed\n") ;
}

void DelayTime(INT16U cycle)
{
    INT16U i ;
    for (i=0; i<cycle; i++)
        ;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -