View previous topic :: View next topic |
Author |
Message |
Ranfo
Joined: 08 Sep 2008 Posts: 38
|
DSPIC33 ECAN What am I missing? |
Posted: Wed Nov 23, 2016 9:16 am |
|
|
I am trying to send CAN messages with a PIC33EP512MC806. Not having any luck. Need help! Nothing on the CAN_TX pin. I have used the CAN bus on other PIC parts, but cannot find working examples for PIC33.
The test hangs on while (!can_tbe()); If I remove this the terminal output is:
Code: | PUT 0: ID=576 LEN=8 PRI=3 EXT=0 RTR=0
DATA = 63 30 84 40 A5 50 C6 60 |
Code: |
#include "can-pic24.c"
#define CAN_RX PIN_B15 // CANRX1
#define CAN_TX PIN_F4 // CANTX1
// --- CAN Bus Global Variables ---------------------------------------------
int8 can_in_data[8];
int8 can_out_data[8];
struct rx_stat rxstat;
int32 rx_id;
int rx_len;
int32 tx_id = 0x240; // default ID
int1 tx_rtr = 0;
int1 tx_ext = 0;
int tx_len = 8;
int tx_pri = 3;
// Initialize
// ----------------------------------------------------------------------------
void can_initialize() {
pin_select("C1RX",CAN_RX);
pin_select("C1TX",CAN_TX);
can_init(); // 62.5k baud for ECAN
}
// CAN Test
// ----------------------------------------------------------------------------
void can_test() {
int8 i;
while (!can_tbe()); // Wait for transmit buffer ready
i = can_putd(tx_id, can_out_data, tx_len,tx_pri,tx_ext,tx_rtr);
if (i != 0xFF) { //success, a transmit buffer was open
fprintf(CON6, "\r\nPUT %U: ID=%LU LEN=%U ", i, tx_id, tx_len);
fprintf(CON6, "PRI=%U EXT=%U RTR=%U\r\n DATA = ", tx_pri, tx_ext, tx_rtr);
for (i=0;i<tx_len;i++) {
fprintf(CON6, "%X ", can_out_data[i]);
}
fprintf(CON6, "\r\n");
}
else { //fail, no transmit buffer was open
fprintf(CON6, "\r\nFAIL on PUTD\r\n");
}
} |
|
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1348
|
|
Posted: Wed Nov 23, 2016 9:37 am |
|
|
I don't know much about CAN bus myself, but try the compile time pin select method:
Code: |
#pin_select C1RX=CAN_RX
#pin_select C1TX=CAN_TX
|
Some PIC24 and dsPIC chips have fuse settings that can prevent the function call from always working. Compile time ones should work though. |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Wed Nov 23, 2016 9:37 am |
|
|
I don't know what you are missing, but what I do know is that your sample code is missing some important bits: the CAN set-up defines (normally before the include of can-PIC24.c), any call to can-initialize, all fuses and processor set-up. Therefore it cannot be compiled and cannot be run.
It is behaving as if the CAN sub-system has not been initialised. Hence my interest in where and how it is initialised. |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1907
|
|
Posted: Wed Nov 23, 2016 9:40 am |
|
|
Something like 4 or 5 years ago I did my first project with a dsPIC33 device and, like you, I quickly found that the CCS CAN functions didn't work. This was back with versions 4.099 - 4.141. I had to do my own CAN drivers from scratch, but I'm actually glad I did because I ended up implementing DMA to handle CAN and it made my projects way faster than if the CCS functions had worked.
If you're on a version 5.-something of the compiler I would have assumed that CCS had ironed out the CAN bugs with the dsPICs by now.
Sorry, can't share the CAN code. Just read the ECAN section of your PIC's FRM (family reference manual) and it's not that hard to do. |
|
|
Ranfo
Joined: 08 Sep 2008 Posts: 38
|
|
Posted: Wed Nov 23, 2016 11:32 am |
|
|
newguy,
Can you at least give me a hint as to why the CCS functions do not work? Re-writing can-PIC24.c is a daunting task. |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1907
|
|
Posted: Wed Nov 23, 2016 11:50 am |
|
|
I didn't dig too deeply into why but from what I recall, the CCS functions were pointing to wrong registers in the late 4.xxx compilers. There's another aspect in that the set of registers for CAN and even ECAN for the 8 bit processors (PIC18) are more-or-less identical. ECAN, for the dsPICs, is a completely different animal with way more registers and much more flexibility, but that also brings increased code complexity.
Here's another hint. In the FRM ECAN document you'll find an explanation of all the registers involved with CAN. From there you can figure out how to set up your filters & masks for reception, along with other registers used to set up how the filters are allocated (TX or RX).
In the section dealing with CAN transmission, there is a table of the 8 words (int16 registers) that must be properly set up in order to send a CAN packet. That same format is exactly how those registers are filled when a message is received. You just need your own custom code to fill those registers properly given your CAN data, and then trigger an immediate transmit. When a CAN receive interrupt fires, that same data is available - you just need to figure out where and properly extract everything from those 8 words.
Just don't worry about all the CCS functions and take care to properly write your own functions to a) set up the CAN, b) transmit a message (better if you can set up a buffer which your code can fill, and write other code to automatically take data from that buffer and have it place it in the CAN outbound TX registers when they're empty), and c) receive messages. It honestly isn't difficult. Maybe a little time consuming, but certainly not difficult. |
|
|
Ranfo
Joined: 08 Sep 2008 Posts: 38
|
|
Posted: Mon Jun 26, 2017 12:26 pm |
|
|
Can someone tell me what values should go here?
#use DELAY(clock=80M, crystal=16M)
#define CAN_CANCKS ???
#define CAN_BRG_PRESCALAR ???
#define CAN_BRG_PHASE_SEGMENT_1 ???
#define CAN_BRG_PHASE_SEGMENT_2 ???
#define CAN_BRG_SYNCH_JUMP_WIDTH ???
#define CAN_BRG_PROPAGATION_TIME ???
Looking for 100 or 125 Kb/s |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Mon Jun 26, 2017 12:43 pm |
|
|
Use the online calculator to work out the values. Remember the clock feeding the CAN is clock/2.
I would second the suggestion to use the #pin_select method, rather than the inline format. The inline commands will not work if the IOL1WAY fuse is set. |
|
|
Ranfo
Joined: 08 Sep 2008 Posts: 38
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Mon Jun 26, 2017 2:40 pm |
|
|
Beware of this one. If you look at the MicroChip one, it requires you to specify the clock feeding the Can peripheral. This one doesn't, which almost certainly implies it is written for PIC18's. The PIC24, clocks the peripherals twice as fast for a given CPU clock.
If can_tbe is not going true, it almost certainly implies the can peripheral is not actually running. Look at the initialisation in the examples. What is your compiler version?. |
|
|
Ranfo
Joined: 08 Sep 2008 Posts: 38
|
|
Posted: Tue Jun 27, 2017 7:08 am |
|
|
Reading:
Understanding Microchip’s CAN Module Bit Timing
and
Section 21. Enhanced Controller Area Network (ECAN™)
Not really understanding much of it, but I see now why nobody knows how to use the Microchip CAN Bus. Is there a better calculator than the one I posted above? Maybe some documentation specific to the can-pic24.c?
PCWHD 5.073 |
|
|
Ranfo
Joined: 08 Sep 2008 Posts: 38
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Tue Jun 27, 2017 8:15 am |
|
|
Honestly, you are making things too complex....
The timings for the phase segments etc., supplied by CCS will work fine, they are for 125KHz. All you need to do is calculate the prescaler value to give the same Tq they use, for your master clock. Their examples use 8Tq/bit for 125KHz (so a Tq of 1uSec). |
|
|
Ranfo
Joined: 08 Sep 2008 Posts: 38
|
|
Posted: Tue Jun 27, 2017 8:59 am |
|
|
Ttelmah wrote: | All you need to do is calculate the prescaler value to give the same Tq they use, for your master clock. |
Can you expand on this a bit? How do I calculate Tq and what do I do with the value once I calculate it? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Tue Jun 27, 2017 9:25 am |
|
|
Tq is the basic internal 'lump' which the CAN state machine clocks from, and all transactions are handled in terms of.
The settings CCS give are for a Tq of 1uSec, then 8 counts of this clock per bit. (So 125KHz).
Simply adjust the prescaler to give this Tq from your master clock. You don't need to change anything else. |
|
|
|