DSP28335之CAN通信易错点总结

一、CAN初始化流程

①接收发送引脚初始化;

②接收和发送邮箱设置;

③邮箱使能;

④波特率配置;

⑤接收掩码设置;

⑥中断配置。

二、几个重要的知识点

①影子寄存器

因为ECanbRegs是不可以单独对位操作,所以需要设置先将其指向影子寄存器,设置影子寄存器的值,然后再把影子寄存器的值指向ECanbRegs,我们可以看到初始化中都是这样的套路;

②CANMD、CANME、CANMC、CANGIM

好几个类似的结构体成员,简直了是不是。。。他们分别是用来设置邮箱接收(1为RX)、使能邮箱(1为使能)、波特率配置、中断配置相关的;

③中断设置

CANA和CANB的中断初始化是不同的,并且每一路CAN都有2路中断线,如果配置错了,就进不了中断。

DSP28335之CAN通信易错点总结_第1张图片

从上面手册可知,如果你自己的板子电路只使用了CANB,那接受中断就只能使用TNT9.7(中断线0)、或者INT9.8(中断线1),配置为别的都会是错误的。

④发送设置

修改ID前要先禁止邮箱才能往寄存器里面写值,所以假如未禁止邮箱或者寄存器操作错误(我误把ECanbShadow.CANME.bit.ME16 = 0;写成ECanbRegs.CANME.bit.ME16 = 0;结果死活改不了ID),那就肯定达不到效果。

⑤接收设置

要想接收任意ID,只需要设置LAM和AME两个寄存器即可,ECanaMboxes.MBOX0.MSGID.bit.AME = 1;(启用筛选器,如果不启用就默认只能接收自己设置的ID)ECanaLAMRegs.LAM0.all = 0xFFFFFFFF;(接收任意ID)

注意,调试CAN中断接收时,每次烧录后最好把单片机重启,可能筛选ID寄存器未清空,那么即便设置对,也不能接收任意ID,我就遇到了,真坑!

好啦,上面的就是我调试过程中遇到的问题啦,完整代码见下方,有问题评论区讨论吧~

/*
 * can.c
 *
 *  Created on: 2023年12月12日
 *      Author: Cyber.
 */

#include "can.h"


interrupt void ISRECanbRx(void)
{

    PieCtrlRegs.PIEACK.bit.ACK9 = 1;

    Uint16 group;
    Uint32 high;  //用于存储接收邮箱的内容
    Uint32 low;   //用于存储接收邮箱的内容
    Uint32 id;

    volatile struct MBOX* Mailbox;
    group = (ECanbRegs.CANGIF0.all)&0x3F;   //判断是哪个接收邮箱触发的中断
    Mailbox = &ECanbMboxes.MBOX0 + group;   //取触发中断邮箱的地址
    if(Mailbox->MSGID.bit.IDE == 1) {  //IDE =1 收到的消息有扩展标识位
        id =Mailbox->MSGID.all&0x1FFFFFFF;
    } else{
        id = Mailbox->MSGID.bit.STDMSGID;
    }
    switch(group)  //我这里是把0-5号邮箱配置成了接收邮箱,所以下面case的取值是0-5
    {
    case 0:
    	LED1_TOGGLE;
        low     = Mailbox->MDL.all;    //低32位
        high    = Mailbox->MDH.all;   //高32位
        break;
    }
    ECanbRegs.CANRMP.all = 0x0000003F;   //清除GIF0.GMIF位,即中断标志位
}


