dsPIC33EP芯片ECAN模块学习

dsPIC33EP64MC504 ECAN模块应用笔记 

 

(1) 参考官网的例子
链接地址 http://ww1.microchip.com/downloads/en/DeviceDoc/ce429_ecan_rtr.zip

 

(2) ECAN初始化
在上面的例子中,找到ecan1_config.c文件,需要修改的设置基本上都在这里。

 

1. 波特率设置
函数`Ecan1ClkInit()` 设置CAN总线的波特率,可以直接修改h文件中的宏定义设置波特率,如果需要搞清楚每个参数的意义,参照ECAN的说明文档。

 

#define FCAN 40000000 // ECAN模块的时钟频率,默认情况下等于Fp,也可以设置为Fp的两倍 (CiCTRL1.CANCKS = 1)
#define BITRATE 1000000 // CAN 总线波特率
#define NTQ 20 // 20 Time Quanta in a Bit Time, 不用修改;参考ECAN的文档可以修改处理,Ecan1ClkInit()函数中的参数也要同时修改
#define BRP_VAL ( (FCAN / (2 * NTQ * BITRATE)) - 1 )

 

2. 滤波器和滤波器掩码设置,在`Ecan1Init()`函数中调用了滤波器设置和滤波器掩码设置函数,这个函数在`ecan1_drv.c` 文件中有定义,这个文件不需要修改。
Ecan1WriteRxAcptFilter( 0, CAN_FILTER1, 0, 1, 0 ); // 掩码编号与下方的掩码编号对应
Ecan1WriteRxAcptFilter( 1, CAN_FILTER2, 0, 1, 0 ); // 掩码编号与下方的掩码编号对应
Ecan1WriteRxAcptMask( 0, 0x07FF, 1, 0 ); // 掩码为7FF时,严格匹配过滤器设置ID号;为0x0000时,滤波器ID设置失效,可以匹配任意ID
// 掩码的设置与局域网子网掩码设置类似,对应位为1时,应严格匹配滤波器ID编号,为零的位不匹配

 

3. DMA设置,文件中有两个DMA的初始化设置,分别用于总线数据的发送和接收,具体寄存器的含义可以参考文档,实际应用时可以不做修改

 

4. IO口设置,因为ECAN没有对应的引脚,芯片内部通过RP和RPI映射到具体的引脚,参照自己的硬件原理图,设置好CAN总线的收,发引脚。硬件设计时,要注意RP和RPI的方向性
    TRISBbits.TRISB2 = 1; //CAN1RX input
    TRISBbits.TRISB7 = 0; //CAN1TX output
    // remapping CAN1RX to RPI34 , CAN1TX to RP39
    RPINR26bits.C1RXR = 34;
    _RP39R = 14; // or RPOR0bits.RP39R = 1 ;

 

5. 缓存数据设置。
// 定义缓存变量,在例子的main.c文件中可找到
__eds__ ECAN1MSGBUF ecan1msgBuf __attribute__((space(eds), aligned(ECAN1_MSG_BUF_LENGTH * 16)));
/* ECAN transmit/receive message control */
C1RXFUL1 = C1RXFUL2 = C1RXOVF1 = C1RXOVF2 = 0x0000; // 清除中断状态信息
C1TR01CONbits.TXEN0 = 1; /* ECAN1, Buffer 0 is a Transmit Buffer */ // 设置第0个缓存用于数据发送
C1TR01CONbits.TXEN1 = 0; /* ECAN1, Buffer 1 is a Receive Buffer */ // 设置第1个缓存用于数据接收
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 0 Priority Level */
C1TR23CONbits.TX3PRI = 0b11; /* Message Buffer 1 Priority Level */

  

6. 操作模式说明。例子文件中都已经做好相关的设置,不需要要修改,可参考文档说明帮助理解
// ECAN 的配置寄存器修改时,需要先进入 配置操作模式,切换操作模式的 语句如下
/* Request Configuration Mode */
C1CTRL1bits.REQOP = 4;
while( C1CTRL1bits.OPMODE != 4 );


/* ... configuration setting ...*/


// 回到正常操作模式
/* Enter Normal Mode */
C1CTRL1bits.REQOP = 0;
while( C1CTRL1bits.OPMODE != 0 );

 

7. 类似的,滤波器设置时,需要设置 `C1CTRL1bits.WIN = 1;`,在`ecan1_drv.c` 文件中可以看到

 

(3)发送ECAN数据
/ 初始化
Ecan1Init();
    DMA0Init();
    DMA2Init();


    /* 开启中断 Enable ECAN1 Interrupt */
    IEC2bits.C1IE = 1;
    C1INTEbits.TBIE = 1;
    C1INTEbits.RBIE = 1;


// 调用 ecan1_drv.c 文件的函数,将数据按照 ECAN 的缓存格式填写到外部变量
// Ecan1WriteTxMsgBufId( 0, 0x1FFEFFFF, 1, 0 ); //发送扩展帧数据
    Ecan1WriteTxMsgBufId( 0, 0x0000666, 0, 0 ); //发送标准帧数据,注意这里的第一个参数是缓存的编号,需要将对应的 C1TR01CONbits.TXEN0 设置为1
Ecan1WriteTxMsgBufData( 0, 8, 0x1111, 0x2222, 0x3333, 0x4444 ); //
 
    C1TR01CONbits.TXREQ0 = 0x1; // 设置发送数据请求,
    while(C1TR01CONbits.TXREQ0 == 0x1);  // 等待数据发送完成

 

(4)数据接收. 数据接收在中断中处理
void __attribute__ ( (interrupt, no_auto_psv) ) _C1Interrupt( void )
{
// _LEDRED = ~_LEDRED;
IFS2bits.C1IF = 0; // clear interrupt flag
if( C1INTFbits.TBIF ) // 数据发送中断
{
C1INTFbits.TBIF = 0;
}


if( C1INTFbits.RBIF ) //数据接收中断
{
// read the message
if( C1RXFUL1bits.RXFUL1 == 1 ) // 因为前面将buffer1设置为数据接收的buffer,所以这里检查buffer1对应的状态位
{
rx_ecan1message.buffer = 1;
C1RXFUL1bits.RXFUL1 = 0;
}


RxECAN1( &rx_ecan1message ); // 读取数据
C1INTFbits.RBIF = 0;
}
// _LEDRED = ~_LEDRED;
}

 

posted @ 2019-05-16 08:45  BH78  阅读(1821)  评论(2编辑  收藏  举报