在线时间2 小时
UID3420125
注册时间2017-9-2
NXP金币0
该用户从未签到
新手上路

- 积分
- 17
- 最后登录
- 2017-11-22
|
void CANInit(void){
UInt8 i;
// CAN0BaseAdd=CAN0_BASE_PTR;
OSC_CR=0x80|0x02; //使能CAN外部时钟
SIM_SCGC6|=0x10; //使能CAN0的时钟模块
// SIM_SCGC3|=0x10; //使能CAN1的时钟模块
NVICICPR0 = (NVICICPR0 & ~(0x07<<29)) | (0x07<<29);//清除挂载在FlexCAN0的中断
NVICISER0 = (NVICISER0 & ~(0x07<<29)) | (0x07<<29);//使能FlexCAN0中断
NVICICPR1 = (NVICICPR1 & ~(0x1F<<0)) | (0x1F);//清除挂载在FlexCAN0的中断
NVICISER1 = (NVICISER1 & ~(0x1F<<0)) | (0x1F);//使能FlexCAN0中断
// NVICICPR1 = (NVICICPR1 & ~(0xFF<<5)) | (0xFF<<5);//清除挂载在FlexCAN1的中断
// NVICISER1 = (NVICISER1 & ~(0xFF<<5)) | (0xFF<<5);//使能FlexCAN1中断
PORTB_PCR18 = 0X0203;//使能CAN0TX 使能上拉
PORTB_PCR19 =0X0203 ; //使能CAN0RX 使能上拉
//选择时钟源,外设时钟48MHz,内部时钟:12MHz
CAN0_CTRL1|=0x00002000;
CAN0_MCR |= CAN_MCR_FRZ_MASK; //使能冻结模式 y
// CAN0_MCR|=0x40000000;
CAN0_MCR&= ~CAN_MCR_MDIS_MASK;//使能CAN模块 y
// CAN0_MCR&=0x7FFFFFFF;
//确认已退出冻结模式
while((CAN_MCR_LPMACK_MASK & CAN0_MCR));// (((CAN_MCR) >> (20)) & 1)
// while((CAN0_MCR >> 20) & 1);
//软件复位
CAN0_MCR ^= CAN_MCR_SOFTRST_MASK;
//等待复位完成
while(CAN_MCR_SOFTRST_MASK & CAN0_MCR);
// while((CAN0_MCR >> 25) & 1); //(CAN0_MCR >> 25) & 1
//等待进入冻结模式
// while(!((CAN0_MCR >> 24) & 1));//(CAN0_MCR >> 24) & 1
while(!(CAN_MCR_FRZACK_MASK & CAN0_MCR));
//将16个邮箱缓冲区内容清0
for(i=0;i<16;i++)
{
CAN0_BASE_PTR->MB.CS = 0x00000000;
CAN0_BASE_PTR->MB.ID = 0x00000000;
CAN0_BASE_PTR->MB.WORD0 = 0x00000000;
CAN0_BASE_PTR->MB.WORD1 = 0x00000000;
}
CAN0_MCR |= CAN_MCR_SRXDIS_MASK; //禁止自发自收
//配置相关的寄存器
CAN0_CTRL2 &= ~CAN_CTRL2_EACEN_MASK; //接收邮箱过滤IDE匹配,RTR不匹配
CAN0_CTRL2&= ~CAN_CTRL2_RRS_MASK; //不自动产生远程请求帧产生
CAN0_CTRL2 &= ~CAN_CTRL2_MRP_MASK; //ID首先从邮箱中匹配
//canx->CTRL1 |= CAN_CTRL1_LBUF_MASK; //发送的时候从低Msg开始
// CAN0_CTRL1 &= ~CAN_CTRL1_LBUF_MASK; //发送的时候从低优先级发送
CAN0_CTRL1&= ~CAN_CTRL1_LPB_MASK; //使用正常模式
SetCANBand(250);
// CAN0_CTRL1=CAN0_CTRL1|(0<<12); //使用正常模式
////不屏蔽ID
CAN0_RXMGMASK=0x0;
CAN0_RX14MASK=0x0;
CAN0_RX15MASK=0x0;
CAN0_MCR &=~( CAN_MCR_HALT_MASK); //0x10000000u
//等待直到退出冻结模式
while( CAN0_MCR& CAN_MCR_FRZACK_MASK);
//等到不在冻结模式,休眠模式或者停止模式
while((CAN0_MCR & CAN_MCR_NOTRDY_MASK));
}
UInt8 SetCANBand(UInt32 baudrateKHz)
{
switch (baudrateKHz)
{
case (250):
if(CAN0_CTRL1 & CAN_CTRL1_CLKSRC_MASK)
{
// 48M/(PRESDIV+1)= 3M sclock, 12Tq=(1+(PSEG1+1)+(PSEG2+1)+(PROPSEG+1))
//波特率=3M/12=250K
// PROPSEG = 3, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 1
// RJW = 2, PSEG1 = 4, PSEG2 = 4, PRESDIV = 16
CAN0_CTRL1 = (0 | CAN_CTRL1_PROPSEG(2)
| CAN_CTRL1_RJW(1)
| CAN_CTRL1_PSEG1(3)
| CAN_CTRL1_PSEG2(3)
| CAN_CTRL1_PRESDIV(15));
}
else
{
// 12M/4= 3M sclock, 12Tq
// PROPSEG = 3, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 1
// RJW = 2, PSEG1 = 4, PSEG2 = 4, PRESDIV = 4
CAN0_CTRL1= (0 | CAN_CTRL1_PROPSEG(2)
| CAN_CTRL1_RJW(1)
| CAN_CTRL1_PSEG1(3)
| CAN_CTRL1_PSEG2(3)
| CAN_CTRL1_PRESDIV(3));
}
break;
case (500):
if(CAN0_CTRL1 & CAN_CTRL1_CLKSRC_MASK)
{
// 48M/8=6M sclock, 12Tq
// PROPSEG = 3, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 1
// RJW = 2, PSEG1 = 4, PSEG2 = 4, PRESDIV = 6
CAN0_CTRL1 = (0 | CAN_CTRL1_PROPSEG(2)
| CAN_CTRL1_RJW(1)
| CAN_CTRL1_PSEG1(3)
| CAN_CTRL1_PSEG2(3)
| CAN_CTRL1_PRESDIV(7));
}
else
{
// 12M/2=6M sclock, 12Tq
// PROPSEG = 3, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 1
// RJW = 2, PSEG1 = 4, PSEG2 = 4, PRESDIV = 2
CAN0_CTRL1 = (0 | CAN_CTRL1_PROPSEG(2)
| CAN_CTRL1_RJW(1)
| CAN_CTRL1_PSEG1(3)
| CAN_CTRL1_PSEG2(3)
| CAN_CTRL1_PRESDIV(1));
}
break;
}
}
//此程序可写MB,但发送未完成,程序死在 while(!(CAN0_BASE_PTR->IFLAG1 & (1<<iMB)))循环中
UInt8 CANSendData(UInt16 iMB, UInt32 id,UInt8 length,UInt8 Data[])
{
UInt8 i;
UInt16 j;
//以下四步骤为发送过程
CAN0_BASE_PTR->MB[iMB].CS = ( (0x08&0x0000000F)<<24)//缓冲区写激活代码
| (1<<21)//缓冲区写IDE位
| (0<<20)//缓冲区写RTR位
|((length&0x0000000F)<<16); //缓冲区写数据长度
//缓冲区写ID
CAN0_BASE_PTR->MB[iMB].ID = (1 <<30) | id;
//缓冲区写内容
CAN0_BASE_PTR->MB[iMB].WORD0 =(UInt32)((Data[0]<<24)|(Data[1]<<16)|(Data[2]<<8)|Data[3]) ;
CAN0_BASE_PTR->MB[iMB].WORD1 =(UInt32)((Data[4]<<24)|(Data[5]<<16)|(Data[6]<<8)|Data[7]) ;
//延迟
for(i = 0;i < 100;i++);
//通过制定的发送代码开始发送
CAN0_BASE_PTR->MB[iMB].CS = (CAN0_BASE_PTR->MB[iMB].CS & ~(0x0F000000))
| ( (0x0C&0x0000000F)<<24)//写激活代码
| ((length&0x0000000F)<<16);//缓冲区写数据长度
//限时等待发送完成(如果使用中断则限时等待语句可删除)
while(!(CAN0_IFLAG1 & (1<<iMB)))
{
if((j++)>0x1000)
return 1;
}
//清报文缓冲区中断标志
CAN0_IFLAG1 = (1<<iMB);
return 0;
}
最佳答案
你可以参考TWR-K60D100 的例程包, 也可以参考其对应的KSDK 例程;
KINETIS512_V2_SC:
http://www.nxp.com/products/micr ... ab=Design_Tools_Tab
KSDK:
http://www.nxp.com/support/devel ... 1&pageNum=1
...
|
|