void ECAN_Init(void)
{
    struct ECAN_REGS ECanbShadow;

    //配置引脚
    InitECanbGpio();

    //配置引脚用于CAN
    EALLOW;
    ECanbShadow.CANTIOC.all = ECanbRegs.CANTIOC.all;
    ECanbShadow.CANTIOC.bit.TXFUNC = 1;
    ECanbRegs.CANTIOC.all = ECanbShadow.CANTIOC.all;

    ECanbShadow.CANRIOC.all = ECanbRegs.CANRIOC.all;
    ECanbShadow.CANRIOC.bit.RXFUNC = 1;
    ECanbRegs.CANRIOC.all = ECanbShadow.CANRIOC.all;
    EDIS;

    EALLOW;
    ECanbShadow.CANMC.all = ECanbRegs.CANMC.all;
    ECanbShadow.CANMC.bit.STM = 0;		//退出测试模式
    ECanbShadow.CANMC.bit.SCB = 1;    	// eCAN mode (reqd to access 32 mailboxes)
    ECanbRegs.CANMC.all = ECanbShadow.CANMC.all;
    EDIS;


    //设置邮箱是接收还是发送
    ECanbRegs.CANME.all = 0;//先禁用所有邮箱,后面会打开指定使用的邮箱
    EALLOW;
    ECanbShadow.CANMD.all = ECanbRegs.CANMD.all;
    ECanbShadow.CANMD.bit.MD0  = 1;  //Rx
    ECanbShadow.CANMD.bit.MD16 = 0;  //Tx
    ECanbRegs.CANMD.all = ECanbShadow.CANMD.all;

    //设置邮箱使能和禁用
    ECanbShadow.CANME.all = ECanbRegs.CANME.all;
    ECanbShadow.CANME.bit.ME0  = 1;
    ECanbShadow.CANME.bit.ME16 = 1;
    ECanbRegs.CANME.all = ECanbShadow.CANME.all;
    EDIS;

    //波特率设置
    EALLOW;
    ECanbShadow.CANMC.all = ECanbRegs.CANMC.all;
    ECanbShadow.CANMC.bit.CCR = 1;
    ECanbRegs.CANMC.all = ECanbShadow.CANMC.all;
    EDIS;
    do
    {
        ECanbShadow.CANES.all = ECanbRegs.CANES.all;
    }while(ECanbShadow.CANES.bit.CCE != 1 );

    EALLOW;
    ECanbShadow.CANBTC.all = ECanbRegs.CANBTC.all;
    ECanbShadow.CANBTC.bit.BRPREG = 9;
    ECanbShadow.CANBTC.bit.TSEG2REG = 2 ;
    ECanbShadow.CANBTC.bit.TSEG1REG = 10;
    ECanbShadow.CANBTC.bit.SAM = 1;
    ECanbRegs.CANBTC.all = ECanbShadow.CANBTC.all;

    ECanbShadow.CANMC.all = ECanbRegs.CANMC.all;
    ECanbShadow.CANMC.bit.CCR = 0;
    ECanbRegs.CANMC.all = ECanbShadow.CANMC.all;
    EDIS;
    do
    {
      ECanbShadow.CANES.all = ECanbRegs.CANES.all;
    } while(ECanbShadow.CANES.bit.CCE != 0 );

    ECanbRegs.CANTA.all = 0xFFFFFFFF;  //清除所有TA位

    //这里是设置接收任意ID的功能
	ECanbLAMRegs.LAM0.all=0xffffffff;//邮箱15的局部验收屏蔽寄存器置位可接收任何id的报文(全局验收屏蔽寄存器用于scc模式)
	ECanbMboxes.MBOX0.MSGID.all=0x40000000;  //AME位为1使能验收屏蔽位

	//中断设置
    EALLOW;
    ECanbRegs.CANGIM.all = 0;
    ECanbRegs.CANMIM.all = 0x003F;  //使能上面的接收邮箱(0-5号邮箱)中断
    ECanbRegs.CANMIL.all = 0;

    ECanbShadow.CANGIM.all = ECanbRegs.CANGIM.all;
    ECanbShadow.CANGIM.bit.I0EN = 1;  //选择中断线0
    ECanbRegs.CANGIM.all = ECanbShadow.CANGIM.all;

    PieCtrlRegs.PIECTRL.bit.ENPIE=1;
    PieCtrlRegs.PIEIER9.bit.INTx7=1;  //9.7
    PieVectTable.ECAN0INTB = &ISRECanbRx;
    IER|=M_INT9;
    EINT;
    EDIS;
}


//注意邮箱编号需要根据实际修改
//CANB 发送函数 Can_Id为CAN_ID, length为CAN数据长度(单位是字节), Data_L为低四位字节,Data_H为高四位字节
void CanBSend(Uint32 Can_Id, char length, Uint32 Data_L, Uint32 Data_H)
{
    struct ECAN_REGS ECanbShadow;

    //修改ID前要禁止邮箱才能往寄存器里面写值
    ECanbShadow.CANME.all = ECanbRegs.CANME.all;
    ECanbShadow.CANME.bit.ME16 = 0;
    ECanbRegs.CANME.all = ECanbShadow.CANME.all;
     /* Write to the MSGID field  */
    ECanbMboxes.MBOX16.MSGID.all = Can_Id; // stand Identifier
    //使能邮箱
    ECanbShadow.CANME.all = ECanbRegs.CANME.all;
    ECanbShadow.CANME.bit.ME16 = 1;
    ECanbRegs.CANME.all = ECanbShadow.CANME.all;

    /* Write to DLC field in Master Control reg */
    ECanbMboxes.MBOX16.MSGCTRL.bit.DLC = length; //8;
    /* Write to the mailbox RAM field */
    ECanbMboxes.MBOX16.MDL.all =Data_L;  //低位4字节
    ECanbMboxes.MBOX16.MDH.all =Data_H ; //高位4字节

    //struct ECAN_REGS ECanbShadow;
    ECanbShadow.CANTRS.all = 0;
    ECanbShadow.CANTRS.bit.TRS16 = 1;             // Set TRS for mailbox under test
    ECanbRegs.CANTRS.all = ECanbShadow.CANTRS.all;
    do
    {
        ECanbShadow.CANTA.all = ECanbRegs.CANTA.all;
    }while(ECanbShadow.CANTA.bit.TA16 == 0 );   // Wait for TA5 bit to be set..
    ECanbShadow.CANTA.all = 0;
    ECanbShadow.CANTA.bit.TA16 = 1;             // Clear TA5
    ECanbRegs.CANTA.all = ECanbShadow.CANTA.all;
}





 

你可能感兴趣的:(单片机,dsp开发)