DSPIC33EV DSPIC33EP系列CAN驱动

   今天带着大家学习DSPIC33EV、DSPIC33EP系列CAN驱动模块的配置。下面直接上代码一起结合数据手册一起学习下,

首先我们先来看下DSPIC33EV、DSPIC33EP系列CAN框图


ECAN模块包括:DMA(Direct Memory Access,直接内存存取),CAN协议引擎,过滤器、屏蔽寄存器等,如上图所示,CAN总线上收到数据之后

保存至DMA RX接收缓冲区控制寄存器  ,同样发送时将发送的数据保存至DMA TX发送缓冲区控制寄存器。。。

下面直接结合代码看看

#include <xc.h>
#include "ecan1_config.h"


/******************************************************************************
 * Function:      void DMA0Init(void)
 *
 * PreCondition:  None
 *
 * Input:         None
 *
 * Output:        None
 *
 * Side Effects:  None
 *
 * Overview:      DMA0 initialization/configuration function.
 *                Direction: Read from RAM and write to the C1TXD register
 *                AMODE: Register indirect with post increment
 *                MODE: Continuous, Ping-Pong Mode
 *                IRQ: ECAN1 Transmit Interrupt
 *****************************************************************************/
void DMA0Init( void )
{
    //     DMACS0=0;
    DMAPWC = 0;
    DMARQC = 0;
    DMA0CON = 0x2020;
    DMA0PAD = ( int ) &C1TXD;   /* ECAN 1 (C1TXD) */  设置为ECAN 发送缓冲区
    DMA0CNT = 0x0007;
    DMA0REQ = 0x0046;           /* ECAN 1 Transmit */


    #ifdef _HAS_DMA_
    DMA0STAL = __builtin_dmaoffset( ecan1msgBuf );
    DMA0STAH = __builtin_dmapage( ecan1msgBuf );
    #else
    DMA0STAL = (uint16_t)(int_least24_t)(&ecan1msgBuf);
    DMA0STAH = 0;
    #endif
    DMA0CONbits.CHEN = 1;
  //  Enable: Enable DMA Channel 0 Interrupt */
//IEC0bits.DMA0IE = 1;   //added ramya
}
void DMA1Init( void )
{
//    DMAPWC = 0;
//    DMARQC = 0;
//    DMA1CON = 0x2020;
//    DMA1PAD = ( int ) &C1RXD;   /* ECAN 2 (C2TXD) */
//    DMA1CNT = 0x0007;
//    DMA1REQ = 0x0022;           /* ECAN 2 Transmit */
//
//    #ifdef _HAS_DMA_
//    DMA1STAL = __builtin_dmaoffset( ecan2msgBuf );
//    DMA1STAH = __builtin_dmapage( ecan2msgBuf );
//    #else
//    DMA1STAL = (uint16_t)(int_least24_t)(&ecan1msgBuf);
//    DMA1STAH = 0;
//    #endif
//    DMA1CONbits.CHEN = 1;
}
/******************************************************************************
 * Function:      void DMA2Init(void)
 *
 * PreCondition:  None
 *
 * Input:         None
 *
 * Output:        None
 *
 * Side Effects:  None
 *
 * Overview:      DMA0 initialization/configuration function.
 *                Direction: Read from RAM and write to the C1RXD register
 *                AMODE: Register indirect with post increment
 *                MODE: Continuous, Ping-Pong Mode
 *                IRQ: ECAN1 Transmit Interrupt
 *****************************************************************************/
void DMA2Init( void )
{
    //     DMACS0=0;
    DMAPWC = 0;
    DMARQC = 0;
    DMA2CON = 0x0020;
    DMA2PAD = ( int ) &C1RXD;   /* ECAN 1 (C1RXD) */   设置为ECAN 接收缓冲区
    DMA2CNT = 0x0007;
    DMA2REQ = 0x0022;           /* ECAN 1 Receive */


    #ifdef _HAS_DMA_
    DMA2STAL = __builtin_dmaoffset( ecan1msgBuf );
    DMA2STAH = __builtin_dmapage( ecan1msgBuf );
    #else
    DMA2STAL = (uint16_t)(int_least24_t)(&ecan1msgBuf);
    DMA2STAH = 0;
    #endif
    DMA2CONbits.CHEN = 1;


}


/******************************************************************************
 * Function:      void Ecan1ClkInit(void)
 *
 * PreCondition:  None
 *
 * Input:         None
 *
 * Output:        None
 *
 * Side Effects:  None
 *
 * Overview:      ECAN1 clock initialization function
 *                This function is used to configure the clock used for the
 *                ECAN1 module during transmission/reception.
 *****************************************************************************/
void Ecan1ClkInit( void )
{
    /* FCAN is selected to be FCY
   FCAN = FCY = 40MHz */
    //    C1CTRL1bits.CANCKS = 0x1;
    /*
Bit Time = (Sync Segment + Propagation Delay + Phase Segment 1 + Phase Segment 2)=20*TQ   通过同步段、时间段等设置位时间  ,设置指定的波特率
Phase Segment 1 = 8TQ
Phase Segment 2 = 6Tq
Propagation Delay = 5Tq
Sync Segment = 1TQ
CiCFG1<BRP> =(FCAN /(2 譔譌BAUD))?1
*/
    /* Synchronization Jump Width set to 4 TQ */
    C1CFG1bits.SJW = 0x0;


    /* Baud Rate Prescaler */
    C1CFG1bits.BRP = BRP_VAL;


    /* Phase Segment 1 time is 8 TQ */
    C1CFG2bits.SEG1PH = 0x7;


    /* Phase Segment 2 time is set to be programmable */
    C1CFG2bits.SEG2PHTS = 0x1;


    /* Phase Segment 2 time is 6 TQ */
    C1CFG2bits.SEG2PH = 0x5;


    /* Propagation Segment time is 5 TQ */
    C1CFG2bits.PRSEG = 0x4;


    /* Bus line is sampled three times at the sample point */
    C1CFG2bits.SAM = 0x1;
}


