nnimo 发表于 2014-5-29 09:51:02

【代码分享】基于飞思卡尔HCS12处理器的CAN驱动源代码.

本帖最后由 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 ;
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 = 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 ;
      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 ;
    CAN1TXDSR1 = canframe->data ;
    CAN1TXDSR2 = canframe->data ;
    CAN1TXDSR3 = canframe->data ;
    CAN1TXDSR4 = canframe->data ;
    CAN1TXDSR5 = canframe->data ;
    CAN1TXDSR6 = canframe->data ;
    CAN1TXDSR7 = canframe->data ;
//
    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++)
      ;
}

FSL_TICS_ZJJ 发表于 2014-5-29 10:46:56

感谢楼主的代码分享!

lyzhangxiang 发表于 2014-5-29 13:03:09

fsl团队搞个canopen的帖子吧,单单can应用太单调了
看了好几天301文档还是不懂字典对象怎么起作用的

zndz410 发表于 2014-5-29 15:26:11

支持顶一个。

浪里白条 发表于 2014-5-31 22:32:11

有用,感谢楼主分享

FSL_TICS_ZP 发表于 2014-6-3 10:09:39

感谢楼主分享!

laotui 发表于 2014-9-1 12:42:28

can非常有用,谢谢楼主分享源码。

829xuming 发表于 2014-9-1 19:22:25

支持分享

浪里白条 发表于 2014-9-1 19:52:36

lyzhangxiang 发表于 2014-5-29 13:03
fsl团队搞个canopen的帖子吧,单单can应用太单调了
看了好几天301文档还是不懂字典对象怎么起作用的 ...

这个可以有!

829xuming 发表于 2014-9-1 22:32:39

支持分享

湛泸骏驰 发表于 2014-9-1 22:59:55

楼主可否来个简单的实例呢。。。这块不太懂,有意向试一下。。。有一个板子的。

wycox 发表于 2014-9-2 00:49:18

让我也在DEMO9S12XEP100上试试看。

rockyyangyang 发表于 2014-9-4 14:50:46

mark            

wangkdd 发表于 2014-9-4 16:10:51

楼主照片太猛了吧

dongyanbo 发表于 2014-9-4 16:12:07

感谢楼主的代码分享
页: [1]
查看完整版本: 【代码分享】基于飞思卡尔HCS12处理器的CAN驱动源代码.