コード例 #1
0
//============================================================================
//函数名称:CANInit
//函数返回:0:成功;1:失败
//参数说明:
//         CANChannel:模块号
//		   baudrateKHz: 波特率
//         selfLoop: 模式选择(1=回环模式;0=正常模式)
//         idMask: ID过滤(1=ID过滤;0=ID不过滤)
//功能概要:CAN初始化
//============================================================================
uint8 CANInit(uint8 CANChannel,uint32 baudrateKHz,uint8 selfLoop,uint8 idMask)
{
    int8 i;
    CAN_MemMapPtr CANBaseAdd;
  
    //使能FlexCAN外部时钟
    OSC_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)
    {
		PORTA_PCR12 = PORT_PCR_MUX(2) | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK; //上拉
		PORTA_PCR13 = PORT_PCR_MUX(2) | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK; //上拉
    }
    else
    {
    	PORTE_PCR24 = PORT_PCR_MUX(2) | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK; //Tx上拉
    	PORTE_PCR25 = PORT_PCR_MUX(2) | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK; //Rx上拉
    } 
    
    //选择时钟源,外设时钟48MHz,内部时钟:12MHz
    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)));
    
    //将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;
    //远程请求帧产生
    CAN_CTRL2_REG(CANBaseAdd) &= ~CAN_CTRL2_RRS_MASK;
    //邮箱首先从接收FIFO队列匹配然后再在邮箱中匹配
    CAN_CTRL2_REG(CANBaseAdd) &= ~CAN_CTRL2_MRP_MASK;
 
    //使用一个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;
}
コード例 #2
0
ファイル: can.c プロジェクト: SproutOrc/CH-K-Lib
/***********************************************************************************************
 功能:CAN 初始化
 形参:CAN_InitStruct: CAN 初始化结构
 返回:0
 详解:0
************************************************************************************************/
void CAN_Init(CAN_InitTypeDef* CAN_InitStruct)
{
	uint8_t i = 0;
	PORT_Type *CAN_PORT = NULL;
	CAN_MapTypeDef *pCAN_Map = (CAN_MapTypeDef*)&(CAN_InitStruct->CANxMap);
    CAN_Type  *CANx = NULL;
	//参数检测
	assert_param(IS_FUNCTIONAL_STATE(CAN_InitStruct->FilterEnable));
	assert_param(IS_CAN_MAP(CAN_InitStruct->CANxMap));
	assert_param(IS_CAN_SPEED(CAN_InitStruct->CAN_BaudRateSelect));
	//找出CAN模块 开启CAN模块时钟
	switch(pCAN_Map->CAN_Index )
	{
		case 0:
			SIM->SCGC6 |= SIM_SCGC6_FLEXCAN0_MASK;
			CANx = CAN0;
			break;
		case 1:
			SIM->SCGC3 |= SIM_SCGC3_FLEXCAN1_MASK;
			CANx = CAN1;
			break;
		default:break;     
	}
	//找出对应的PORT
	switch(pCAN_Map->CAN_GPIO_Index)
	{
		case 0:
			SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK;
			CAN_PORT = PORTA;
			break;
		case 1:
			SIM->SCGC5 |= SIM_SCGC5_PORTB_MASK;
			CAN_PORT = PORTB;
			break;
		case 2:
			SIM->SCGC5 |= SIM_SCGC5_PORTC_MASK;
			CAN_PORT = PORTC;
			break;
		case 3:
			SIM->SCGC5 |= SIM_SCGC5_PORTD_MASK;
			CAN_PORT = PORTD;
			break;
		case 4:
			SIM->SCGC5 |= SIM_SCGC5_PORTE_MASK;
			CAN_PORT = PORTE;
			break;
		default:break;
	}
	//开启对应的引脚 
	CAN_PORT->PCR[pCAN_Map->CAN_TX_Pin_Index] &= ~PORT_PCR_MUX_MASK;
	CAN_PORT->PCR[pCAN_Map->CAN_RX_Pin_Index] &= ~PORT_PCR_MUX_MASK;
	CAN_PORT->PCR[pCAN_Map->CAN_TX_Pin_Index] |= PORT_PCR_MUX(pCAN_Map->CAN_Alt_Index);
	CAN_PORT->PCR[pCAN_Map->CAN_RX_Pin_Index] |= PORT_PCR_MUX(pCAN_Map->CAN_Alt_Index);
	//选择为BusClock时钟
	CANx->CTRL1 |=  CAN_CTRL1_CLKSRC_MASK;	
	//使能冻结模式 只有进入冻结模式才能配置波特率
	CANx->MCR|=CAN_MCR_FRZ_MASK;
	//开启CAN通信模块 
	CANx->MCR &= ~CAN_MCR_MDIS_MASK;
	//等待通信模块复位启动
	while((CAN_MCR_LPMACK_MASK & (CANx->MCR)));
	//软件复位模块 //等待软件复位完成
	CANx->MCR |= CAN_MCR_SOFTRST_MASK;
	while(CAN_MCR_SOFTRST_MASK & (CANx->MCR));
	// 等待模块进入冻结模式
	while(!(CAN_MCR_FRZACK_MASK & (CANx->MCR)));
	for(i=0;i<16;i++)
	{
		CANx->MB[i].CS = 0x00000000;
		CANx->MB[i].ID = 0x00000000;
		CANx->MB[i].WORD0 = 0x00000000;
		CANx->MB[i].WORD1 = 0x00000000;
	}
	//配置远程请求产生,接收邮箱过滤ide,远程请求不比较,
	//邮箱首先从接收fifo匹配后再邮箱中匹配见参考手册
	CANx->CTRL2 = (0|CAN_CTRL2_TASD(22)); 
	//配置ID模式,目前选择的是A格式
	//按照工作要求配置MCR寄存器
	CANx->MCR |= CAN_MCR_IDAM(0); 
	//使能个别滤波和接受队列特点?
	//配置通信频率和初始化CTRL1  (自己理解的,设置传输一bite的时间)	 |CAN_CTRL1_LPB_MASK
    CANx->MCR |= CAN_MCR_IRMQ_MASK;    
    //设置传输速率
    CAN_SetBaudrate(CANx,CAN_InitStruct->CAN_BaudRateSelect);
	CANx->MCR |= CAN_MCR_IDAM(0); //配置ID模式,目前选择的是A格式
	//设置屏蔽功能
	if(CAN_InitStruct->FilterEnable == ENABLE)
	{
		for(i = 0; i < 16 ; i++)
		{
			CANx->RXIMR[i] = 0x1FFFFFFF; //设置16个接收id的掩码寄存器 
			CANx->RXMGMASK = 0x1FFFFFFF;
		} 	
	}
	else
	{
		for(i = 0; i < 16 ; i++)
		{
			CANx->RXIMR[i] = 0; //设置16个接收id的掩码寄存器 
			CANx->RXMGMASK = 0;
		} 		
	}
	//只有在冻结模式下才能配置 配置完退出冻结模式
	CANx->MCR &= ~(CAN_MCR_HALT_MASK);
	//等待模块推出冻结模式
	while((CAN_MCR_FRZACK_MASK & (CANx->MCR)));  
	//等待同步
	while(((CANx->MCR)&CAN_MCR_NOTRDY_MASK));    
	//设置接收ID过滤功能
}