主题中讨论的其他器件:C2000WARE
您好-
我最终获得了硬件、并尝试启动和运行 CAN 通信。 F28377S 可以接收 CAN 数据包。 我在 CCS 调试器中看到它们进入我的应用。 我无法使传输正常工作。 我将数据加载到接口中-我看到了这一点、但消息不会进入 RAM。 我在范围内看不到任何活动。
我的问题可能是仲裁或屏蔽寄存器。 对于接收、我设置了仲裁接受和屏蔽寄存器、这似乎是有效的。 我也尝试过在传输端这样做-没有乐趣。 此外、我只尝试使用 TX 的仲裁寄存器-同样、没有乐趣。
如果有一些见解、我将不胜感激。 随附了我的335和377S 代码。
-------------------------------------------------- //文件:CANModule.c // //说明:CAN 驱动 程序// //版本:1.0 (2015年2月5日) // 目标:TMS320F28335 // //详细信息:到 ECAN 硬件的外设接口 //硬件支持扩展 CAN (ECAN)和标准 CAN //(SCC)。 此驱动程序使用 SCC CAN。 //// 参考:sprue1 - TMS320F2833x、2823x 增强型控制器局域 网//网络(eCAN)参考指南 //////../../---------------增强型控制器局域网//网络(eCAN)参考指南 ///------------------ 包括-------------------------------- #include "Defs.h" #include "processormodule.h" #include "PeripheralHeaderIninclude.h" #include "GMNIAddeding.h" #include "CANModule.h" #include "Errors.h"#include "ParamDB.h" #include "DebugModule.h" #include "CommandProtocol.h" #include "---"include-- #include "--/-"ines.h" 定义了------------------------------------------------------- #define LOOP_Counts(((uint32) 10000)//取消循环计数以便我们不会永远被卡住 #define NUM_POOFFER((int) 16)//标准 CAN 模式中允许的邮箱数 #define ACCEITY_MASK0xFF03FFFF//位18到28用于标准 CAN、屏蔽用0来完成 //在本应用中, 节点 ID 用作消息 ID。 它存储在6位中、因此... //位18到23必须匹配消息 ID -(位31) xxxx、xxxx、000000、00xx、xxxx、xxxx、xxxx、xxxx (位0) #define MAX_TX_Attempts((UINT32) 2) //--- 全局变量-------------------------------------------- CANQueue canQueue;//存储来自总线 CANQueue LocalCommQueue 的 CAN 消息;//存储来自与发送方相同 CAN 节点的 CAN 消息。 //每个节点都可以看到来自所有其他节点的所有消息,但无法看到自己的消息。 //参考: www.keil.com/.../canprimer_v2.pdf 静态 uint16 currDestID; // Ecanb 接口用于与 Encore 静态易失性结构 ECAN_REGS 上的主仪器 CAN 总线进行通信*ECANRegs=&ECANbRegs; 静态易失性结构 ECAN_MBOXES *ECANMbox=&ECanbMboxes; 静态易失性 Regstruct EAM---- //注意:访问 ECAN 控制和状态寄存器 // //只允许对这些寄存器进行32位访问。 对 这些寄存 器的16位访问//可能会破坏寄存器内容或返回//假数据。 当写入 /读取位16 - 31之间的位//(或位组)时尤其如此 // 这适用于以下寄存器: // CANMECANMDCANTRSCANTRRCANTA CANAACANRMPCANRML // CANRFPCANGAMCANMCCANBTCCANTECCANRECCANNGIF0 // CANGIMCANGIF1CANMIM CANMIM CANMIL CANTIOCCANRIOCCANTSC // CANTOC CANTSC CANTSC CANTSC // //////采用影子寄存器进行32位读操作以进行读操作。 ///---------------------------------- 静态易失性结构 ECAN_REGS EDANRegsShadow; //--------------- // eCAN-Init // //标准 CAN 初始化。 使用控制器板上的 CAN-B。 //与主控制器总线通信。 ///---------------------------------- void eCAN-Init (uint16 bcastAddr) { volatile struct MBOX *邮箱; int i; canQueue.size= 0; localCommQueue.size= 0; EALLOW;// EALLOW 启用对受保护位的访问 //使用 eCAN 寄存器为 CAN 操作配置 eCAN RX 和 TX 引脚 //请参阅文件 ECANRegsShading.CANTIOC.all =ECANRegs->CANTIOC.all 顶部的注释; ECANRegsShading.CANTIOC.bit.TXFUNC= 1;//启用发送 ECANRegs->CANTIOC.all= ECANRegsShading.CANTIOC.all; ECANRegsShading.CANRIOC.all= ECANRegs->CANRIOC.all; ECANRegsShading.CANRIOC.bit.RXFUNC= 1;//启用接收 ECANRegs->CANRIOC.ALL= ECANRegsShadow。CANRIOC.ALL; //将 CAN 配置为 SCC 模式(标准 CAN 控制器模式)-(要访问邮箱15至0) //我们不使用 eCAN,我们使用 影子(邮箱0至15) ECANRegsSCN.CANMC.ALL= ESCRegs->CANCLA.USC.B ;CANCLUSC.AB.USC.T= CANSDC.TANCE.USC.D/ CAN.CANCLUSC.TL.MC.CAN.USC.TABTBIT.CAN.ABT= CANESC.D/ CANCR.CANESC.D/ CANCR.CANCR.CANCR.CAN //启用 ECANRegs->CANMC.ALL上的自动总线= ECANRegsShading.CANMC.ALL; //将“消息控制寄存器”的所有位初始化为零 //MSGCTRL 寄存器的某些位出现在未知状态。 为了正确操作, //MSGCTRL 的所有位(包括保留位)必须初始化为零 Mailbox =&ECanMboxs->MBOX0; for (i = 0;i < NUM_mailbox;++I) { Mailbox->MSGCTRL.ALL= 0x00000000; +Mailbox; } // CANCCR MC 位设置为1: // CPU 请求到配置寄存器 CANBTC 和 SCC 的接受屏蔽 //寄存器(CANGAM、LAM [0]和 LAM [3])的写入访问。 置位该位后、CPU 必须等到 CANES 寄存器的 CCE 标志为1、然后再进入 CANBTC 寄存器。 ECANRegsShadure.CANMC.ALL= ECANRegs->CANMC.ALL; ECANRegsShading.CANMC.bit.CCR= 1;//更改配置请求位 ECANRegs->CANMC.ALL= ECANRegsShading.CANMC.ALL; //等待 CCE 位被置位。 // CCE = 1、当 CPU 对配置寄存器具有写访问权限时。 // CCE 是更改配置使能位 DO { ECanRegsShading.canes.all = ECanRegs->canes.all; } while (ECANRegsShading.canes.bit.CCE!= 1); //清除位时序配置寄存 器 ECANRegs->CANBTC.all= 0; //配置位时序 //位速率=(SYSCLKOUT / 2)/((BRPreg + 1)* BitEG) //其中 SYSCLKOUT = 150MHz //位时间=(TSEG1REG + 1)+(TSEG2REG + 1)+ 1 EDANRegsShading.CANBTC.all= ESEG1REG + 1)+(TCCANREG2REG + 1)+ CANBRCN.CANRegDIDT.CANTC.ALL = ECANBRTC.TC.TC.TCC.Tc = CANTCC.TCC.TB.Tc = CANTBC// 4 for 1Mbps 提供15MHz CAN 模块时钟 ECANRegsShadow。CANBTC.bit.TSEG2REG= 2;// 15个时间份额每位- 80%采样点 ECANRegsShadow。CANBTC.bit.TSEG1REG= 10;// 15个时间份额每位- 80%采样点 ECANRegsShadow。CANBTC.TCCS.bit.TSEG1REG = 10;// 15个时间份额: //采样3次并获取多数读取 ECANRegsShading.CANBTC.bit.SJWREG= 0;// 0:SJW (同步跳转宽度、扩展段1和缩短段2);1:SJW = 2 (1表示800KB) ECANRegs->CANBTC.ALL= ECANRegsShading.CANBTC.ALL ;1 = CANCANGAM.ALL 用于全局接受屏蔽6;CANGANGAM = 6 = CANGANGAM.MASK 接收邮箱 //位18到23必须与 msg ID EDANRegsShading.CANGAM.all= ECANRegs->CANGAM.all; ECANRegsShading.CANGAM.bit.AMI= 1;//接受屏蔽标识符- 1:CAN 将接受标准和扩展帧。 //接收邮箱的 IDE 是“无关”。 被发送的消息覆盖。 //使用 CANGAM 的位18至28在标准 CAN 模式 下进行 msg 过滤 EDANRegs->CANGAM.all= ECANRegsShading.CANGAM.all; // LAM0 (本地访问掩码)用于邮箱0至2 ECANLAMRegs->LAM0.all= Accepting_mask;// LAM23位必须匹配 1至 ECANLAMID;//接受屏蔽标识符- 1:CAN 将接受标准和扩展帧。 //使用 CANGAM 的位18至28在标准 CAN 模式下进行 msg 过滤 // LAM3 (本地访问掩码)用于邮箱3至5 ECANLARegs->LAM3.all= Accepting_mask;//位18至23必须与 msg ID EDANLAM Regs->LAM3.bit.Lami= 1匹配;//接受掩码://标识符掩码: CAN 将接受标准和扩展帧。 //在标准 CAN 模式中使用 CANGAM 的位18至28进行 msg 过滤 // CANMC CCR 位设置为0: //在配置寄存器 CANBTC 和 SCC 的接受屏蔽//寄存器(CANGAM、LAM[0]和 LAM[3])完成后,CPU 请求正常运行。 ECANRegsShadure.CANMC.ALL= ECANRegs->CANMC.ALL; ECANRegsShading.CANMC.bit.CCR= 0;//更改配置请求位 ECANRegs->CANMC.ALL= ECANRegsShading.CANMC.ALL; //等待 CCE 位被清除。 // CCE = 0当 CPU 没有到配置寄存器的写入访问权限时。 执行 { ECanRegsShading.canes.all = ECanRegs->canes.all; } while (ECANRegsShading.canes.bit.CCE!= 0); currDestID= 0x3F;//初始化后续-此处使用的虚拟值 ECANRegs->CANME.all= 0;//禁用所有邮箱,写入 MSGID 前需要 ;邮箱=&ECANMboxs->MBOX0;//在第一个邮箱开始 / 邮箱传输位 IDE->MSGID-邮箱设置邮箱//无扩展 ID,使用 SCC (statndard CAN) 邮箱->MSGID.bit.STDMSGID=(currDestID & 0x3F);//目标 ID -在此处使用虚拟值。 在发送时设置为目的 // STDMSGID 为11位(bit 10至 bit 0),对应于 MSGID ++Mailbox 的 bit 28至 bit 18; //为 (i = 0;i < 5;++I) { Mailbox->MSGID.bit.ide= 0设置5个接收邮箱;// IDE 是一个“无关”,当 AMI=1时被发送的消息覆盖 //仍然在这里设置-在这里设置它没有任何危害 邮箱->MSGID.bit.AME=1;//接受屏蔽被启用 邮箱->MSGID.bit.STDMSGID= cntrlrNodeAddr;//消息 ID,cntrlrNodeAddr 是控制器节点 ID ++Mailbox; } //为 (i = 0;i < 10;+i) { Mailbox->MSGID.bit.ide= 0设置10个广播接收邮箱;// IDE 是一个“无关”,当 AMI=1时被发送的消息覆盖 //仍然在这里设置-在这里设置它没有任何损害 邮箱->MSGID.bit.AME= 1;//接受屏蔽被启用 邮箱->MSGID.bit.STDMD= bCastAddr;//消息 ID +Mailbox; }ECANRegs->0x0000FFGID.all ;}CANGID.STDMD = 0x0000FFMD//为接收 ECANRegs->CANOPC.ALL= 0x0000FFBD 设置邮箱;//保护数据,除了最后一个接收邮箱 ECANRegs->CANME.all= 0x0000FFFF;//启用邮箱 EDIS; }//------------------ // EcanRX // CAN 接口上的接收消息。 ///---------------------------------- void EcanRX (void) { uint32 rcvMask、mask; volatile struct MBOX *邮箱; //检查溢出 (如果(ECANRegs->CANRML.all!= 0) { DEBUG_log (0xFC100000); } do { //检查 RMP =接收待处理消息 rcvMask= ECanRegs->CANRcml; 如果所有 数据都可以读取到邮箱中) 邮箱=&ECANMboxs->MBOX15; 掩码= 0x00008000; while (mask!= 0) { //如果有消息,请将其放入 CAN Q if ((mask & rcvMask)!= 0) { if (canQueue.size < CAN_queue_queue) { canQueue.data[canQueue.size].mdl.mc邮箱= 低位数;mdlc= cand.cmc.mbl.micro.micro.rc.mcand.dl.micro.rc.mced.r.r.r.r.r.r.rc.mblu.mcand//低消息数据 canQueue.data[canQueue.size].high=邮箱->mDH.all;//高消息数据 +canQueue.size; } else { //可以队列溢出 debug_log (0xFC200000 | rcvMask); } }--> 邮箱; 掩码>=1; } //允许进一步接收数据包 EcRegs->CANvMask ;}//将所有接收位设置为1以清除 CANRMP rcvMask=~rcvMask; while ((ECANRegs->CANRMP.ALL 和 rcvMask)!= ECANRegs->CANRMP.ALL){}//等待位清除 } while (ECANRegs->CANRMP.ALL)}--> CANRMP.ALL!------------------------------------------------------------------ // EcanTX // //将数据传输到 CAN 总线上的目标位置,或者如果 节点是自消息传送,则将其放入//本地通信队列中。 ///---------------------------------- void EcanTX (uint16 destID、uint32 low、uint32 high、uint16 len) { uint32 i、j、k; BOOL tryRecover= true; 如果(destID =cntrlrNodeAddr || GMNI_ADDR_BCAST == destID) {// 本地节点单播或要广播到自身的数据包,请将其放入本地消息通信队列 中,如果(localCommQueue.size < CAN_Queue_size) {localCommQueue.data[localCommQueue.size].low = low.localCommQueu.= low.= localCommQueu.s/sime.size.s/sime.s/sime.data];[localCommQueu.Commsize.s=localCommQueu.localComms/sime.data];[localCommsize.s=localCommque 否则 { //本地邮箱溢出 debug_log (0xFC300000); } } //else//将所有传出消息发送到 CAN 总线-单播和广播 IF (destID!= cntrlrNodeAddr) { //如果目标从上一条消息更改为( currdestID!= CANdestID) { EDANRegsShading.CANME.all= ECANRegs->CANRegme.all;CANest.all = CANCand.0;CANME.0;//禁用 TX 邮箱 ECANRegs->CANME.all= ECANRegsShading.CANME.all; ECANMboxs->MBOX0.MSGID.STDMSGID =(DestID & 0x3F);//目标 ID ECANRegsShading.CANME.ALL= ECMDR.ALL = CANDRES.0>EMCMBE0>EMCMDR.UME ;// EMR0>EMCMDR.UME = 低字节0>EMCMDR.UME =高字节0>EMCMOS.REDME;////写入高字节 ECANRegs->CANTRS.All= 0x00000001;//开始传输 (i = 0;i < MAX_TX_Attempts;+i)//尝试发送,然后在出错 时再次尝试发送{ //如果发送 ACK 未在通过此循环的合理次数内设置, //退出循环。 如果发生超时、控制器可能无法连接到系统。 //我们不想在该循环中卡住。 //在控制器中设置 CANTA 的典型时间小于~130 μ s。 //典型循环计数小于229。 ECanRegsShadow.Canta.all = ECanRegs->CANTa.all; for (j = 0;j < LOOP_Counts && ECANRegsShadow.CANTAM.TA0 = 0;+j) { ECanRegsShadow.Canta. all = ECanRegs->CANTA.all; } (如果 您尝试全部恢复、 则为1){ECanRegsShadow / CANTANRegs.all = 1;允许全部恢复(如果是) if (ECANRegsShading.canes.bit.SA1)//检查显性错误时卡住 { //尝试清除其显性位错误 ECANRegsShading.CANMC.ALL= ECANRegs->CANMC.ALL; ECANRegsShadow CANMC.bit.CCR= 1;//更改配置请求-写入访问 ECANRegs->CANRegs.eCan.all;ECANRegsShadow = CANMC.CANCR.CANCR.CANCR.CANCR.CN.0=CANCR.CANCR.CANCR.CANCR.NOR = ECANCR.CANCR.CANCR.CANCR.CANCR.CANCR.RECN.0; ECANCR.CANCR.CANCR.CANCR.CANCR.CANCR.CANCR.NOP=0=ECANCR. +k) {//等待 CCE 为1,CPU 将具有对配置寄存 器 ECanRegsShading.canes.all的写入访问 权限= ECanRegs->CANES.all;}ECanRegsShading.CANMC.ALL = ECanRegs->CANMC.ALL; ECanRegsCCR.bit.alk= 0; = CANReakradr.CANMC.u.all = 0;= CANReakralu.CANReakr.CANMC.u.CANMC.u.u.CANReakeMC 配置 = 0;= 0;= CANReakr.CANCR.CANReakr.CANReakr.CANReakr.CANCR.CAN 否则 { //报告错误 debug_log (0xFC400000); debug_log (ECanRegsShading.canes.all); instrstates[0].errCode= ERRCODE (ERRCODE_HI_CAN、ERRCODE_LOW_NO_MSG_TX); return; } } 否则 { //获取传输确认-一切都是精细 中断; } } EDANRegsShadure.CANTA 全部= 0; ECANRegsShading.CANTA 位.TA0= 1;//清除传输确认下一个传输 ECANRegs->CANTA 全部= EDANRegs.CANTA 全部; ECANRegsShadow = 0<& ECANTA 全部= 1;ECAN.I = CANTA 全部= CANTANRegsShadow ++i) {//等待传输确认清除 ECanRegsShading.Canta.all= ECanRegs->Canta.all; } }//--------------- //文件结尾 ///------------------------------------------------------- ///---------------------------------- //文件:CANModule.c // //说明:CAN 驱动 程序// //版本:1.0 (2015年2月5日) // 目标:TMS320F28377S // 详细信息:到 DCAN 硬件的外设接口 //硬件支持扩展 CAN (ECAN)和标准 CAN //(SCC)。 该驱动程序使用 SCC CAN。 // //参考:spruhx5d - TMS320x2837x、2837x 技术 //参考指南 // /../../----------- ///------------------ 包括-------------------------------- #include "Defs.h" #include "processormodule.h" #include "F2837xS_device.h" #include "hw_types.h" #include "hw_CAN.h" #include "GMNIAddings.h" #include "Errors.h" #include "Parameters.h"#include "paramdB.h"#include "ines.h" -"include "influe.h-"-"#include -"ines.h"#-"--#include -"inue.mandion-"-"-"#include -"-"#-"#include -"-"dictionnation.h"-"-"-"-"-"-"-"#include -"#-"-"#- 定义了------------------------------------------------------- #define LOOP_Counts((UINT32) 20000)//取消循环计数以便我们不会永远被卡住 #define NUM_POMSG((int) 16)//标准 CAN 模式中允许的邮箱数 #define CAN_BRP_REG(19) #define CAN_BRP_EX_REG(0) #define CAN_TSEG1_REG(6)#define CAN_CAN_BR_8 (6)#define CK_REG_18 (#define CAN_CK_REG_1)#define CAN_REG_1 (#define CK_REG_18)#define CAN_CK_REG_1 (#define CAN_CK_REG_1 到28用于标准 CAN、屏蔽由1s 完成 //在此应用中、节点 ID 用作消息 ID。 它存储在6位中、因此... //位18到23必须与消息 ID 匹配- (位31) xxxx、xxxx、111111xx、xxxx、xxxx、xxxx (位0) #define CAN_IF3ARB_STD_ID_M (0x1FFC0000U) #define IF3_mailbox(0x0000FFFE) #define FIRST_OSSIT_MB(2)//第一个 CAN 单播邮箱 #define LAST_MB_MB(6)- cCAN / LAST_M_BONMOD- (cast-32-)/cast-/ cast_mailbox #define (casteast-/cast_mb) 全局变量-------------------------------------------- CANQueue canQueue;//存储来自总线 CANQueue LocalCommQueue 的 CAN 消息;//存储来自与发送方相同 CAN 节点的 CAN 消息。 //每个节点都可以看到来自所有其他节点的所有消息,但无法看到自己的消息。 //参考: www.keil.com/.../canprimer_v2.pdf 静态 uint16 currDestID = 0x3F;//虚拟初始值,将在第一个 TX 上更改 //--------------- //注:访问 DCAN 控制和状态寄存器 // // 32位 DCAN 寄存器必须读/写为32位值。 如果 使用16位//访问、则值可能会损坏。 编译器提供 //内在函数__bit_peripheral_32。 提供了一个宏来提供对 内在函数的访问// HWREG_BP // //////../../--------------- ///---------------------------------- // DCanInit // //标准 CAN 初始化。 使用控制器板上的 CAN-B。 //与主控制器总线通信。 ///---------------------------------- void DCANInit (uint16 bcastAddr、uint32 base) { uint16 mailbox;//消息对象(mailbox)索引 uint32 mailBoxID; uint16 endOfBlock;//接收 FIFO 结束-单播块或广播块 uint32 bitReg; uint32 maskReg; canQueue.size = 0; --- 启动 DCan init------------------------------------------------------- //将 CAN 控制器置于初始化状态,与之前的状态无关。 这个 //将使控制器空闲、并且允许对消息对象 RAM 进行//编程。 // CAN_CTL 寄存器 // CAN_O_CTL 相对于寄存器基址偏移 //位:init (b0)= 1; //ABO Auto-Bus_ON (b9):启用 //PMD 奇偶校验(B10-B13)= 0101 (复位时的默认值) //DAR 禁用自动重传:0我们想要重传|CAN_INIT_CTL (CAN_INIT)| INTO_CTL (CAN_INIT )| INT_CTL (CAN_INT_INIT (UCTL) 16)| INT_INIT (CAN_INT_CTL (CAN_INT_INT_CTL) //设置脱离总线计时器值-发生脱离总线和恢复启动后的时钟周期数 // CAN_ABOTR 寄存器 // CAN_O_ABOTR 相对于寄存器基址偏移 //位:Abo_Time (b0-B31) HWREG_BP (base + CAN_O_ABOTR)= 2;//尝试0、5、10? //在使用消息 RAM 之前初始化消息 RAM // CAN_init 寄存器 // CAN_O_RAM_init 与基址偏移 //位:CAN_RAM_init (b4)= 1;键(b0-b3)= 1010 HWREinit (base + CAN_O_RAM_init)= CAN_RAM_CAN_RAM_INIT (b4)= 1;CAN_INIT (while + CAN_RAM_INIT)+ HW_INIT (+ CAN_RAM INIT + CAN_RAM_INIT)+ CAN_RAM INIT (while + CAN_RAM_COMPLETE)+ CAN_RAM_INIT (+ CAN_RAM_INIT + HW_RAM_INIT (CAN_RAM_INIT_RAM_INIT_DONE | CAN_RAM_INIT_Key2 | CAN_RAM_INIT_KEY0)) { // RAM_INIT_DONE 将为1 // CAN_RAM_INIT 将为0 //键将为0101 } //强制模块复位// CAN_CTL 寄存 器// CAN_O_O_INIT 位为1位:ALLOW 位= 1位(ALLOW 位) HWREGH (base + CAN_O_CTL)|= CAN_CTL_SWR; EDIS; //延迟14个周期- 1us DELAY_US (1); //启用对配置寄存器的写入访问 // CAN_CTL 寄存 器// CAN_O_CTL 从寄存器基址偏移 //位: GH (B6):1 REGH (HWL)-|-—————— ————CAN_CTL 寄存器 设置位定时--- //将 CAN 总线位速率设置为1Mbps //有关如何设置 更严格的时序控制的信息,请参阅驱动程序库用户指南。 此外、请参阅器件数据表 //以了解有关 CAN 模块计时的更多信息。 //要设置位时序寄存器,必须将控制器置于初始 化//模式(如果尚未), 并且配置更改(CCE)位被使能 //这在上面完成 //配置位时序 //位速率=(SYSCLKOUT)/(((BRPreg + 1)* BitTime)= 1、000、000、000Mb/s //其中 SYSCLKOUT = 200 MHz;BRPreg = 19;TSEG1reg = 1;TSEG2reg = 1; SJWreg = 1 //位时间=(TSEG1REG + 1)+(TSEG2REG + 1)+ 1 = 10 //默认情况下、复位时使用外设时钟(SYSCLKOUT) bitReg =(UINT32)( (UINT32) CAN_BRP_REG & CAN_BR_BR_BR_CAN_TR_CK_32)< TR_CAN_TR_TR_TR_TR_TR_TR_TR_TR_CK_TR_TR_TR_TR_CK_32 (UTR_TR_TR_TR_TR_TR_TR_TR_TR_TR_TR_TR_TR_TR_TR_TR_TR_TR_TR_TR_CK_32)|(TTR_TR_TR_TR_TR_TR_TR_TR_TR_TR_TR_TR_TR_TR_TR_TR_TR_TR_ bitReg |=(uINT32)(((uint32) CAN_TSEG2_REG << CAN_BTR_TSEG2_S)& CAN_BTR_TSEG2_M); bitReg |=(uINT32)(CAN_BRP_REG_REG << CAN_BTR_TSEG2_M);CAN_CTR_BUCTL 寄存器+ CC_0 (UINT_CTL)+ CCTR_CL_CL_CL_BIT_B_6)+ CAN_CL_CL_CL_BIT_BIT_BIT_CL/ (CAN_CTL + CAN_CL_CL_CL_BIT_BIT_BCTL (CAN_6)+ CAN_CTL + CAN_CL_CL_CL_BIT_BIT_BIT_BIT_BIT_BCTL 寄存器/(CAN_CL_6)/ CAN_CL_CL_CL_CL_BIT_BIT_BIT_BIT_BCTL (CAN_CL_CL_CL/ CAN ~ ///---------------- 设置邮箱--- // 1个发送邮箱 // 5个单播接收邮箱 // 10个广播接收邮箱 //确保接口1不忙 ((HWREGH (base + CAN_O_IF1CMD)& CAN_IF1CMD_BUSY)== CAN_IF1CMD_BUSY) { } // TX 邮箱--- // CAN_IF1MSK 寄存器-接口1掩码寄存 器// CAN_O_IF1MSK 相对于寄存器基址偏移 //位:dir (B29):dir:1 = TX; //MessageID (b0-B28):0x00FC0000 Filter on Acceptance mask //mDir (B30):0 -不按方向进行滤波 //MX31: 0 -请勿在扩展 ID HWREG_BP (base + CAN_O_IF1MSK)= 0; //HWREG_BP (base + CAN_O_IF1MSK)=(Acceptance_MASK & CAN_IF1ARB_STD_ID_M); // CAN_IF1BARB 寄存器-接口1仲裁寄存 器// CAN_O_IF1MSK = 0 (bARB):b3dir_dir (bID:b29):bd2) 虚拟(0x3f << 18) TX msg 的占位 DESID。 发送时将用目标地址填充; //XTD (B30):0 -标准标识符(11位) //MsgVal (B31):1 -使用邮箱 HWREG_BP (base + CAN_O_IF1ARB)=CAN_IF1ARB_DIR | (ACCESTIVE_MASK & CAN_IF1ARB_ID_M)| CAN_IF1ARB_STD_GV1ARB ; // CAN_IF1MCTL -接口1消息控制 // CAN_O_IF1MCTL 相对于寄存器基址偏移 //位:DLC (b0-B3):8 -数据长度; //EOB (B7):1 -块末尾; //umask (B12): 0 -请勿使用掩码在发送 /HWREG_BP (base + CAN_O_IF1MCTL)= CAN_IF1MCTL_UMASK | HWREG_BP (base + CAN_O_IF1MCTL)=((uint32) MSG_DATA_LENGTH 和 CAN_IF1MCTL_DLC_M)| HWREG_WCA_MASK | CAN_1D/ CAN_IF1D/CAN_MASK | CMD/ CAN_MASK | CAN_CMO_MASK | CAN_CMO_MASK | CAN_CMO_CMD/ CAN_CONTRAM| CMO_INT_LK | CAN_CMO_MASK | CAN_CMO_MASK | CAN_CMO_CMO_MASK | CAN_CMO_MASK | CAN_CMO_CMO_MASK | CAN_CMO_CMO_CMO_CMO_ 5个单播 RX 邮箱和10个广播 Rx 邮箱--- //使用 IF1或 IF2设置消息对象(邮箱)-我们将使用 IF1 //设置消息对象后,我们可以使用 IF3接收 (邮箱= FIRST_OSSON_MB;邮箱<= LAST_BCast_MB; ++mailbox) { //确保接口1在 (((HWREGH (base + CAN_O_IF1CMD)& CAN_IF1CMD_BUSY)=CAN_IF1CMD_BUSY) { // CAN_IF1MSK 寄存器-接口1屏蔽寄存 器// CAN_O_IF1MSK 是标准 帧掩码(b31)的偏移 (bMX28位/bd/ bmask)0 -不使用扩展 ID 进行验收滤波 //MDir (B30):0 -不使用方向进行验收滤波 HWREG_BP (BASE + CAN_O_IF1MSK)=(ACCESTIVE_MASK & CAN_IF1ARB_STD_ID_M); // CAN_IF1DIR 寄存器-接口1仲裁寄存 器// CAN_O_IF1ARB 寄存 器0 -来自 RX 寄存器的位数:0 //MessageID (b0-B28):MSG ID 是控制器节点 addr; //MsgVal (B31):1 -如果 (邮箱<= LAST_unicast_MB) { //设置单播邮箱 mailBoxID = cntrlrNodeAddr; } 否则 { //设置广播邮箱 mailBoxID = bcastAddr ;} HWREG_BP (base + CAN_O_IF1ARB)=((mailBoxID << CAN_IF1ARB_STD_ID_S)和 CAN_IF1ARB_STD_ID_M)| CAN_IF1ARB_MSGVAL; // CAN_IF1MCTL -接口1消息控制 // CAN_O_IF1MCTL ( B8位)-从 BOB 1到 B8的数据位数(0);/ B8位数:1) 使用 FIFO 为最后一个单播邮箱和最后一个广播邮箱设置 EOB //umask (B12):1 -如果 (LAST_OST_MB =mailbox || LAST_BCast_MB == mailbox){ endOfBlock =CAN_IF1MCTL_EOB; } 否则 { endOfBlock =0; } HWREG_BP (base + CAN_O_IF1MCTL)= CAN_IF1MCTL_UMASK | ((uint32) MSG_DATA_LENGTH & CAN_IF1MCTL_DLC_M)| endDIR Block; //将数据传输到消息对象 RAM HWREG_BP (base + CAN_O_IF1CMD)= CAN_IF1M_BMSG |CAN_IF1M| CAN_CMIF1M| CAN_MASK | CAN_CMIF1M| CAN_CMIF1M| CAN_CMIF1M| CAN_CMIF1M| CAN_CMIF1M| CAN_CMIF1MK_CONTROL_CMD_CMING_CMD| CAN_MASK | //启用 IF3以接收所有 RX 消息,无论是单播还是广播 HWREG_BP (base + CAN_O_IF3UPD)= IF3_mailboxes;//邮箱2到16 //设置 IF3,以便在从接口读取所有数据之前不会发生下一次 IF3更新 // CAN_IF3OBS 寄存器- IF3观察寄存器 // CAN_O_IF3OBS 是寄存器基址的偏移 //位:DATA_A (B3): 1 -在数据被读取前没有新的 IF3更新 //Data_B (b4):1 -在数据被读取前没有新的 IF3更新 HWREGH (base + CAN_O_IF3OBS)= CAN_IF3OBS_DATA_A | CAN_IF3OBS_DATA_B; //CAN_IF3OBS_IF3SM;//要求论坛执行 //清除所有未使用的邮箱的消息有效位 (邮箱=(LAST_BCast_MB + 1);邮箱<= LAST_CAN_MB;+mailbox) { HWREG_BP (base + CAN_O_IF1ARB)= 0;//将 MsgVal 设置为0 HWREG_BP (base + CAN_MSG_IFM_BM ) | CMO_IFD_邮箱= 1);CMIFD_CMD_CMD_CMD_CMD_CMD_CMD_CMD_CMD_CMD_CMD_CMD_CMD_CMD_CMD_CM //初始化后启动 CAN 模块 HWREGH (base + CAN_O_CTL)&=~(CAN_CTL_init | CAN_CTL_CCE); } //--- // DcanRX // CAN 接口上的接收消息。 ///---------------------------------- #define RCV_POMS_MASK (0x0000FFFE) void DcanRX (UINT32 base) { volatile UINT32 msgsPending = 0; volatile UINT16 msgCtrl; volatile UINT16 msgObs; msgObs = HWREGH (base + CAN_O_IF3OBS); //通过 IF3 (CAN 接口3)读取消息 RAM 中的所有传入消息 、同时((msgObs & CAN_IF3OBS_IF3UPD)=CAN_IF3OBS_IF3UPD) { //do //检查 消息 RAM 中设置了 NewData 位的 邮箱// msgsbs_rbp + HW21 (HW_MASK +) //检查 IF3观察寄存器以查看新数据是否显示在 IF3 - IF3Upd 位 //msgObs = HWREGH (base + CAN_O_IF3OBS); //检查 IF3以查看消息是否已自动传输到接口 //msgCtrl = HWREGH (base + CAN_O_IF3MCTL); //如果在 IF3中有消息,则将其放入 CAN Q //if (msgCtrl & CAN_IF3MCTL_NEWDAT)=CAN_IF3MCTL_NEWDAT) if (msgObs & CAN_IF3OBS_IF3PDD)=CAN_IF3OBS_IF3LD_NEWDAT)=CAN_3MCTL_NEWDAT (msgObs & CAN_QUEST_END)=cine.t_QUEST_CAN.trl.trl.t =cannu.trl.trl_cin_cinu.trl.trl.trl =cinu.trl.trl.c&can32.t_trl.trl_can32.t_canc (cannu.trl =can32.t_trl.trl.trl //低消息数据-字节0到3 canQueue.data[canQueue.size].high = HWREG_BP (base + CAN_O_IF3DATB);//高消息数据-字节4到7 +canQueue.size; } else { // CAN 队列溢出 DEBUG_log (0xFC200000 | msgObsGH);}-->---/---/---/---/---- // DcanTX // //将数据传输到 CAN 总线上的目标位置,或者如果 节点是自消息传送,则将其放入//本地通信队列中。 ///---------------------------------- void DcanTX (uint32 base、uint32 destID、uint32 low、uint32 high、uint16 len) { //在 IF1和 IF2之间切换每次发送 TODO 都可以执行此 操作//canIF =(canIFToggle)? 1:2; //canIFToggle =(canIFToggle)? 0:1; 易失性 UINT32 CANStatus; UINT16 loopCounts;//针对超时 易失性 UINT32 msgArb; //针对此控制器节点的消息-如果 (destID == cntrlRNodeAddr || AMST_ADDR_BCNI ==destID),请勿将其发送到总线,将其放入本地 CAN 队列中 { //本地节点单播或广播到自身的数据包,如果 (localCommQueue.size < CAN_queue_size) {{ CommQueue.data[localCommQueue.size].low = low; 溢出 CommQueue.data[localCommQueue_Queue.size].high = high;localCommQueue.data[localCommQueue.size]= 0x000+localCommLog.size];localCommlog.size.size];{// debug = localCommlog.size.size.size.s/size];{// localCommQueue_mailbox+0x000 } //将所有传出的消息发送到 CAN 总线-单播和广播 //使用 IF1 (接口1)作为 CAN TXS IF (destID != cntrlrNodeAddr) {// //设置 if 命令以读取仲裁值 // //设置对消息对象数据的请求。 //将报文对象传输到 IF 寄存器。 // HWREG_BP (base + CAN_O_IF1CMD)= CAN_IF1CMD_ARB | (TX_mailbox & CAN_IF1CMD_MSG_NUM_M); //确保 IF1不会忙于 IF1和 CAN RAM 之间的前一个传输 (HWREGH (base + CAN_O_IF1ARB) = CAN_WAIT + CAN_INUST_BIST_BID/ CAN_BID/ CAN_BIST_COMPB= BUSY (BUSY) = CAN_ING_BIST_CAN_IND/ CANIF1CMD/ CAN_BIST_BIST_CAN_CAN_BIST_CAN_CAN_COMPB) //将数据写入接口1 HWREG_BP (base + CAN_O_IF1DATA)=低电平; HWREG_BP (base + CAN_O_IF1DATB)=高电平; //如果(currdestID != destID) { HWREG_BP (base + CAN_O_IF1DATB)=高电平、则重置目标消息 ID (current-stdb!= destinb) | db = 1arb )| CAN_i_i_i_iDb (CAN_1stb) //在 RAM 中将 IF 消息对象传输到 TX 邮箱 //不更改方向、长度或邮箱 ID HWREG_BP (base + CAN_O_IF1CMD)=(CAN_IF1CMD_DATA_B | CAN_IF1CMD_DATA_A |/ HWCAN_IF1CMD_CONTROL | CAN_IF1CMD_QST | CAN_CMD_QST | CAN_CMD_QST | CAN_CMIF1QST | CAN_CMD_PRBQ | CAN_Q1CMD_QCMD_| CAN_CMD_QST | CAN_CMD_PRBQ //HWREG_BP (base + CAN_O_IF1CMD)= 1; //CanbRegs.CANIF1CMD.bit.MSG_NUM = 1; //HWREG_BP (base + CAN_O_IF1CMD)|=(1 & CAN_IF1CMD_MSG_MSG_M); //检查总线 是否一直等待 或不确认任何恢复/至少在此处进行任何传输/不会在此处进行。 让我们通过 以下方式进行恢复并获取消息:/*loopCounts = 0; canStatus = HWREG (base + CAN_O_ES); while (!(CANStatus & CAN_ES_Es_TXOK)&& loopCount++< LOOP_Counts) { canStatus = HWREG (base + CAN_O_ES); if (loopCounts + 1 >= ROLOCK_RECORECORECODE_RECO0_RECODE_COUNT[0x000] (LOCK_RECORECORECODE_COUNT_RECODEBUG); }CANTRIGNOT_COUNT_RECORECORECODE_COUNT_RECORECODE_COUNT_LK = 0x000_COUNT_RECORECORECORECORECORECO } */} }//------------------ //文件结尾 ///-------------------------------------------------------
谢谢-
Mary