一,前言
补充上一篇文章“TMS320F28377X芯片can通信心得笔记”,之前一直找不到清晰又压缩的方式把图片缩小
二,补充流程如图片和部分代码
带颜色 和带**号部分为中断配置
1.CAN配置部分代码
在这里插入代码片
//ui32Base为CANb基础地址 CAN_0_CTL为相应的寄存器组群地址
//CAN_CTL_SWR为相应位十六进制数(特别注意寄存器初始值)
HWREGH(ui32Base + CAN_O_CTL) = CAN_CTL_INIT;
//1.开启初始化保护(初始化可用)
HWREGH(ui32Base + CAN_O_CTL) = CAN_CTL_SWR;
//寄存器软件重启
while(HWREGH(ui32Base + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY)
{
}// 2.Wait for busy bit to clear 等 busy位清除
HWREGH(ui32Base + CAN_O_IF1CMD + 2) = (CAN_IF1CMD_DIR | CAN_IF1CMD_ARB | CAN_IF1CMD_CONTROL) >> 16;
//3.设置方向 ,设置if1写仲裁位,设置if1访问控制位(设置可以访问)
HWREGH(ui32Base + CAN_O_IF1ARB) = 0;
//4.重置if1仲裁寄存器
HWREGH(ui32Base + CAN_O_IF1ARB + 2) = 0;
HWREGH(ui32Base + CAN_O_IF1MCTL) = 0;
//5.重置if1消息对象控制寄存器
HWREGH(ui32Base + CAN_O_IF1MCTL + 2) = 0;
HWREGH(ui32Base + CAN_O_IF2CMD + 2) = (CAN_IF2CMD_DIR | CAN_IF2CMD_ARB | CAN_IF2CMD_CONTROL) >> 16;
//设置方向 ,设置if2写仲裁位,设置if2访问控制位(设置可以访问)
HWREGH(ui32Base + CAN_O_IF1ARB) = 0;
//重置if2仲裁寄存器
HWREGH(ui32Base + CAN_O_IF1ARB + 2) = 0;
HWREGH(ui32Base + CAN_O_IF1MCTL) = 0;
//重置if2消息对象控制寄存器
HWREGH(ui32Base + CAN_O_IF1MCTL + 2) = 0;
#if(RX_IE) // 根据需求设置 //***********************************************************************************************
HWREGH(ui32Base + CAN_O_IF1MCTL) =HWREGH(ui32Base + CAN_O_IF1MCTL) | CAN_IF1MCTL_RXIE;
//6.中断方向为接收中断(用于配置消息邮箱内的消息对象)*** //消息对象的接收中断使能 选择编译
#elif(TX_IE)
HWREGH(ui32Base + CAN_O_IF1MCTL) =HWREGH(ui32Base + CAN_O_IF1MCTL) | CAN_IF1MCTL_TXIE;
#endif
//******************************************************************************************************************
// CAN_IF1CMD寄存器(0-7bit)为msg_num,当CPU将消息编号写入其中时,开始传输,相当于清空消息邮箱
//7.初始化消息对象,清空消息对象
for(iMsg = 1; iMsg <= 32; iMsg+=2)
{
while(HWREGH(ui32Base + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY)
{
}
HWREGH(ui32Base + CAN_O_IF1CMD) = iMsg & 0xff;
while(HWREGH(ui32Base + CAN_O_IF2CMD) & CAN_IF2CMD_BUSY)
{
}
HWREGH(ui32Base + CAN_O_IF2CMD) = (iMsg + 1) & 0xff;
}
EALLOW;
switch(ui32Base) // 8.系统时钟配置
{
case CANA_BASE:
ClkCfgRegs.CLKSRCCTL2.bit.CANABCLKSEL = 0;
break;
case CANB_BASE:
ClkCfgRegs.CLKSRCCTL2.bit.CANBBCLKSEL = 0;
break;
default:
break;
}
EDIS;
CANBitRateSet(CANB_BASE, 200000000, 1000000);//9.配置canb波特率为1000k
HWREGH(ui32Base + CAN_O_CTL) = HWREGH(ui32Base + CAN_O_CTL) | (CAN_CTL_ABO | CAN_CTL_INIT | CAN_CTL_CCE);
//10.自动开启总线启用,初始化启用,can模块配置更改启用
HWREG_BP(ui32Base + CAN_O_CTL) = ((HWREG_BP(ui32Base + CAN_O_CTL) | (CAN_CTL_INIT | CAN_CTL_CCE)) &
~(CAN_CTL_INIT | CAN_CTL_CCE));
//11.把 CAN_CTL_INIT 和 CAN_CTL_CCE位 置0
HWREG_BP(ui32Base + CAN_O_CTL) =(HWREG_BP(ui32Base + CAN_O_CTL) | (CAN_CTL_IE0 | CAN_CTL_EIE)) &
~(CAN_CTL_IE0 | CAN_CTL_EIE);
//12.把 CAN_CTL_IE0 和 CAN_CTL_EIE 位 置0
//cpu控制器选择了DSP的CANB模块 以上HWREG为指针函数
//以下的寄存器 地址 和操作数在 hw_can.h内 和hw_memap.h内
//或者查Ti文档(系列详细那本)can模块 自己配置 ,以下不是全部,仅看看构成
#define CAN_CTL_INIT 0x1U // Initialization
#define CAN_CTL_IE0 0x2U // Interrupt line 0 Enable
#define CAN_CTL_SIE 0x4U // Status Change Interrupt Enable
#define CAN_CTL_EIE 0x8U // Error Interrupt Enable
#define CAN_CTL_DAR 0x20U // Disable Automatic Retransmission
#define CAN_CTL_CCE 0x40U // Configuration Change Enable
#define CAN_CTL_TEST 0x80U // Test Mode Enable
#define CAN_CTL_IDS 0x100U // Interruption Debug Support Enable
#define CAN_CTL_ABO 0x200U // Auto-Bus-On Enable
#define CAN_CTL_PMD_S 10U
#define CAN_CTL_PMD_M 0x3C00U // Parity on/off
#define CAN_CTL_SWR 0x8000U // SW Reset Enable
#define CAN_CTL_INITDBG 0x10000U // Debug Mode Status
#define CAN_CTL_IE1 0x20000U // Interrupt line 1 Enable Disabled
2.CAN中断配置代码
DINT;//1.禁用中断
InitPieCtrl();//2.初始化PIE 控制寄存器
IER=0x0000; //3.清空中断使能寄存器
IFR=0x0000; //4.清空中断标志寄存器
InitPieVectTable();//5.初始化PIE中断向量表
//6. can中断配置//***************************************************************
while(HWREGH(CANB_BASE + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY) //***
{
}//a,等待中断忙位清空
HWREGH(CANB_BASE + CAN_O_CTL) |= (CAN_CTL_INIT | CAN_CTL_CCE); //b,开启an初始化 和 启用配置更改
HWREG_BP(CANB_BASE + CAN_O_CTL) | = CAN_CTL_IE0 ;
//| CAN_CTL_EIE | CAN_CTL_SIE);
//c,只开启IE0
CanbRegs.CAN_GLB_INT_CLR.bit.INT0_FLG_CLR = 1;//d,清除CANb中断int0 flag
HWREG_BP(CANB_BASE + CAN_O_GLB_INT_EN ) = CAN_GLB_INT_EN_GLBINT0_EN;//e,CAN GLB全局中断*******
EALLOW;
PieVectTable.CANB0_INT = &IntHandler; //7.pie 中断向量表canB0中断关联中断函数(链接函数地址)
EDIS;
PieCtrlRegs.PIEIER9.bit.INTx7 = 1; //8.pie 控制开启canb0,查PIE通道映射 canb0中断在组群9 位置7
IER |= 0x0100; // 9.M_INT9 中断使能 使能中断组群9
EINT;//10.使能中断,开启中断
//*******************************************************************************************************
3.CAN邮箱建立
CAN_Setup_Msg_Obj(&CanbRegs, 17, EXT_ID, TEST_CAN_CONNECT_RX_ID_1, Len_8, MSG_OBJ_RECEIVE);
CAN_Setup_Msg_Obj(&CanbRegs, 18, EXT_ID, TEST_CAN_CONNECT_RX_ID_2, Len_8, MSG_OBJ_RECEIVE);
//最多可设置32个消息对象 消息邮箱号 是否扩展帧, 消息ID 数据长度 ,消息的方向(接收与发送)
//创建一个Canb模块 消息邮箱号17,扩展帧,ID为TEST_CAN_CONNECT_RX_ID_1,数据长度为8,方向为接收的 消息邮箱
仅仅做参考,Ti 提供有相应的函数可以拿来用
4.CAN中断注意部分
Uint16 Status; //这部分必须放在中断函数内,前面
//CAN中断数据处理
Status = CanbRegs.CAN_INT.bit.INT0ID; //触发中断的消息邮箱号
CanbRegs.CAN_GLB_INT_CLR.bit.INT0_FLG_CLR = 1;
//清除Interrupt 0 Flag
if(Status == 0x8000) //故障状态
{
Status = CanbRegs.CAN_ES.all; //最低3位为故障码
} //cpu读取es才能清楚该寄存器位(只读不能写)
PieCtrlRegs.PIEACK.all = PIEACK_GROUP9;//此句放中断函数最后面
//PIE中断确认寄存器 清除中断组群9,允许同组群中断产生(其他或本身)
以上仅是我个人心得,可能不是很适合新人,你还是得翻阅下Ti 提供的技术文件can模块的和 中断相关的(去官网上下)《TMS320F2837xD Dual-Core Microcontrollers Technical Reference Manual》 F2837xD和F2837xS的CAN模块是一样的模式结构, 你若是用的F2837xS你也还是要去下该芯片的技术文件。谢谢