/******************************************************************************
 * Function:     void Ecan1Init(void)
 *
 * PreCondition:  None
 *
 * Input:         None
 *
 * Output:        None
 *
 * Side Effects:  None
 *
 * Overview:      ECAN1 initialization function.This function is used to
 *                initialize the ECAN1 module by configuring the message
 *                buffers, and the acceptance filters and
 *                setting appropriate masks for the same.
 *****************************************************************************/
void Ecan1Init( void )
{
    /* Request Configuration Mode */
    C1CTRL1bits.REQOP = 4;
    while( C1CTRL1bits.OPMODE != 4 );


    Ecan1ClkInit();    


    C1FCTRLbits.DMABS = 0b000;     /* 4 CAN Message Buffers in DMA RAM */


    /*    Filter Configuration


    Ecan1WriteRxAcptFilter(int n, long identifier, unsigned int exide,unsigned int bufPnt,unsigned int maskSel)


    n = 0 to 15 -> Filter number


    identifier -> SID <10:0> : EID <17:0> 


    exide = 0 -> Match messages with standard identifier addresses 
    exide = 1 -> Match messages with extended identifier addresses 


    bufPnt = 0 to 14  -> RX Buffer 0 to 14
    bufPnt = 15 -> RX FIFO Buffer


    maskSel = 0    ->    Acceptance Mask 0 register contains mask
    maskSel = 1    ->    Acceptance Mask 1 register contains mask
    maskSel = 2    ->    Acceptance Mask 2 register contains mask
    maskSel = 3    ->    No Mask Selection
    
*/
   // Ecan1WriteRxAcptFilter( 1, 0x1FFEFFFF, 1, 1, 0 );
   Ecan1WriteRxAcptFilter( 1, 0x123, 0, 1, 0 );   设置接收过滤即只接受0x123



    /*    Mask Configuration


    Ecan1WriteRxAcptMask(int m, long identifierMask, unsigned int mide, unsigned int exide)


    m = 0 to 2 -> Mask Number


    identifier -> SID <10:0> : EID <17:0> 


    mide = 0 -> Match either standard or extended address message if filters match 
    mide = 1 -> Match only message types that correpond to 'exide' bit in filter


    exide = 0 -> Match messages with standard identifier addresses 
    exide = 1 -> Match messages with extended identifier addresses
    
*/
    //Ecan1WriteRxAcptMask( 1, 0x1FFFFFFF, 1, 1 );
    Ecan1WriteRxAcptMask( 0, 0x7FF, 1, 0 );//MASK0
    Ecan1WriteRxAcptMask( 1, 0x7FF, 1, 0 );//MASK1 
    
    /* Enter Normal Mode */
    C1CTRL1bits.REQOP = 0;
    while( C1CTRL1bits.OPMODE != 0 );
   // while( C1CTRL1bits.OPMODE != 2 );
    /* ECAN transmit/receive message control */
    C1RXFUL1 = C1RXFUL2 = C1RXOVF1 = C1RXOVF2 = 0x0000;
    //C1TR01CONbits.TXEN0 = 1;        /* ECAN1, Buffer 0 is a Transmit Buffer */
    //C1TR01CONbits.TXEN1 = 0;        /* ECAN1, Buffer 1 is a Receive Buffer */
    C1TR01CONbits.TX0PRI = 0b11;   /* Message Buffer 0 Priority Level */
    C1TR01CONbits.TX1PRI = 0b11;   /* Message Buffer 1 Priority Level */


   // C1TR23CONbits.TXEN2 = 1;        /* ECAN1, Buffer 2 is a Transmit Buffer */
    //C1TR23CONbits.TXEN3 = 0;        /* ECAN1, Buffer 3 is a Receive Buffer */
    C1TR23CONbits.TX2PRI = 0b11;   /* Message Buffer 2 Priority Level */
    C1TR23CONbits.TX3PRI = 0b11;   /* Message Buffer 3 Priority Level */
    /* Setup I/O pins */
    // The PPS configuration varies from device to device. Refer the datasheet of the device being used and
    // use the appropriate values for the RPINR/RPOR registers.    
//    RPINR26 = 0;                    //clear register
//    RPINR26bits.C1RXR = 57;         //set CAN1 RX to RP57    设置CAN RX 引脚
//    RPOR6bits.RP56R = 14;           //RP56->CAN1 TX   
}

如需获取相关源码,请关注微信公众号“嵌入式软件开发学习圈”,
留言“DSPIC33EV_CAN”,即可免费获取相关学习资料。

微信公众号内有其他嵌入式学习经验分享。需要朋友们可以关注下微信公众号

如有相关嵌入式学习问题或疑问,欢迎在微信公众号留言.


  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值