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
}
微信公众号内有其他嵌入式学习经验分享。需要朋友们可以关注下微信公众号
如有相关嵌入式学习问题或疑问,欢迎在微信公众号留言.