基于dsPIC33FJ128MC506的CAN通信
n->
identifier-> 合法的标识符
exide -> 是否扩展数据帧,"0" 表示为标准数据帧,"1"表示为扩展数据帧
bufPnt -> 过滤后的信息存放的缓冲区,范围为[0-15]
maskSel -> 关连的屏蔽寄存器[0-3] */
void ecan1WriteRxAcptFilter(int n, long identifier, unsigned int exide, unsigned int bufPnt, unsigned int maskSel)
{
/*定义局部变量*/
unsigned long sid10_0=0, eid15_0=0, eid17_16=0;
unsigned int *sidRegAddr,*bufPntRegAddr,*maskSelRegAddr, *fltEnRegAddr;
/*因为将要设置的特殊寄存器要与别的寄存器共用地址,所以需设置控制位WIN*/
C1CTRL1bits.WIN=1;
/* 根据输入的参数,计算出相应寄存器的地址,包括滤波器n的地址、缓冲指针寄存器地址、相关的屏蔽寄存器的地址及接收过滤使能寄存器的相关位*/
// 接过过滤寄存器的地址
sidRegAddr = (unsigned int *)(&C1RXF0SID + (n < 1));
//报文缓冲区地址
bufPntRegAddr = (unsigned int *)(&C1BUFPNT1 + ((n >> 2)*2) ) ;
//屏蔽寄存器地址
maskSelRegAddr = (unsigned int *)(&C1FMSKSEL1 + ((n >> 3)*2));
//过滤器使能地址
fltEnRegAddr = (unsigned int *)(&C1FEN1);
/* 将ID按规定分配到相关的寄存器中*/
if(exide==1) { //扩展帧的ID
eid15_0 = (identifier & 0xFFFF);
eid17_16= (identifier>>16) & 0x3;
sid10_0 = (identifier>>18) & 0x7FF;
*sidRegAddr=(sid10_0)<5 + 0x8 + eid17_16;
*(sidRegAddr+2)= eid15_0;
}else{ //标准帧的ID
sid10_0 = (identifier & 0x7FF);
*sidRegAddr=(sid10_0)<5;
*(sidRegAddr+2)=0;
}
*bufPntRegAddr = (bufPnt < (4*(n&3))); // 写缓冲指针寄存器CiBUFPNTn内容*maskSelRegAddr = (maskSel < (2*(n&7))); // 确定关连屏蔽寄存器
CiFMSKSELn *fltEnRegAddr = (0x1 < n); //使能第n个滤波器
C1CTRL1bits.WIN=0; //恢复寄存器地址选择位
}
/*
下面的函数用来写接收屏蔽寄存器"m" ,各输入参数的意义分别为:
m-> 屏蔽寄存器号[0-3]
identifier->屏蔽位
mide -> "0" 表示无论是标准帧还是扩展帧,屏蔽器都起作用
"1" 表示屏蔽器是否起作用要参照'exide' 位 */
void ecan1WriteRxAcptMask(int m, long identifier, unsigned int mide)
{
/*定义局部变量*/
unsigned long sid10_0=0, eid15_0=0, eid17_16=0;
unsigned int *maskRegAddr;
//因为将要设置的特殊寄存器要与别的寄存器共用地址,所以需设置控制位WIN
C1CTRL1bits.WIN=1;
/* 根据"m"计算出CiRXMmSID 寄存器的地址*/
maskRegAddr = (unsigned int *)(&C1RXM0SID + (m < 2));
/* 将屏敝ID写入到屏蔽寄存器中*/
if(mide==1) { //扩展帧格式
eid15_0 = (identifier & 0xFFFF);
eid17_16= (identifier>>16) & 0x3;
sid10_0 = (identifier>>18) & 0x7FF;
*maskRegAddr=(sid10_0)<5 + 0x8 + eid17_16;
*(maskRegAddr+2)= eid15_0;
}else{ // 标准帧格式
sid10_0 = (identifier & 0x7FF);
*maskRegAddr=(sid10_0)<5; *(maskRegAddr+2)=0;
}
C1CTRL1bits.WIN=0;
}
TJA1054的启动
TJA1054是广泛应用的低速容错CAN收发器,其工作启动要按照其说明进行,下面的函数将TJA1054初始化为工作状态。
void TJA1054Init (void)
{
TRISBbits.TRISB15=1; //将错误引脚设为输入状态
TRISEbits.TRISE4=0; //将EN引脚设为输出状态
TRISEbits.TRISE5=0; //将STB引脚设为输出状态
PORTEbits.RE5=1; //STB=0;
PORTEbits.RE4=0; //EN=1
PORTEbits.RE5=1; //STB=1;
PORTEbits.RE4=1; //EN=1
}
结合以上内容,ECAN1的初始化函数为:
void ecan1Init(void)
{
C1CTRL1bits.REQOP=4;
while(C1CTRL1bits.OPMODE!=4); //请求进入配置模式
ecan1ClkInit(); //调用波特率设置函数
C1FCTRLbits.DMABS=0b000; //在DMA RAM 中设置4个CAN报文缓冲
ecan1WriteRxAcptFilter(1,0x36,0,2,0); //配置接过收滤寄存器
/*配置接收屏蔽寄存器,要注意的是,这里设为“1”的位是非屏蔽位,设为“0”的位为屏蔽位。这里的0x7FF将会对标准帧ID的每一位都进行检查是否对应的过滤器相匹配*/
ecan1WriteRxAcptMask(0,0x7ff,0);
C1CTRL1bits.REQOP=0;
while(C1CTRL1bits.OPMODE!=0); //进入正常模式
/*以下语句设置CAN报文的发射接收控制*/
C1RXFUL1=C1RXFUL2=C1RXOVF1=C1RXOVF2=0x0000;
C1TR01CONbits.TXEN0=1; /*ECAN1的0缓冲器为发射缓冲 */
C1TR01CONbits.TXEN1=0; /* ECAN1的1缓冲器为接收缓冲 */
C1TR01CONbits.TX0PRI=0b11; /* 发射缓冲的优先级*/
}
数据的发射和接收
写报文ID
下面的函数将一个报文ID写到ECAN1的发射缓冲区,其中各个参数代表
CAN TJA1054 dsPIC33FJ128MC506 相关文章:
- CAN网络-其特性阻抗及终端阻抗 (04-29)
- 解读CAN总线行车记录仪系统电路(06-04)
- 为什么要使用CAN总线?(05-31)
- 基于CAN总线的智能家居安防系统设计(10-11)
- 如果CAN总线中节点ID相同会怎样?(08-31)
- CAN通信协议在矿井安全生产监控系统中的应用(09-27)