主题中讨论的其他器件:ISO1050
大家好、我将使用 CAN 分析仪测试 CAN 模块。 F28075+ ISO1050连接到 CAN 分析仪。
我可以使用下面的代码将数据发送到 CAN 分析仪、但无法从 CAN 分析仪接收数据。 (当 CAN 分析仪向 F28075发送数据时、CANA.CAN_IF2MCTL.bit.NewDat 永远不会被设置为1)。
请帮助您查看我的代码有什么问题?
该代码基于示例代码 CAN_loopback_bitfields.c
//
//文件: CAN_loopback_bitfields.c
//
//标题: 演示基本 CAN 设置和使用的示例。
//
//! addtogroup cpu01_example_list
//!
使用位字段的 CAN 外部环回(CAN_loopback_bitFields)
//!
//! 重要说明:位字段标头是否需要编译器 v16.6.0.STS 和更高版本!
//!
//! 该示例使用位域报头、显示了中 CAN 的基本设置
//! 以便在 CAN 总线上发送和接收消息。 CAN
//! 外设配置为发送具有特定 CAN ID 的消息。
//! 然后、使用简单的延迟每秒传输一条消息
//! 用于计时的环路。 发送的消息是一个4字节的消息
//! 包含一个递增模式。
//! 此示例将 CAN 控制器设置为外部环回测试模式。
//! 发送的数据在 CAN0TX 引脚上可见、可通过接收
//! 适当的邮箱配置。
//!
//
//######################################################################################################################
//$TI 发行版:F2807x 支持库 V210 $
//$Release Date:Tue Nov1 15:42:43 CDT 2016 $
//版权所有:版权所有(C) 2014-2016 Texas Instruments Incorporated -
// http://www.ti.com/ 保留所有权利$
//######################################################################################################################
//
//包含的文件
//
#include "F28x_Project.h"
//
//定义
//
#define CAN_MSG_ID 0x1111
#define CAN_TX_MSG_OBJ 1
#define CAN_RX_MSG_OBJ 2 // 这里是定义1号邮箱是发送,2号邮箱是接收。
#define CAN_MAX_BIT_DIFFERS_( 13) //最大 CAN 位时序除数
#define CAN_MIN_BIT_DIMINUSESCULE (5) //最小 CAN 位时序除数
#define CAN_MAX_PRE_DIFFERS_1024 ( 1024)//最大 CAN 预除数
#define CAN_MIN_PRE_DIMINUSTERINL (1) //最小 CAN 预除数
#define CAN_BTR_BRP_M (0x3F)
#define CAN_BTR_BRPE_M (0xF0000)
//
//全局
//
uint32_t rec1;
unsigned char ucTXMsgData[4]={0x1、0x2、0x3、0x4};// TX 数据
unsigned char ucRXMsgData[4]={0x5、0x6、0x7、0x8}; // RX 数据
uint32_t messageSize = sizeof (ucTXMsgData); //消息大小(DLC)
volatile unsigned long msgCount = 0;//一个跟踪的计数器
//发送次数
//成功。
volatile unsigned long errFlag = 0; //一个用于指示某些标志的标志
//发生传输错误。
静态常量 uint16_t canBitValues[]= // 设置比特率的时候会用到;
{
0x1100、// TSEG2 2、TSEG1 2、SJW 1、除以5
0x1200、// TSEG2 2、TSEG1 3、SJW 1、除以6
0x2240、// TSEG2 3、TSEG1 3、SJW 2、分频7
0x2340、// TSEG2 3、TSEG1 4、SJW 2、8分频
0x3340、// TSEG2 4、TSEG1 4、SJW 2、9分频
0x3440、// TSEG2 4、TSEG1 5、SJW 2、10分频
0x3540、// TSEG2 4、TSEG1 6、SJW 2、分频11
0x3640、// TSEG2 4、TSEG1 7、SJW 2、12分频
0x3740 // TSEG2 4、TSEG1 8、SJW 2、分频13
};
typedef 枚举
{
//! 发送报文对象。
MSG_obj_type_transmit、
//! 接收报文对象。
MSG_OBJ_TYPE_Receive
}
msgObjType;
//
//函数原型
//
uint32_t setCANBitRate (uint32_t sourceClock、uint32_t bitrate); // 设置比特率;
void setupMessageObject (uint32_t Objid、uint32_t msgid、msgObjType msgType); // 设置消息对象;
void sendCANMessage (uint32_t Objid); // 发送can信息;
bool getCANMessage (uint32_t Objid); // 接收can信息;
//
//主函
//
内部
main (空)
{
//
//初始化系统控制:
// PLL、安全装置、启用外设时钟 // 初始化系统时钟,PLL,外设时钟等
//此示例函数位于 F2807x_sysctrl.c 文件中。
//
InitSysCtrl(); // 系统初始化里就已经讲外设时钟初始化了。
//
//初始化 GPIO:
//此示例函数位于 F2807x_GPIO.c 文件和中
//说明了如何将 GPIO 设置为其默认状态。
//
InitGpio();
GPIO_SetupPinMux (62、GPIO_MUX_CPU1、6); //GPIO30 - CANRXA // 这几个函数都是在gpio c里定义的;
GPIO_SetupPinMux (63、GPIO_MUX_CPU1、6); //GPIO31 - CANTXA
GPIO_SetupPinOptions (62、GPIO_INPUT、GPIO_异 步);
GPIO_SetupPinOptions (63、GPIO_OUTPUT、GPIO_PushPull);
//
//初始化 CAN-A 控制器
//
InitCAN();
//
//设置可以关闭 SYSCLKOUT
//
ClkCfgRegs.CLKSRCCTL2.bit.CANABCLKSEL = 0; // CAN clock为系统时钟;
//
//设置 CAN 总线的比特率。 此函数设置 CAN
针对标称配置的//总线时序。
//在此示例中、CAN 总线设置为500kHz。
//
//有关的更多信息,请查阅数据表
// CAN 外设时钟。
//
uint32_t status = setCANBitRate (120000000、50000); // 这里设置的sourceclock是200M,比特率是500k
//
//如果请求的值太小或太大,则捕获错误
//
if (status =0)
{
errFlag++;
ESTOP0; //在此处停止并处理错误
}
//
//步骤3. 清除所有中断并初始化 PIE 矢量表:
//禁用 CPU 中断
//
Dint; // 禁止中断;
//
//将 PIE 控制寄存器初始化为默认状态。
//默认状态为禁用所有 PIE 中断和标志
//被清除。
//此函数位于 F2807x_PIECTRL.c 文件中。
//
InitPieCtrl();
//
//禁用 CPU 中断并清除所有 CPU 中断标志:
//
IER = 0x0000;
IFR = 0x0000;
//
//使用指向 shell 中断的指针初始化 PIE 矢量表
//服务例程(ISR)。
//这将填充整个表,即使是中断也是如此
//在本例中未使用。 这对于调试很有用。
//可以在 F2807x_DefaultIsr.c 中找到 shell ISR 例程
//此函数位于 F2807x_PieVect.c 中
//
InitPieVectTable();
//
//启用测试模式并选择外部环回。
//
/*CanaRegs.CAN_CTL.bit.Test = 1; // 通过注释掉这两句来禁用测试模式。
CANaRegs.CAN_TEST.BIT.EXL = 1; // EXL 外部循环使能位;*
/* CanaRegs.CAN_CTL.bit.Test = 0; // 该位为0后,测试寄存器里面的功能就全部取消;*
//
//初始化将用于发送 CAN //初始化将用于发送CAN的消息对象;的消息对象
//消息。 这个实际是上是配置邮箱 μ s
//
setupMessageObject (CAN_TX_MSG_obj、CAN_MSG_ID、MSG_OBJ_TYPE_transmit);
//
//初始化将用于接收 CAN 的消息对象
//消息。
//
setupMessageObject (CAN_RX_MSG_obj、CAN_MSG_ID、MSG_OBJ_TYPE_Receive);
//
//启用 CAN 以进行操作。
//
CANaRegs.CAN_CTL.bit.Init = 0;
//
//输入循环以发送消息。 根据、将发送一条新消息
//秒。 4字节的消息内容将被视为无符号
// long 并每次递增1。
//
for (;;)
{
//
//使用对象1发送 CAN 消息(与不一样
// CAN ID、在本例中也是1)。 此函数将导致
//要立即传输的消息。 // 发送信息1,
//
/* sendCANMessage (CAN_TX_MSG_obj); // CAN_TX_MSG_obj ID=1*/
//
//现在等待1秒后再继续
//
DELAY_US (1000*1000);
//
//获取接收消息
//
getCANMessage (CAN_RX_MSG_obj);
//
//确保接收到的数据与发送的数据匹配
//
/* if ((*(unsigned long *) ucTXMsgData)!=(*(unsigned long *) ucRXMsgData))
{
errFlag++;
asm (" ESTOP0");
}*/
//
//递增成功的消息计数和中的值
//传输的消息数据。
//
msgCount++;
/* (*(unsigned long *) ucTXMsgData)++;*/
}
}
//
// setCANBitRate -根据器件时钟(Hz)设置 CAN 比特率
// 和所需的比特率(Hz)
//
uint32_t setCANBitRate (uint32_t sourceClock、uint32_t 比特率)
{
uint32_t 设计位置;
uint32_t canBits;
uint32_t 预分频;
uint32_t regValue;
uint16_t canControlValue;
//
//计算所需的时钟速率。
//
desedRatio = sourceClock/bitrate;
//
//确保所需比率不会太大。 这将强制执行
//要求比特率大于请求的。
//
if ((sourceClock / desedRatio)>位速率)
{
希望+=1;
}
//
//检查所有可能的值以查找匹配的值。
//
while (希望的位置<= CAN_MAX_PRE_DIFFERS_CAN_MAX_BIT_DIFFERS_DIFFERS_CAN_MAX_BIT_DIFFERS_DIFFERS_OUR)
{
//
//循环遍历所有可能的 CAN 位分频器。
//
对于(CANBits = CAN_MAX_BIT_DIFFERS_DIFFERS_IN;
CANBits >= CAN_min_bit_di遮 阳板;
坎比特:-)
{
//
//对于一个给定的 CAN 位分频值、保存预分频值。
//
预分频=需要的 Ratio / canBits;
//
//如果计算出的分频值与所需的时钟比率相匹配
//返回这些比特率并设置 CAN 位时序。
//
if ((preDivide * canBits)==desedRatio)
{
//
//通过添加位时序开始构建位时序值
//在时间份额中。
//
regValue = canBitValues[canBits - CAN_MIN_BIT_DIESS];
//
//要设置位时序寄存器,控制器必须是
//放置
//处于初始化模式(如果尚未),以及配置更改
//位被启用。 应保存寄存器的状态
//这样就可以恢复。
//
canControlValue = CanaRegs.CAN_CTL.ALL;
CANaRegs.CAN_CTL.bit.Init = 1;
CANARegs.CAN_CTL.bit.CCE = 1;
//
//现在添加位速率的预分频器。
//
regValue |=((preDivide-1)& CAN_BTR_BRP_M)|
(((预分频器- 1)<< 10)& CAN_BTR_BRPE_M);
//
//在和中设置时钟位
//预分频器。
//
CanaRegs.CAN_BTR.All = regValue;
//
//恢复保存的 CAN 控制寄存器。
//
CanaRegs.CAN_CTL.ALL = canControlValue;
//
//返回计算出的比特率。
//
return (sourceClock /(preDivide * canBits));
}
}
//
//将除数上移一并重新查看。 只有在极少数情况下才会发生这种情况
//找到该值需要2个以上的循环。
//
需要的信息++;
}
返回0;
}
//
// setupMessageObject -将消息对象设置为发送或接收
//
void setupMessageObject (uint32_t Objid、uint32_t msgid、msgObjType msgType)
{
//
//等待忙位清零。
//
while (CANaRegs.CAN_IF1CMD.bit.BUSY)
{
}
//
//清除并写出寄存器以编程报文对象。
//
CANARegs.CAN_IF1CMD.ALL = 0;
CANaRegs.CAN_IF1MSK.ALL = 0;
CanaRegs.CAN_IF1ARB.all = 0;
CANaRegs.CAN_IF1MCTL.ALL = 0;
//
//设置 Control、Mask 和 ARB 位,以便将它们传送到
//消息对象。
//
CANARegs.CAN_IF1CMD.bit.Control = 1;
CanaRegs.CAN_IF1CMD.bit.ARB = 1;
CANARegs.CAN_IF1CMD.bit.Mask = 1;
CANARegs.CAN_IF1CMD.bit.DIR = 1;
//
//设置发送方向 //
//
if (msgType = MSG_obj_type_transmit)
{
CANARegs.CAN_IF1ARB.bit.Dir = 1; //
}
//
//设置消息 ID (此示例假定11位 ID 掩码) //
//
CanaRegs.CAN_IF1ARB.bit.ID = msgid; //
CANARegs.CAN_IF1ARB.bit.MsgVal = 1; //
//
//设置数据长度,因为这是为所有传输设置的。 这是
//也是单次传输,而不是 FIFO 传输,所以将 EOB 位置位。
//
CanaRegs.CAN_IF1MCTL.bit.DLC =消息大小; //
CANaRegs.CAN_IF1MCTL.bit.EOB = 1; //
//
//将数据传输到消息对象 RAM // 将data传到消息RAM;
//
CANARegs.CAN_IF1CMD.bit.MSG_NUM = Objid; //
}
//
// sendCANMessage -从 传输数据;报文对象发送数据//μ s
//
空 sendCANMessage (uint32_t Objid)
{
//
//等待忙位清零。
//
while (CANaRegs.CAN_IF1CMD.bit.BUSY)
{
}
//
//将要传输的数据写入数据 A 和数据 B 接口寄存器
//
uint16_t 索引;
for (index = 0;index < messageSize;index++)
{
switch (索引)
{
情况0:
CANARegs.CAN_IF1DATA.bit.Data_0 = ucTXMsgData[index]; //
中断;
案例1:
CANARegs.CAN_IF1DATA.bit.Data_1 = ucTXMsgData[index];
中断;
案例2:
CANARegs.CAN_IF1DATA.bit.Data_2 = ucTXMsgData[index];
中断;
案例3:
CANARegs.CAN_IF1DATA.bit.Data_3 = ucTXMsgData[index];
中断;
案例4:
CANARegs.CAN_IF1DATB.bit.Data_4 = ucTXMsgData[index];
中断;
情况5:
CANARegs.CAN_IF1DATB.bit.Data_5 = ucTXMsgData[index];
中断;
案例6:
CANARegs.CAN_IF1DATB.bit.Data_6 = ucTXMsgData[index];
中断;
案例7:
CANARegs.CAN_IF1DATB.bit.Data_7 = ucTXMsgData[index];
中断;
}
}
//
//设置写入方向并设置要传输到的数据 A/数据 B
//消息对象
//
CANaRegs.CAN_IF1CMD.ALL = 0x830000; // DIR=1;dataaa,dataB=1;
//
//设置 Tx 请求位
//
CANARegs.CAN_IF1CMD.bit.TXRQST = 1;
//
//将报文对象传输到由指定的报文对象
// Objid。
//
CANaRegs.CAN_IF1CMD.bit.MSG_NUM = Objid; ;μ A
}
//
// getCANMessage -检查消息对象是否有新数据。
// 如果是新数据、则写入数组并返回 true。
// 如果没有新数据、则返回 false。
//
bool getCANMessage (uint32_t Objid)
{
bool 状态;
//
//设置要读取的消息数据 A、数据 B 和控制值
//从报文对象请求数据时。
//
CANARegs.CAN_IF2CMD.ALL = 0;
CANARegs.CAN_IF2CMD.bit.Control = 1; ;μ A
CANARegs.CAN_IF2CMD.bit.DATA_A = 1;
CANARegs.CAN_IF2CMD.bit.DATA_B = 1;
//
//将报文对象传输到报文对象 IF 寄存器。
//
CANARegs.CAN_IF2CMD.bit.MSG_NUM = Objid;
//
//等待忙位清零。
//
while (CANaRegs.CAN_IF2CMD.bit.BUSY)
{
}
//
//查看是否有可用的新数据。
//
if (CANaRegs.CAN_IF2MCTL.bit.NewDat = 1) // 有新的消息写入;
{
//
//从 CAN 寄存器中读出数据。
//
uint16_t 索引;
for (index = 0;index < messageSize;index++)
{
switch (索引)
{
情况0:
ucRXMsgData[index]= CANaRegs.CAN_IF2DATA.bit.Data_0;
中断;
案例1:
ucRXMsgData[index]= CANaRegs.CAN_IF2DATA.bit.Data_1;
中断;
案例2:
ucRXMsgData[index]= CANaRegs.CAN_IF2DATA.bit.Data_2;
中断;
案例3:
ucRXMsgData[index]= CANaRegs.CAN_IF2DATA.bit.Data_3;
中断;
案例4:
ucRXMsgData[index]= CANaRegs.CAN_IF2DATB.bit.Data_4;
中断;
情况5:
ucRXMsgData[index]= CANaRegs.CAN_IF2DATB.bit.Data_5;
中断;
案例6:
ucRXMsgData[index]= CANaRegs.CAN_IF2DATB.bit.Data_6;
中断;
案例7:
ucRXMsgData[index]= CANaRegs.CAN_IF2DATB.bit.Data_7;
中断;
}
}
//
//清除新数据标志
//
CANaRegs.CAN_IF2CMD.bit.TxRqst = 1; // 清除 newDATA 位;
//等待忙位清零。
//
while (CANaRegs.CAN_IF2CMD.bit.BUSY)
{
}
//
//将报文对象传输到报文对象 IF 寄存器。
//
CANARegs.CAN_IF2CMD.bit.MSG_NUM = Objid;
状态= true;
}
其他
{
状态= false;
}
退货(状态);
}