Other Parts Discussed in Thread: ISO1050
Hi, I'm testing the CAN module with can analyzer. F28075+ ISO1050 to a CAN analyzer.
I can send the data to CAN analyzer with the code below, but no able to receive data from the can analyzer. (CanaRegs.CAN_IF2MCTL.bit.NewDat will never be set to 1 when CAN analyzer is sending data to F28075).
Could you please help to see what's wrong with my code?
The code was based on the example code can_loopback_bitfields.c
//
// FILE: can_loopback_bitfields.c
//
// TITLE: Example to demonstrate basic CAN setup and use.
//
//! \addtogroup cpu01_example_list
//! <h1>CAN External Loopback Using Bitfields (can_loopback_bitfields)</h1>
//!
//! IMPORTANT: CAN Bitfield headers require compiler v16.6.0.STS and newer!
//!
//! This example, using bitfield headers, shows the basic setup of CAN in
//! order to transmit and receive messages on the CAN bus. The CAN
//! peripheral is configured to transmit messages with a specific CAN ID.
//! A message is then transmitted once per second, using a simple delay
//! loop for timing. The message that is sent is a 4 byte message that
//! contains an incrementing pattern.
//! This example sets up the CAN controller in External Loopback test mode.
//! Data transmitted is visible on the CAN0TX pin and can be received with
//! an appropriate mailbox configuration.
//!
//
//###########################################################################
// $TI Release: F2807x Support Library v210 $
// $Release Date: Tue Nov 1 15:42:43 CDT 2016 $
// $Copyright: Copyright (C) 2014-2016 Texas Instruments Incorporated -
// http://www.ti.com/ ALL RIGHTS RESERVED $
//###########################################################################
//
// Included Files
//
#include "F28x_Project.h"
//
// Defines
//
#define CAN_MSG_ID 0x1111
#define CAN_TX_MSG_OBJ 1
#define CAN_RX_MSG_OBJ 2 // 这里是定义1号邮箱是发送,2号邮箱是接收。
#define CAN_MAX_BIT_DIVISOR (13) // The maximum CAN bit timing divisor
#define CAN_MIN_BIT_DIVISOR (5) // The minimum CAN bit timing divisor
#define CAN_MAX_PRE_DIVISOR (1024) // The maximum CAN pre-divisor
#define CAN_MIN_PRE_DIVISOR (1) // The minimum CAN pre-divisor
#define CAN_BTR_BRP_M (0x3F)
#define CAN_BTR_BRPE_M (0xF0000)
//
// Globals
//
uint32_t rec1;
unsigned char ucTXMsgData[4] = {0x1, 0x2, 0x3, 0x4}; // TX Data
unsigned char ucRXMsgData[4] = {0x5, 0x6, 0x7, 0x8}; // RX Data
uint32_t messageSize = sizeof(ucTXMsgData); // Message Size (DLC)
volatile unsigned long msgCount = 0; // A counter that keeps track of the
// number of times the transmit was
// successful.
volatile unsigned long errFlag = 0; // A flag to indicate that some
// transmission error occurred.
static const uint16_t canBitValues[] = // 设置比特率的时候会用到;
{
0x1100, // TSEG2 2, TSEG1 2, SJW 1, Divide 5
0x1200, // TSEG2 2, TSEG1 3, SJW 1, Divide 6
0x2240, // TSEG2 3, TSEG1 3, SJW 2, Divide 7
0x2340, // TSEG2 3, TSEG1 4, SJW 2, Divide 8
0x3340, // TSEG2 4, TSEG1 4, SJW 2, Divide 9
0x3440, // TSEG2 4, TSEG1 5, SJW 2, Divide 10
0x3540, // TSEG2 4, TSEG1 6, SJW 2, Divide 11
0x3640, // TSEG2 4, TSEG1 7, SJW 2, Divide 12
0x3740 // TSEG2 4, TSEG1 8, SJW 2, Divide 13
};
typedef enum
{
//! Transmit message object.
MSG_OBJ_TYPE_TRANSMIT,
//! Receive message object.
MSG_OBJ_TYPE_RECEIVE
}
msgObjType;
//
// Function Prototypes
//
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
//
int
main(void)
{
//
// Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks // 初始化系统时钟,pll,外设时钟等
// This example function is found in the F2807x_SysCtrl.c file.
//
InitSysCtrl(); // 系统初始化里就已经讲外设时钟初始化了。
//
// Initialize GPIO:
// This example function is found in the F2807x_Gpio.c file and
// illustrates how to set the GPIO to its default state.
//
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_ASYNC);
GPIO_SetupPinOptions(63, GPIO_OUTPUT, GPIO_PUSHPULL);
//
// Initialize the CAN-A controller
//
InitCAN();
//
// Setup CAN to be clocked off the SYSCLKOUT
//
ClkCfgRegs.CLKSRCCTL2.bit.CANABCLKSEL = 0; // can clock为系统时钟;
//
// Set up the bit rate for the CAN bus. This function sets up the CAN
// bus timing for a nominal configuration.
// In this example, the CAN bus is set to 500 kHz.
//
// Consult the data sheet for more information about
// CAN peripheral clocking.
//
uint32_t status = setCANBitRate(120000000, 500000); // 这里设置的sourceclock是200M,比特率是500k
//
// If values requested are too small or too large, catch error
//
if(status == 0)
{
errFlag++;
ESTOP0; // Stop here and handle error
}
//
// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
//
DINT; // 禁止中断;
//
// Initialize the PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.
// This function is found in the F2807x_PieCtrl.c file.
//
InitPieCtrl();
//
// Disable CPU interrupts and clear all CPU interrupt flags:
//
IER = 0x0000;
IFR = 0x0000;
//
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if the interrupt
// is not used in this example. This is useful for debug purposes.
// The shell ISR routines are found in F2807x_DefaultIsr.c.
// This function is found in F2807x_PieVect.c.
//
InitPieVectTable();
//
// Enable test mode and select external loopback.
//
/*CanaRegs.CAN_CTL.bit.Test = 1; // Test mode disabled by commenting out these two sentences.
CanaRegs.CAN_TEST.bit.EXL = 1; // EXL 外部循环使能位;*/
/* CanaRegs.CAN_CTL.bit.Test = 0; // 该位为0后,测试寄存器里面的功能就全部取消;*/
//
// Initialize the message object that will be used for sending CAN //初始化将用于发送CAN的消息对象;
// messages. //这个实际是上是配置邮箱
//
setupMessageObject(CAN_TX_MSG_OBJ, CAN_MSG_ID, MSG_OBJ_TYPE_TRANSMIT);
//
// Initialize the message object that will be used for receiving CAN
// messages.
//
setupMessageObject(CAN_RX_MSG_OBJ, CAN_MSG_ID, MSG_OBJ_TYPE_RECEIVE);
//
// Enable the CAN for operation.
//
CanaRegs.CAN_CTL.bit.Init = 0;
//
// Enter loop to send messages. A new message will be sent once per
// second. The 4 bytes of message content will be treated as an unsigned
// long and incremented by one each time.
//
for(;;)
{
//
// Send the CAN message using object number 1 (not the same thing as
// CAN ID, which is also 1 in this example). This function will cause
// the message to be transmitted right away. // 发送信息1,
//
/* sendCANMessage(CAN_TX_MSG_OBJ); // CAN_TX_MSG_OBJ ID=1*/
//
// Now wait 1 second before continuing
//
DELAY_US(1000*1000);
//
// Get the receive message
//
getCANMessage(CAN_RX_MSG_OBJ);
//
// Ensure the received data matches the transmitted data
//
/* if((*(unsigned long *)ucTXMsgData) != (*(unsigned long *)ucRXMsgData))
{
errFlag++;
asm(" ESTOP0");
}*/
//
// Increment successful message count and the value in the
// transmitted message data.
//
msgCount++;
/* (*(unsigned long *)ucTXMsgData)++;*/
}
}
//
// setCANBitRate - Set the CAN bit rate based on device clock (Hz)
// and desired bit rate (Hz)
//
uint32_t setCANBitRate(uint32_t sourceClock, uint32_t bitRate)
{
uint32_t desiredRatio;
uint32_t canBits;
uint32_t preDivide;
uint32_t regValue;
uint16_t canControlValue;
//
// Calculate the desired clock rate.
//
desiredRatio = sourceClock / bitRate;
//
// Make sure that the Desired Ratio is not too large. This enforces the
// requirement that the bit rate is larger than requested.
//
if((sourceClock / desiredRatio) > bitRate)
{
desiredRatio += 1;
}
//
// Check all possible values to find a matching value.
//
while(desiredRatio <= CAN_MAX_PRE_DIVISOR * CAN_MAX_BIT_DIVISOR)
{
//
// Loop through all possible CAN bit divisors.
//
for(canBits = CAN_MAX_BIT_DIVISOR;
canBits >= CAN_MIN_BIT_DIVISOR;
canBits--)
{
//
// For a given CAN bit divisor save the pre divisor.
//
preDivide = desiredRatio / canBits;
//
// If the calculated divisors match the desired clock ratio then
// return these bit rate and set the CAN bit timing.
//
if((preDivide * canBits) == desiredRatio)
{
//
// Start building the bit timing value by adding the bit timing
// in time quanta.
//
regValue = canBitValues[canBits - CAN_MIN_BIT_DIVISOR];
//
// To set the bit timing register, the controller must be
// placed
// in init mode (if not already), and also configuration change
// bit enabled. The state of the register should be saved
// so it can be restored.
//
canControlValue = CanaRegs.CAN_CTL.all;
CanaRegs.CAN_CTL.bit.Init = 1;
CanaRegs.CAN_CTL.bit.CCE = 1;
//
// Now add in the pre-scalar on the bit rate.
//
regValue |= ((preDivide - 1) & CAN_BTR_BRP_M) |
(((preDivide - 1) << 10) & CAN_BTR_BRPE_M);
//
// Set the clock bits in the and the bits of the
// pre-scalar.
//
CanaRegs.CAN_BTR.all = regValue;
//
// Restore the saved CAN Control register.
//
CanaRegs.CAN_CTL.all = canControlValue;
//
// Return the computed bit rate.
//
return(sourceClock / ( preDivide * canBits));
}
}
//
// Move the divisor up one and look again. Only in rare cases are
// more than 2 loops required to find the value.
//
desiredRatio++;
}
return 0;
}
//
// setupMessageObject - Setup message object as Transmit or Receive
//
void setupMessageObject(uint32_t objID, uint32_t msgID, msgObjType msgType)
{
//
// Wait for busy bit to clear.
//
while(CanaRegs.CAN_IF1CMD.bit.Busy)
{
}
//
// Clear and Write out the registers to program the message object.
//
CanaRegs.CAN_IF1CMD.all = 0;
CanaRegs.CAN_IF1MSK.all = 0;
CanaRegs.CAN_IF1ARB.all = 0;
CanaRegs.CAN_IF1MCTL.all = 0;
//
// Set the Control, Mask, and Arb bit so that they get transferred to the
// Message object.
//
CanaRegs.CAN_IF1CMD.bit.Control = 1;
CanaRegs.CAN_IF1CMD.bit.Arb = 1;
CanaRegs.CAN_IF1CMD.bit.Mask = 1;
CanaRegs.CAN_IF1CMD.bit.DIR = 1;
//
// Set direction to transmit //
//
if(msgType == MSG_OBJ_TYPE_TRANSMIT)
{
CanaRegs.CAN_IF1ARB.bit.Dir = 1; //
}
//
// Set Message ID (this example assumes 11 bit ID mask) //
//
CanaRegs.CAN_IF1ARB.bit.ID = msgID; //
CanaRegs.CAN_IF1ARB.bit.MsgVal = 1; //
//
// Set the data length since this is set for all transfers. This is
// also a single transfer and not a FIFO transfer so set EOB bit.
//
CanaRegs.CAN_IF1MCTL.bit.DLC = messageSize; //
CanaRegs.CAN_IF1MCTL.bit.EoB = 1; //
//
// Transfer data to message object RAM // 将data传到消息RAM;
//
CanaRegs.CAN_IF1CMD.bit.MSG_NUM = objID; //
}
//
// sendCANMessage - Transmit data from the specified message object //传输数据;
//
void sendCANMessage(uint32_t objID)
{
//
// Wait for busy bit to clear.
//
while(CanaRegs.CAN_IF1CMD.bit.Busy)
{
}
//
// Write data to transfer into DATA-A and DATA-B interface registers
//
uint16_t index;
for(index = 0; index < messageSize; index++)
{
switch(index)
{
case 0:
CanaRegs.CAN_IF1DATA.bit.Data_0 = ucTXMsgData[index]; //
break;
case 1:
CanaRegs.CAN_IF1DATA.bit.Data_1 = ucTXMsgData[index];
break;
case 2:
CanaRegs.CAN_IF1DATA.bit.Data_2 = ucTXMsgData[index];
break;
case 3:
CanaRegs.CAN_IF1DATA.bit.Data_3 = ucTXMsgData[index];
break;
case 4:
CanaRegs.CAN_IF1DATB.bit.Data_4 = ucTXMsgData[index];
break;
case 5:
CanaRegs.CAN_IF1DATB.bit.Data_5 = ucTXMsgData[index];
break;
case 6:
CanaRegs.CAN_IF1DATB.bit.Data_6 = ucTXMsgData[index];
break;
case 7:
CanaRegs.CAN_IF1DATB.bit.Data_7 = ucTXMsgData[index];
break;
}
}
//
// Set Direction to write and set DATA-A/DATA-B to be transfered to
// message object
//
CanaRegs.CAN_IF1CMD.all = 0x830000; // DIR=1;dataA,dataB=1;
//
// Set Tx Request Bit
//
CanaRegs.CAN_IF1CMD.bit.TXRQST = 1;
//
// Transfer the message object to the message object specified by
// objID.
//
CanaRegs.CAN_IF1CMD.bit.MSG_NUM = objID; ;
}
//
// getCANMessage - Check the message object for new data.
// If new data, data written into array and return true.
// If no new data, return false.
//
bool getCANMessage(uint32_t objID)
{
bool status;
//
// Set the Message Data A, Data B, and control values to be read
// on request for data from the message object.
//
CanaRegs.CAN_IF2CMD.all = 0;
CanaRegs.CAN_IF2CMD.bit.Control = 1; ;
CanaRegs.CAN_IF2CMD.bit.DATA_A = 1;
CanaRegs.CAN_IF2CMD.bit.DATA_B = 1;
//
// Transfer the message object to the message object IF register.
//
CanaRegs.CAN_IF2CMD.bit.MSG_NUM = objID;
//
// Wait for busy bit to clear.
//
while(CanaRegs.CAN_IF2CMD.bit.Busy)
{
}
//
// See if there is new data available.
//
if(CanaRegs.CAN_IF2MCTL.bit.NewDat == 1) // 有新的消息写入;
{
//
// Read out the data from the CAN registers.
//
uint16_t index;
for(index = 0; index < messageSize; index++)
{
switch(index)
{
case 0:
ucRXMsgData[index] = CanaRegs.CAN_IF2DATA.bit.Data_0;
break;
case 1:
ucRXMsgData[index] = CanaRegs.CAN_IF2DATA.bit.Data_1;
break;
case 2:
ucRXMsgData[index] = CanaRegs.CAN_IF2DATA.bit.Data_2;
break;
case 3:
ucRXMsgData[index] = CanaRegs.CAN_IF2DATA.bit.Data_3;
break;
case 4:
ucRXMsgData[index] = CanaRegs.CAN_IF2DATB.bit.Data_4;
break;
case 5:
ucRXMsgData[index] = CanaRegs.CAN_IF2DATB.bit.Data_5;
break;
case 6:
ucRXMsgData[index] = CanaRegs.CAN_IF2DATB.bit.Data_6;
break;
case 7:
ucRXMsgData[index] = CanaRegs.CAN_IF2DATB.bit.Data_7;
break;
}
}
//
// Clear New Data Flag
//
CanaRegs.CAN_IF2CMD.bit.TxRqst = 1; // clear newDATA bit;
// Wait for busy bit to clear.
//
while(CanaRegs.CAN_IF2CMD.bit.Busy)
{
}
//
// Transfer the message object to the message object IF register.
//
CanaRegs.CAN_IF2CMD.bit.MSG_NUM = objID;
status = true;
}
else
{
status = false;
}
return(status);
}