Minmin Zhengzheng

can't send data about 1 in TWR-K60F120

Discussion created by Minmin Zhengzheng on Sep 25, 2017
Latest reply on Sep 26, 2017 by Minmin Zhengzheng

everyone:

    I am learning CAN Module.This is my program.when it is debugged, the flag about sending data doesn't be equal to 1.So it can't be sent successfully.

main.c:

CANInit(can be initialized):

uint8 CANInit(uint8 CANChannel,uint32 baudrateKHz,uint8 selfLoop,uint8 idMask)
{
int8 i;
CAN_MemMapPtr CANBaseAdd;

//使能FlexCAN外部时钟
OSC0_CR |= OSC_CR_ERCLKEN_MASK | OSC_CR_EREFSTEN_MASK;//*晶振提供外部时钟

//通过模块号选择模块基地址
if(CANChannel == 0)
CANBaseAdd = CAN0_BASE_PTR;
else if(CANChannel == 1)
CANBaseAdd = CAN1_BASE_PTR;

//使能CAN模块时钟
if(CANBaseAdd == CAN0_BASE_PTR)
SIM_SCGC6 |= SIM_SCGC6_FLEXCAN0_MASK;//使能CAN0的时钟模块
else
SIM_SCGC3 |= SIM_SCGC3_FLEXCAN1_MASK;//使能CAN1的时钟模块
/*
//使能CAN中断
if(CANChannel == 0)//使能CAN0的中断
{
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中断
}
else //使能CAN1的中断
{
NVICICPR1 = (NVICICPR1 & ~(0xFF<<5)) | (0xFF<<5);//清除挂载在FlexCAN1的中断
NVICISER1 = (NVICISER1 & ~(0xFF<<5)) | (0xFF<<5);//使能FlexCAN1中断
}
*/
//配置CAN_RX/TX复用引脚功能
if(CANChannel == 0)
{
PORTE_PCR24 = PORT_PCR_MUX(2) | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK; //上拉 *PORT PCR寄存器的设置
PORTE_PCR25 = PORT_PCR_MUX(2) | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK; //上拉
}
else
{
PORTC_PCR17 = PORT_PCR_MUX(2) | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK; //Tx上拉
PORTC_PCR16 = PORT_PCR_MUX(2) | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK; //Rx上拉
}
//选择时钟源,外设时钟48MHz,内部时钟:12MHz
CAN_CTRL1_REG(CANBaseAdd) |= CAN_CTRL1_CLKSRC_MASK;//选择内部时钟
// CAN_CTRL1_REG(CANBaseAdd) &=~CAN_CTRL1_CLKSRC_MASK;//应该是外部时钟源吧?

CAN_MCR_REG(CANBaseAdd) |= CAN_MCR_FRZ_MASK; //使能冻结模式
CAN_MCR_REG(CANBaseAdd) &= ~CAN_MCR_MDIS_MASK;//使能CAN模块
//确认已退出冻结模式
while((CAN_MCR_LPMACK_MASK & CAN_MCR_REG(CANBaseAdd)));
//软件复位
CAN_MCR_REG(CANBaseAdd) ^= CAN_MCR_SOFTRST_MASK;
//等待复位完成
while(CAN_MCR_SOFTRST_MASK & CAN_MCR_REG(CANBaseAdd));
//等待进入冻结模式
while(!(CAN_MCR_FRZACK_MASK & CAN_MCR_REG(CANBaseAdd)));
// Set local priority
CAN_MCR_REG(CANBaseAdd)|=CAN_MCR_LPRIOEN_MASK;
//将16个邮箱缓冲区内容清0
for(i=0;i<16;i++)
{
CANBaseAdd->MB[i].CS = 0x00000000;
CANBaseAdd->MB[i].ID = 0x00000000;
CANBaseAdd->MB[i].WORD0 = 0x00000000;
CANBaseAdd->MB[i].WORD1 = 0x00000000;
}
//接收邮箱过滤IDE比较,RTR不比较
CAN_CTRL2_REG(CANBaseAdd) &= ~CAN_CTRL2_EACEN_MASK;//0 Rx Mailbox filter’s IDE bit is always compared and RTR is never compared despite mask bits.
//远程请求帧产生
CAN_CTRL2_REG(CANBaseAdd) &= ~CAN_CTRL2_RRS_MASK; //0 Remote Response Frame is generated.
//邮箱首先从接收FIFO队列匹配然后再在邮箱中匹配
CAN_CTRL2_REG(CANBaseAdd) &= ~CAN_CTRL2_MRP_MASK;//0 Matching starts from Rx FIFO and continues on Mailboxes
//使用一个32位过滤器
CAN_MCR_REG(CANBaseAdd) |= (CAN_MCR_REG(CANBaseAdd) & ~CAN_MCR_IDAM_MASK) | CAN_MCR_IDAM(0);
//设置波特率
if(SetCANBand(CANChannel,baudrateKHz) == 1)//若设置错误
return 1;
//模式选择:回环模式或正常模式
//采用正常模式,即注释以下程序
// if(1==selfLoop)
// CAN_CTRL1_REG(CANBaseAdd) |= CAN_CTRL1_LPB_MASK;//使用回环模式

//初始化掩码寄存器
if(1==idMask)//屏蔽ID
{
CAN_RXMGMASK_REG(CANBaseAdd) = 0x1FFFFFFF;
CAN_RX14MASK_REG(CANBaseAdd) = 0x1FFFFFFF;
CAN_RX15MASK_REG(CANBaseAdd) = 0x1FFFFFFF;
}
else//不屏蔽ID
{
CAN_RXMGMASK_REG(CANBaseAdd) = 0x0;
CAN_RX14MASK_REG(CANBaseAdd) = 0x0;
CAN_RX15MASK_REG(CANBaseAdd) = 0x0;
}

//如果单独掩码功能使能,为每个队列初始化单独的掩码寄存器
if(CAN_MCR_REG(CANBaseAdd) & CAN_MCR_IRMQ_MASK)
{
for(i = 0; i < NUMBER_OF_MB ; i++)
{
CANBaseAdd->RXIMR[i] = 0x1FFFFFFFL;
}
}
//只有在冻结模式下才能配置,配置完推出冻结模式
CAN_MCR_REG(CANBaseAdd) &= ~(CAN_MCR_HALT_MASK);
//等待直到退出冻结模式
while( CAN_MCR_REG(CANBaseAdd) & CAN_MCR_FRZACK_MASK);
//等到不在冻结模式,休眠模式或者停止模式
while((CAN_MCR_REG(CANBaseAdd) & CAN_MCR_NOTRDY_MASK));
return 0;
}

 

