📄 candsp.c
字号:
////////////////////////////////////////////////////////////////////
//File: CanDSP.c
//Designed by: Xiaofei Qin
//Device type: TMS320LF2407
//Date: 2008-09-17
/////////////////////////////////////////////////////////////////////
#include "2407c.h"
#include "CanDSP.h"
#include "mydatatype.h"
/***************Variables Definition*******************/
UINT DSPCanRX0Buf[9];
UINT DSPCanRX3Buf[9];
UINT DSPCanTXBuf[8];
UINT DSPCanRX0FIFO[DSPRXFIFODEPTH][9]; //RX0的接收fifo
//每帧的第9字节用来存放此帧的字节个数
UINT DSPCanRX0FIFONEFlag=0; //RX0接收fifo非空标志
UINT DSPCanRX0FIFOHead=0; //RX0fifo的头
UINT DSPCanRX0FIFOTail=0; //RX0fifo的尾
UINT DSPCanRX3FIFO[DSPRXFIFODEPTH][9]; //RX3的接收fifo
//每帧的第9字节用来存放此帧的字节个数
UINT DSPCanRX3FIFONEFlag=0; //RX3接收fifo非空标志
UINT DSPCanRX3FIFOHead=0; //RX3fifo的头
UINT DSPCanRX3FIFOTail=0; //RX3fifo的尾
UINT DSPCanFramBuf[9]; //帧弹出时的临时缓冲器
/*****************Functions Definition*********************/
//DSP的CAN模块初始化函数
//此函数只支持标准ID(11bits),不支持扩展ID
//该函数将RB0与RB3用来接收,将RB4,RB5用来发送,RB1,2未用
//波特率设置为125k
//参数1:接收邮箱RB0的SID屏蔽器
//参数2:接收邮箱RB0的SID
//参数3:接收邮箱RB3的SID屏蔽器
//参数4:接收邮箱RB3的SID
//参数5:波特率(50-50k,100-100k,250-250k,500-500k,1000-1M,others-100k)
//!!注意!!DSPCAN的mask与mcp2515的mask逻辑上是反的
UINT DSPCan_Init(UINT SIDmask0,UINT SIDRb0,UINT SIDmask1,UINT SIDRb3,UINT bitrate)
{
UINT mytimer=0;
UINT tmout=3000;
UINT temp;
(*MCRB)|=0x00c0; //设置IOPC6、IOPC7为CANRX,CANTX
(*CANIFR)|=0x007f; //清所有CAN中断标志
(*CANTCR)|=0xff00;
(*CANRCR)|=0xf0f0;
temp=(SIDmask0<<2);
temp|=0x0003;
(*CANLAM0H)=temp; //设置接收邮箱0(1)的屏蔽ID寄存器
(*CANLAM0L)=0xffff;
temp=(SIDmask1<<2);
temp|=0x0003;
(*CANLAM1H)=temp; //设置接收邮箱2(3)的屏蔽ID寄存器
(*CANLAM1L)=0xffff;
mytimer=tmout;
*CANMCR=0x1000; //CCR=1改变配置请求
while(((*CANGSR)&0x0010)==0)//只有当CCE=1时可配置BCR2、BCR1寄存器
{
mytimer--;
if(mytimer==0)
return 1; //超时
}
switch(bitrate)
{
case 50:
//波特率50kb/s
*CANBCR2=0x0027;//波特率预分频寄存器 (RBP+1)=39+1=40
*CANBCR1=0x005e;//波特率设置为50K=40M/40/20 bittime=(11+1)+(6+1)+1=20
break;
case 100:
//波特率100kb/s
*CANBCR2=0x0013;//波特率预分频寄存器 (RBP+1)=19+1=20
*CANBCR1=0x005e;//波特率设置为100K=40M/20/20 bittime=(11+1)+(6+1)+1=20
break;
case 250:
//波特率250kb/s
*CANBCR2=0x0007;//波特率预分频寄存器 (RBP+1)=7+1=8
*CANBCR1=0x005e;//波特率设置为250K=40M/8/20 bittime=(11+1)+(6+1)+1=20
break;
case 500:
//波特率500kb/s
*CANBCR2=0x0003;//波特率预分频寄存器 (RBP+1)=3+1=4
*CANBCR1=0x005e;//波特率设置为500K=40M/4/20 bittime=(11+1)+(6+1)+1=20
break;
case 1000:
//波特率1000kb/s
*CANBCR2=0x0001;//波特率预分频寄存器 (RBP+1)=1+1=2
*CANBCR1=0x005e;//波特率设置为1000K=40M/2/20 bittime=(11+1)+(6+1)+1=20
break;
default:
//波特率100kb/s
*CANBCR2=0x0013;//波特率预分频寄存器 (RBP+1)=19+1=20
*CANBCR1=0x005e;//波特率设置为100K=40M/20/20 bittime=(11+1)+(6+1)+1=20
break;
}
(*CANMCR)&=0xefff; //CCR=0改变配置结束请求
mytimer=tmout;
while(((*CANGSR)&0x0010)==1)//只有当CCE=0时BCR2、BCR1寄存器配置成功
{
mytimer--;
if(mytimer==0)
return 1; //超时
}
/*接收邮箱0初始化*/
*CANMDER=0x0000; //不使能邮箱
*CANMCR=0x0100; //CDR=1,数据区改变请求
temp=(SIDRb0<<2)&0x1ffc;
temp|=0x4000; //设置邮箱0的控制字及ID
*CANMSGID0H=temp; //IDE=0(标准帧),AME=1(使能接收mask),AAM=0(不自动回复远程帧)
*CANMSGID0L=0xffff;
/* *CANMSGCTRL0=0x00; //设置控制域,数据长度DCL=0 非远程帧
*CANMBX0A = 0x0000;
*CANMBX0B = 0x0000;
*CANMBX0C = 0x0000;
*CANMBX0D = 0x0000;*/
/*接收邮箱3初始化*/
*CANMDER=0x0000; //不使能邮箱
*CANMCR=0x0100; //CDR=1,数据区改变请求
temp=(SIDRb3<<2)&0x1ffc;
temp|=0x4000; //设置邮箱3的控制字及ID
*CANMSGID3H=temp; //IDE=0(标准帧),AME=1(使能接收mask),AAM=0(不自动回复远程帧)
*CANMSGID3L=0xffff;
/* *CANMSGCTRL3 = 0x00; //设置控制域,数据长度DCL=4 非远程帧
*CANMBX3A = 0x0000;
*CANMBX3B = 0x0000;
*CANMBX3C = 0x0000;
*CANMBX3D = 0x0000;*/
/*发送邮箱4初始化*/
*CANMDER=0x0000; //不使能邮箱
*CANMCR=0x0100; //CDR=1,数据区改变请求
*CANMSGID4H=0;
*CANMSGID4L=0;
*CANMSGCTRL4=0;
*CANMBX4A=0xff;
*CANMBX4B=0xff;
*CANMBX4C=0xff;
*CANMBX4D=0xff;
/*发送邮箱5初始化*/
*CANMDER=0x0000; //不使能邮箱
*CANMCR=0x0100; //CDR=1,数据区改变请求
*CANMSGID5H=0;
*CANMSGID5L=0;
*CANMSGCTRL5=0;
*CANMBX5A=0xff;
*CANMBX5B=0xff;
*CANMBX5C=0xff;
*CANMBX5D=0xff;
*CANMCR=0x0480; //DBO=1,CDR=0,ABO=1,STM=0正常工作模式
*CANMDER=0x00b9; //ME0=ME3=ME4=ME5=1,邮箱3接收,邮箱2发送
(*CANIFR)|=0x007f; //清所有CAN中断标志
(*CANTCR)|=0xff00;
(*CANRCR)|=0xf0f0;
*CANIMR=0x8984; //邮箱3,0接收中断使能,总线关闭中断使能,低中断优先级
// *CANIMR=0xbfff;
(*IFR)|=0x10; /*清INT5中断标志*/
(*IMR)|=0x10; /*开INT5中断*/
return 0;
}
void interrupt dspcanisr()//CANdsp中断ISR
{
int i;
UINT piv;
piv=*PIVR;
switch(piv)
{
case 0x40:
/*MB0 接收数据准备好*/
if(((*CANIFR)&0x0100)==0x0100)
{
/*数据放入缓冲区*/
DSPCanRX0Buf[8]=(*CANMSGCTRL0)&0x000f;
for(i=0;i<4;i++)
{
DSPCanRX0Buf[i*2]=(*(CANMBX0A+i))&0x00ff;
DSPCanRX0Buf[i*2+1]=((*(CANMBX0A+i))>>8)&0x00ff;
}
/*向RMP0写1清除RMP0(中断标志位MIF0)*/
(*CANRCR)|=0x0010;
PushDSPCanRX0FIFO();
}
/*MB3 接收数据准备好*/
if(((*CANIFR)&0x0800)==0x0800)
{
/*数据放入缓冲区*/
DSPCanRX3Buf[8]=(*CANMSGCTRL3)&0x000f;
for(i=0;i<4;i++)
{
DSPCanRX3Buf[i*2]=(*(CANMBX3A+i))&0x00ff;
DSPCanRX3Buf[i*2+1]=((*(CANMBX3A+i))>>8)&0x00ff;
}
/*向RMP3写1清除RMP3(中断标志位MIF3)*/
(*CANRCR)|=0x0080;
PushDSPCanRX3FIFO();
}
break;
case 0x41:
/*Can总线关闭*/
if(((*CANIFR)&0x0004)==0x0004)
{
/*向CANIFR写1清除BOIF*/
(*CANIFR)|=0x0004;
}
break;
default:
break;
}
asm(" CLRC INTM");
}
//DSPCAN发送函数
//参数1:发送缓冲器编号
//参数2:目标ID
//参数3:是否远程帧
//参数4:发送字节数
//参数5:指向待发送的数据
void DSPCan_TxFun(UINT TxBNO,UINT SID,UINT RemoteF,UINT DLC,UINT *pbuf)
{
int i,j;
UINT IDtemp,Ctltemp,TCRtemp;
UINT mytimer=0;
UINT tmout=30000;
if(DLC>8)
DLC=8;
IDtemp=(SID<<2)&0x1ffc;
RemoteF=(RemoteF<<4)&0x0010;
if(RemoteF!=0)
DLC=0;
Ctltemp=RemoteF|DLC;
switch(TxBNO)
{
case 4:
TCRtemp=(*CANTCR);
while(TCRtemp&0x0040)
{
mytimer++;
if(mytimer>tmout)
{
i++;
return;
}
TCRtemp=(*CANTCR);
}
(*CANMDER)&=0xffef; //不使能邮箱4
(*CANMCR)|=0x0100; //CDR=1,数据改变请求
(*CANMSGID4H)=IDtemp;
(*CANMSGID4L)=0;
(*CANMSGCTRL4)=Ctltemp;
for(i=0;i<DLC;i++) //邮箱4中数据更新
{
j=(i>>1)&0x000f;
if(i&0x0001)
{
(*(CANMBX4A+j))&=0x00ff;
(*(CANMBX4A+j))|=(((pbuf[i])<<8)&0xff00);
}
else
{
(*(CANMBX4A+j))&=0xff00;
(*(CANMBX4A+j))|=((pbuf[i])&0x00ff);
}
}
(*CANMDER)|=0x0010; //使能邮箱4
(*CANMCR)&=0xfeff; //CDR=0
(*CANTCR)|=0x0040; //请求发送
break;
case 5:
TCRtemp=(*CANTCR);
while(TCRtemp&0x0080)
{
mytimer++;
if(mytimer>tmout)
{
i++;
return;
}
TCRtemp=(*CANTCR);
}
(*CANMDER)&=0xffdf; //不使能邮箱5
(*CANMCR)|=0x0100; //CDR=1,数据改变请求
(*CANMSGID5H)=IDtemp;
(*CANMSGID5L)=0;
(*CANMSGCTRL5)=Ctltemp;
for(i=0;i<DLC;i++) //邮箱4中数据更新
{
j=(i>>1)&0x000f;
if(i&0x0001)
{
(*(CANMBX5A+j))&=0x00ff;
(*(CANMBX5A+j))|=(((pbuf[i])<<8)&0xff00);
}
else
{
(*(CANMBX5A+j))&=0xff00;
(*(CANMBX5A+j))|=((pbuf[i])&0x00ff);
}
}
(*CANMDER)|=0x0020; //使能邮箱5
(*CANMCR)&=0xfeff; //CDR=0
(*CANTCR)|=0x0080; //请求发送
break;
default:
break;
}
}
//向RX0fifo压入一帧
void PushDSPCanRX0FIFO()
{
int i;
DSPCanRX0FIFOHead++;
if(DSPCanRX0FIFOHead>=DSPRXFIFODEPTH)
DSPCanRX0FIFOHead=0;
if(DSPCanRX0FIFOHead==DSPCanRX0FIFOTail)//缓冲区满,覆盖最早的帧
{
DSPCanRX0FIFOTail++;
if(DSPCanRX0FIFOTail>=DSPRXFIFODEPTH)
DSPCanRX0FIFOTail=0;
}
DSPCanRX0FIFO[DSPCanRX0FIFOHead][8]=DSPCanRX0Buf[8];
for(i=0;i<DSPCanRX0FIFO[DSPCanRX0FIFOHead][8];i++)
{
DSPCanRX0FIFO[DSPCanRX0FIFOHead][i]=DSPCanRX0Buf[i];
}
DSPCanRX0FIFONEFlag=1;
}
//向RX3fifo压入一帧
void PushDSPCanRX3FIFO()
{
int i;
DSPCanRX3FIFOHead++;
if(DSPCanRX3FIFOHead>=DSPRXFIFODEPTH)
DSPCanRX3FIFOHead=0;
if(DSPCanRX3FIFOHead==DSPCanRX3FIFOTail)//缓冲区满,覆盖最早的帧
{
DSPCanRX3FIFOTail++;
if(DSPCanRX3FIFOTail>=DSPRXFIFODEPTH)
DSPCanRX3FIFOTail=0;
}
DSPCanRX3FIFO[DSPCanRX3FIFOHead][8]=DSPCanRX3Buf[8];
for(i=0;i<DSPCanRX3FIFO[DSPCanRX3FIFOHead][8];i++)
{
DSPCanRX3FIFO[DSPCanRX3FIFOHead][i]=DSPCanRX3Buf[i];
}
DSPCanRX3FIFONEFlag=1;
}
//从RX0fifo弹出一帧到指定位置
//参数1:指向弹出帧的存储位置
void PopDSPCanRX0FIFO(UINT *pbuf)
{
int i;
if(DSPCanRX0FIFOTail==DSPCanRX0FIFOHead) //缓冲区空
{
DSPCanRX0FIFONEFlag=0;
return;
}
DSPCanRX0FIFOTail++;
if(DSPCanRX0FIFOTail>=DSPRXFIFODEPTH)
DSPCanRX0FIFOTail=0;
pbuf[8]=DSPCanRX0FIFO[DSPCanRX0FIFOTail][8];
for(i=0;i<pbuf[8];i++)
{
pbuf[i]=DSPCanRX0FIFO[DSPCanRX0FIFOTail][i];
}
if(DSPCanRX0FIFOTail==DSPCanRX0FIFOHead) //缓冲区空
{
DSPCanRX0FIFONEFlag=0;
}
}
//从RX3fifo弹出一帧到指定位置
//参数1:指向弹出帧的存储位置
void PopDSPCanRX3FIFO(UINT *pbuf)
{
int i;
if(DSPCanRX3FIFOTail==DSPCanRX3FIFOHead) //缓冲区空
{
DSPCanRX3FIFONEFlag=0;
return;
}
DSPCanRX3FIFOTail++;
if(DSPCanRX3FIFOTail>=DSPRXFIFODEPTH)
DSPCanRX3FIFOTail=0;
pbuf[8]=DSPCanRX3FIFO[DSPCanRX3FIFOTail][8];
for(i=0;i<pbuf[8];i++)
{
pbuf[i]=DSPCanRX3FIFO[DSPCanRX3FIFOTail][i];
}
if(DSPCanRX3FIFOTail==DSPCanRX3FIFOHead) //缓冲区空
{
DSPCanRX3FIFONEFlag=0;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -