搜索
bottom↓
回复: 14

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

[复制链接]

出0入0汤圆

发表于 2014-5-29 09:51:02 | 显示全部楼层 |阅读模式
本帖最后由 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碗,继续卖。说白了,通货膨胀就是,你的钱是挣来的,他的钱是印来的,掺和在一起,你的钱就贬值了。

出0入0汤圆

发表于 2014-5-29 10:46:56 | 显示全部楼层
感谢楼主的代码分享!

出0入0汤圆

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

出0入0汤圆

发表于 2014-5-29 15:26:11 | 显示全部楼层
支持顶一个。

出0入0汤圆

发表于 2014-5-31 22:32:11 | 显示全部楼层
有用,感谢楼主分享

出0入0汤圆

发表于 2014-6-3 10:09:39 | 显示全部楼层
感谢楼主分享!

出0入0汤圆

发表于 2014-9-1 12:42:28 | 显示全部楼层
can非常有用,谢谢楼主分享源码。

出0入0汤圆

发表于 2014-9-1 19:22:25 | 显示全部楼层
支持分享

出0入0汤圆

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

这个可以有!

出0入0汤圆

发表于 2014-9-1 22:32:39 来自手机 | 显示全部楼层
支持分享

出0入0汤圆

发表于 2014-9-1 22:59:55 | 显示全部楼层
楼主可否来个简单的实例呢。。。这块不太懂,有意向试一下。。。有一个板子的。

出0入4汤圆

发表于 2014-9-2 00:49:18 | 显示全部楼层
让我也在DEMO9S12XEP100上试试看。

出0入0汤圆

发表于 2014-9-4 14:50:46 | 显示全部楼层
mark            

出0入0汤圆

发表于 2014-9-4 16:10:51 | 显示全部楼层
楼主照片太猛了吧

出0入0汤圆

发表于 2014-9-4 16:12:07 | 显示全部楼层
感谢楼主的代码分享
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-10-3 02:18

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表