KEAZ128中MSCAN的同步时钟初始化失败已解决

文章目录

  • 运行环境:
  • MSCAN初始化成功代码
  • 初始化流程图
  • 初始化失败分析
  • 初始化异常原因

运行环境:

MSCAN初始化代码(采用24MHz总线时钟当时不行,于是直接采用了外部晶振时钟16MHz)

MSCAN初始化成功代码

void CAN_Init(uint_8 mode,uint_8 open_filter,uint_32 acc_id)
{
    uint_8 i;
		//对CAN_EN和CAN_STB置高,进入正常模式
	  gpio_init(CAN_EN, GPIO_OUTPUT, TURN_ON);
	  gpio_init(CAN_STB, GPIO_OUTPUT, TURN_ON);
		gpio_init(CONTROL, GPIO_OUTPUT, TURN_OFF);

    MSCAN_MemMapPtr p = (MSCAN_MemMapPtr) MSCAN_BASE_PTR;

	  //MSCAN模块时钟门控制;SIM_SCGC的MSCAN位=1:使能总线给MSCAN时钟;
    //SIM_SCGC的MSCAN位=0:禁止总线给MSCAN时钟
    SIM_SCGC |=(uint_32)(SIM_SCGC_MSCAN_MASK);
    //MSCAN的引脚复用选择CAN_TX为PTC7,CAN_RX为PTC6
    SIM_PINSEL1 &= (uint_32)~(uint_32)(SIM_PINSEL1_MSCANPS_MASK);

	  MSCAN->CANCTL0 |= MSCAN_CANCTL0_INITRQ_MASK;  //MSCAN初始化请求
	
		while(!(MSCAN->CANCTL1 & MSCAN_CANCTL1_INITAK_MASK)){;} //等待初始化模式确认
		MSCAN->CANCTL1 =0x80; //使能MSCAN 选择OSC时钟  

    if(open_filter)         //开启接收过滤器,只接收标示符为acc_id的帧
    {
        // 使用2个32位接收过滤器
        p->CANIDAC &= ~MSCAN_CANIDAC_IDAM_MASK;

        // 第1个32位滤波器
        // 设置接受寄存器的值
        p->CANIDAR_BANK_1[0]=acc_id>>3;
        p->CANIDAR_BANK_1[1]=acc_id<<5;
        p->CANIDAR_BANK_1[2]=0xFF;
        p->CANIDAR_BANK_1[3]=0xFF;
        // 设置屏蔽寄存器的值
        p->CANIDMR_BANK_1[0]=0x00;
        p->CANIDMR_BANK_1[1]=0x1F;
        p->CANIDMR_BANK_1[2]=0xFF;
        p->CANIDMR_BANK_1[3]=0xFF;

        // 第2个32位滤波器
        // 设置接受寄存器的值
        p->CANIDAR_BANK_2[0]=acc_id>>3;
        p->CANIDAR_BANK_2[1]=acc_id<<5;
        p->CANIDAR_BANK_2[2]=0xFF;
        p->CANIDAR_BANK_2[3]=0xFF;
        // 设置屏蔽寄存器的值
        p->CANIDMR_BANK_2[0]=0x00;
        p->CANIDMR_BANK_2[1]=0x1F;
        p->CANIDMR_BANK_2[2]=0xFF;
        p->CANIDMR_BANK_2[3]=0xFF;
    }
    else//关闭过滤器
    {
        for (i = 0; i < 16; i++)
        {

            if(i <=3)			//i>=0 && 
                p->CANIDAR_BANK_1[i] = 0xFF;
            else if(i>=4 && i <=7)
                p->CANIDMR_BANK_1[i-4] = 0xFF;
            else if(i>=8 && i <=11)
                p->CANIDAR_BANK_2[i-8] = 0xFF;
            else
                p->CANIDMR_BANK_2[i-12]= 0xFF;
        }
    }

    //配置时钟
    p->CANCTL1 &= ~MSCAN_CANCTL1_CLKSRC_MASK;    // 采用晶振时钟(16MHz)作为模块时钟
    p->CANBTR0 |= MSCAN_CANBTR0_SJW(2);
    p->CANBTR1 &= ~MSCAN_CANBTR1_SAMP_MASK;     // 位时间采样次数为1
    // MSCAN传输波特率 = 模块时钟 / [(1 + TSEG1 + TSEG2) * 分频因子]
    //                = 16000K/[(1+4+11)*2]=500Kbps
		//500K   BRP=1   TSEG1=15   TSEG2=2
    p->CANBTR0 |= MSCAN_CANBTR0_BRP(1);        // 模块时钟2分频
    p->CANBTR1 |= MSCAN_CANBTR1_TSEG2(3);      // TSEG2:3+1=4 Tq
    p->CANBTR1 |= MSCAN_CANBTR1_TSEG1(10);     // TSEG1:10+1=11 Tq

    //配置工作模式
		if(mode == LOOP_MODE)
		{
		 MSCAN->CANCTL1 |= MSCAN_CANCTL1_LOOPB_MASK;
		}
		else
		{
		 MSCAN->CANCTL1 &= ~MSCAN_CANCTL1_LOOPB_MASK;
		}
    p->CANCTL1 &= ~MSCAN_CANCTL1_LISTEN_MASK;   // 禁止侦听模式,即开启正常模式

    //退出初始化模式
    p->CANCTL0 &= ~MSCAN_CANCTL0_INITRQ_MASK;   //退出初始化模式,进入正常模式
		
    //等待应答初始化模式
    while ((p->CANCTL1 & MSCAN_CANCTL1_INITAK_MASK) == 1);

    //等待总线通信时钟同步
    while ((p->CANCTL0 & MSCAN_CANCTL0_SYNCH_MASK) == 0);
		
		    //设置中断方式
    p->CANTIER = 0x00;                          //禁止发送中断
    p->CANRIER = 0x01;                          //开启接收满中断
    //设置嵌套向量中断控制寄存器值,使能CAN接收中断
    NVIC_Init(MSCAN_RX_IRQn,2);
		gpio_set(CONTROL,GPIO_HIGH);
}

初始化流程图

KEAZ128中MSCAN的同步时钟初始化失败已解决_第1张图片

初始化失败分析

任何正在进行的传输或接收都将中止,与CAN总线的同步将丢失。该模块通过设置INITAK = 1来指示进入初始化模式。

初始化异常原因

导致我们初始化时钟域请求失败的原因可能有:
1.CAN芯片是否存在且正常供电(同网上要有外联CANH-CANL节点)
2.CAN芯片是否损坏
3.保证电源电压至少为CAN芯片最低工作电压

你可能感兴趣的:(CAN通信,单片机,嵌入式硬件)