Hi
I am using AN1798 to calculate my bit timing. The following are the details of the bus.
Bus Length = 0.4m
Transceiver (NXP, TJA1041) propogation delay = max 255ns
Bit Rate: 125kbps which is well within the capabilities of the transceiver chip
The hardware set up is 3 nodes one is dormant though on the bus and just provides power to the other 2. Each node uses an MCF51JM128 and an NXP TJA1041.
The following is the bit timing information calculated from AN1798.
BUS CLK (0) or External CLK (1) | 1 |
Cable Length (m) | 0.4 |
Tprop_delay_cable | 2.000E-009 |
Tprop_delay_transceiver | 2.500E-007 |
Tprop_seg | 5.040E-007 |
External CLK | 24000000 |
BUS CLK | 12000000 |
Prescaler | 16 |
CAN CLK | 1500000 |
tQ | 6.67E-007 |
CAN Bit Rate | 1.25E+005 |
tQ per Bit | 12 |
PROP_SEG | 1 |
Tq per Bit – PROP_SEG – Sync_SEG | 10 |
PHASE_SEG1 | 5 |
PHASE_SEG2 | 5 |
RJW | 4 |
Oscillator Requirements: EQ10 | 0.0167 |
EQ11 | 0.0166 |
Required Oscillator Tolerance | 1.6556% |
Now using these values data passes onto the CAN_H CAN_L lines.
The system is such that node 1 transmits a message onto the bus and then waits for a reply from node 2 in a do while loop:
do
{
if(j==0)
{
while(SendByte(fourPtr)!=0) //this is place marker to show me where the code is over the serial port
{
}
}
j++;
(void)CAN_CheckStatusMB( 2, status ); //check buffer 2 status
}
while ( status[0] != NEWDATA); //if data has been received break out of the do while loop
while(SendByte(fivePtr)!=0) //this is place marker to show me where the code is over the serial port
{
}
(void)CAN_ReadDataMB(2, dataR); //read data from buffer 2
Now I'm not sure where to go to from here short of trying every possible bit timing configuration. I just can't seem to get the silly bus to receive messages can anyone see any issues with my CAN Bit Timing? Please don't hesitate to ask for further information!
Solved! Go to Solution.
Alright it now works, the ISR's in the mscan driver provided by freescale are unassigned to a vector number.
you have to change
interrupt void CAN_TransmitISR to interrupt 97 void CAN_TransmitISR
and
interrupt void CAN_ReceiveISR to interrupt 96 void CAN_ReceiveISR
Seems right. Did't you forget to subtract one from phase_seg's to get TSEGx settings? :
TSEG1 = PROP_SEG + PHASE_SEG1 - 1
TSEG2 = PHASE_SEG2 - 1
Using scope you could check your bitrate easily. Disconnect your MSCAN node from the bus and send some message. Shortest high or low pulse you see on the scope is bit time and should equal 8us for 125kbps bitrate.
Hi Kef
Thanks for your response.
I checked the bit rate and it is correct at 8us per bit so I think the timing calculations are working properly and the code is subtracting one for TSeG1 and TSEG2.
What I have found however is that data will only pass onto the bus when there is no other node on the bus. So if I connect two nodes onto the bus no data will appear on CAN_H/CAN_L. If I change the timing of one of the nodes so that the two nodes do not match then again data will appear on CAN_H/CAN_L. I have no idea why this would be the case. Why should adding a second active node to the bus stop all data on the bus?
Alright I have verified that actually there is communication and information is being received by the hardware of the receiving node.
The issue is actually the driver. For some reason the Freescale CAN Driver isn't receiving the data. However because a message is sent and an ACK is returned the data must be there.
Alright it now works, the ISR's in the mscan driver provided by freescale are unassigned to a vector number.
you have to change
interrupt void CAN_TransmitISR to interrupt 97 void CAN_TransmitISR
and
interrupt void CAN_ReceiveISR to interrupt 96 void CAN_ReceiveISR
> Alright it now works, the ISR's in the mscan driver provided by freescale are unassigned to a vector number.
That isn't Freescale's problem.
The "interrupt <vector> void name" syntax is a custom extension of the compiler you're using.
Firstly, as a "convenience" it is changing the standard ABI Function Prologue to one that saves all of the registers required of an interrupt routine. Many compilers do that, but not necessarily the same way. The CodeSourcery GCC compiler we use requires the format:
__attribute__((interrupt_handler)) static void uart_isr( void );
Secondly, as another "convenience", providing the vector in that line has the compiler fill in the vector table for you automatically. That is less common. The usual way is to have code write to the vector table (if it is in RAM) or you have to provide a "vector.S" file listing all your interrupt functions.
Documentation provided with your compiler and development system should detail how to port "standard driver code" to use the features that it provides.
Tom
I'm using the same compiler as the code was written and tested in there should be no need to port anything. Although thank you for pointing that out for me I shall take note the future.
I should add that the acceptance registers are set all set to 0xFF.