Everyone:
I am learning the CAN module.This is my program.When it is debugged, the flag about sending data doesn't be equal to be 1,so it can't be sent successfully.
main.c:
CANInit(CAN module 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(Send Data)
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;
 
}
 
					
				
		
 Robin_Shen
		
			Robin_Shen
		
		
		
		
		
		
		
		
	
			
		
		
			
					
		Hi Minmin Zhengzheng,
I recommend you refer to the "Typical Usage" of CAN_LDD in KDS3.2 ide , you can find them at here:
Hope it help! Have a nice day.
Best Regards,
Robin
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
----------------------------------------------------------------------------------------------------------------------
 
					
				
		
 Robin_Shen
		
			Robin_Shen
		
		
		
		
		
		
		
		
	
			
		
		
			
					
		Yes. You can use it.
The usage of CAN_LDD is the same. You can create a Processor Expert project and refer that example.
 
					
				
		
 Robin_Shen
		
			Robin_Shen
		
		
		
		
		
		
		
		
	
			
		
		
			
					
		Below information may help you know about the Processor Expert.
video
Processor Expert What You Need to Know
Processor Expert® Code Model (CodeWarrior®) - Code Walkthrough
document:
飞思卡尔单片机快速上手指南 6.2.3 处理器专家(PE)的使用
It's difficult for me to learn the Processor Expert. I am a beginner. The teacher told me to use the CAN module to transimit data immediately instead of learning others. So I program the CAN procedure by myself according to other demo in Codewarrior10.7.Can you help me figure out my program?
 
					
				
		
 Robin_Shen
		
			Robin_Shen
		
		
		
		
		
		
		
		
	
			
		
		
			
					
		 
					
				
		
Hi Minmim
In case of difficulties you can also use the uTasker Open Source project for K60F120 and dual-CAN.
Documented at http://www.utasker.com/docs/uTasker/uTaskerCAN.PDF
Video at https://youtu.be/Ha8cv_XEvco
IDE-independent and requires no code generators or porting.
If you are new to CAN also beware that you need another active node on the CAN bus to correctly send messages - also ensure correct bus terminations.
Regards
Mark
http://www.utasker.com/kinetis.html
http://www.utasker.com/kinetis/TWR-K60F120M.html
hi:
what's the uTasker Open Source project for K60F120? I am useing the Codewarrior 10.7. And the PDF doesn't have complete procedure demo. I am still in trouble.
 
					
				
		
Hi Minmim
The uTasker project includes Codewarrior support - see https://youtu.be/uBbiw36Caq4 which explains how to use it.
Regards
Mark