CANSendData(SendData)

uint8 CANSendData(uint8 CANChannel,uint16 iMB, uint32 id,uint8 length,uint8 Data[])
{
int16 i,wno,bno;
uint32 word[2] = {0};
CAN_MemMapPtr CANBaseAdd;

if(CANChannel == 0)
CANBaseAdd = CAN0_BASE_PTR;
else if(CANChannel == 1)
CANBaseAdd = CAN1_BASE_PTR;

//缓冲区和数据长度设置错误
if(iMB >= NUMBER_OF_MB || length >8)
return 1; //超出范围

//转换8个字节转换成32位的word存储
wno = (length-1)>>2;//是否超过4字节
bno = (length-1)%4; //
if(wno > 0) //长度大于4(即发送数据超过4字节)
{
word[0] = (
(Data[0]<<24)
| (Data[1]<<16)
| (Data[2]<< 8)
| Data[3]
);
}
for(i=0;i<=bno;i++)
word[wno] |= Data[(wno<<2)+i] << (24-(i<<3));

///////////////////////////////////////////////////////
// ID 格式
// B31 30 29 28 27 26 ... 11 10 9 8 7 6 5 4 3 2 1 0
// | | | |
// | | |------------------------------------|
// | | |--> 29 位 ID
// | |
// | |--> RTR 1: 远程帧, 0: 数据帧
// |
// |-------> IDE 1 : 扩展ID, 0: 标准ID
///////////////////////////////////////////////////////

//通过id判断帧类型——扩展帧
wno = (id & CAN_MSG_IDE_MASK)>>CAN_MSG_IDE_BIT_NO; //IDE
//通过id判断帧类型——远程帧
bno = (id & CAN_MSG_TYPE_MASK)>>CAN_MSG_TYPE_BIT_NO;//RTR

//获得ID位数
i = wno? 0: FLEXCAN_MB_ID_STD_BIT_NO;

//以下四步骤为发送过程
CANBaseAdd->MB[iMB].CS = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_INACTIVE)//缓冲区写激活代码
| (wno<<FLEXCAN_MB_CS_IDE_BIT_NO)//缓冲区写IDE位
| (bno<<FLEXCAN_MB_CS_RTR_BIT_NO)//缓冲区写RTR位
| FLEXCAN_MB_CS_LENGTH(length); //缓冲区写数据长度

//缓冲区写ID
CANBaseAdd->MB[iMB].ID = (1 << FLEXCAN_MB_ID_PRIO_BIT_NO) //传输的优先级
| ((id & ~(CAN_MSG_IDE_MASK|CAN_MSG_TYPE_MASK))<<i);

//缓冲区写内容
CANBaseAdd->MB[iMB].WORD0 = word[0];
CANBaseAdd->MB[iMB].WORD1 = word[1];

//延迟
for(i = 0;i < 100;i++);

//通过制定的发送代码开始发送
CANBaseAdd->MB[iMB].CS = (CANBaseAdd->MB[iMB].CS & ~(FLEXCAN_MB_CS_CODE_MASK))
| FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_ONCE);//写激活代码


//限时等待发送完成(如果使用中断则限时等待语句可删除)
i=0;

GPIOA_PTOR|=GPIO_PDOR_PDO(GPIO_PIN(29));//指示灯的亮、暗状态切换
while(!(CANBaseAdd->IFLAG1 & (1<<iMB)))
{
if((i++)>0x1000)
return 1;
}
//清报文缓冲区中断标志

CANBaseAdd->IFLAG1 = (1<<iMB);
GPIOA_PTOR&=~GPIO_PDOR_PDO(GPIO_PIN(28));//指示灯的亮、暗状态切换
return 0;

}

Outcomes