Search |
 |
|
 |
| Author |
Message |
|
|
Posted: Feb 13, 2012 - 09:32 AM |
|

Joined: Jul 06, 2011
Posts: 3
|
|
Hi there
I have already use can on another µC like HCS08DZ60 (freescale)
I'm really surprise that there are not really clear information on error gesture...
I'm using MOB5 for TX and MOB1 for RX.
This configuration works fine without can error gesture...
Could you explain me those things ?
What's the difference between ENERR interrupt sources and the ENERG interrupt sources ?
In case of no ack, the CAN module must do some auto-retry. Could I have 1 interrupt by auto message or just 1 for the first ?
In case of auto-retry, the CAN module will become Error Active. How to aboard correctly this process ?
Excuse me for my poor english.
Tanks in advance for your help.
@++
Iko |
|
|
| |
|
|
|
|
|
Posted: Feb 13, 2012 - 04:02 PM |
|


Joined: Jun 22, 2004
Posts: 3849
Location: South West Utah, USA
|
|
|
ikoria wrote:
What's the difference between ENERR interrupt sources and the ENERG interrupt sources ?
Using the 7679H–CAN–08/08 version of the AT90CAN data sheet, look at the section 19.5.3 Acceptance Filter. The CAN state machine hardware receives all CAN bus traffic all the time, but your software has no access to any of this CAN data until after you setup and enable at least one Rx MOb task. When a Rx MOb task is enabled it uses the acceptance filter to decide which Rx CAN traffic to receive and which Rx CAN traffic to ignore. When an acceptance filter gets a match hit, the Rx MOb it selects becomes active.
When no Rx MOb is enabled, all CAN bus errors go into the ENERG (CANGIT.SERG, CANGIT.CERG, CANGIT.FERG and CANGIT.AERG) error bits. Since you have no enabled Rx MOb you will not have access to any of this CAN bus traffic, but you will be able to see the errors happening on the CAN bus through the general register CANGIT error bits.
When one or more Rx MOb is enabled and the acceptance filter gets a match hit, now this CAN bus traffic is sent to the MOb that the acceptance filter selected. The is how your software accesses any CAN bus traffic. As soon as a hit activates the selected MOb, all CAN bus errors now go into that MOb ENERR (CANSTMOB.BERR, CANSTMOB.SERR, CANSTMOB.CERR, CANSTMOB.FERR and CANSTMOB.AERR) error bits.
A Tx MOb is different since your CAN node may only Tx using an enabled Tx MOb. So, Tx errors never go into the ENERG CANGIT register. Tx errors only go into your ENERR CANSTMOB register. This is why the BERR (a Tx only type of error) only appears in the CANSTMOB register and not in the CANGIT register.
So, mostly CANGIT register errors are CAN bus errors in CAN traffic that your CAN node ignored. CANSTMOB errors are CAN bus errors that your CAN node is processing/using. CANGIT errors may also include CAN bus traffic you did want to Rx, except the CAN bus arbitration field bits had errors that prevented any acceptance filter match hit (see the arbitration field in Figure 19-1. CAN Standard Frames and Figure 19-2. CAN Extended Frames).
See the data sheet Figure 19-14. CAN Controller Interrupt Structure. When polling the CAN hardware the CANGIE.ENIT bit is cleared and the CANGIT.CANIT bit is polled for activity. When using interrupts the CANGIE.ENIT bit is set and the CANGIT.CANIT bit is ignored with the CAN IT interrupt vector being used instead. Calling this the “CAN Controller Interrupt Structure” is a little misleading since most of this is also used for polling.
ikoria wrote:
In case of auto-retry, the CAN module will become Error Active.
You do not appear to understand error active state. After the CAN hardware is enabled and there have not been any CAN errors, the CAN hardware is error active (CANREC and CANTEC are less than 128 decimal). This means any CAN bus errors are responded to with a dominant error flag that absolutely destroys the error CAN bus frame traffic on the CAN bus. When CANREC or CANTEC goes higher than 127 the CAN node hardware becomes error passive. This means CAN bus errors are responded to with a recessive error flag that may or may not destroy the error CAN bus frame traffic on the CAN bus. Bosch said that any CANREC or CANTEC value higher than 96 decimal indicates a heavily disturbed CAN bus, so error active is the normal CAN error state. Then for persistent Tx errors where CANTEC overflows its 255 decimal value the CAN node error state will become bus off to confine the malfunctioning Tx node and temporarily stop it from sending any more error flags on the CAN bus. The CAN bus Rx errors stop incrementing CANREC after it goes error passive (it does not go higher than around 128 to 136 decimal). There is one Tx error exception. A repeated AERR (acknowledge error) all by itself with no other Tx errors, will stop incrementing CANTEC after it goes error passive. So, Tx AERR never goes into the bus off error confinement state.
CAN errors will usually increment CANREC or CANTEC by a value up to 8. Successful CAN operations without any errors will decrement CANREC or CANTEC by a value of 1. So, the CAN error states (active, passive and bus off) are dynamic, depending on the error activity on the CAN bus.
ikoria wrote:
In case of no ack, the CAN module must do some auto-retry. Could I have 1 interrupt by auto message or just 1 for the first ?
If you set CANGCON.TTC for Time Triggered CAN mode there will not be any automatic retry when any Tx fails. For normal CAN use with CANGCON.TTC not set (no TTC mode), any Tx error will cause an automatic retry. Again, as pointed out above AERR is a special Tx error that never triggers the bus off error confinement state, so AERR Tx errors will keep happening forever over and over again until you deliberately disable the Tx or it finally gets the acknowledge it needs from another CAN node. Any other constantly repeated Tx error will trigger a bus off error confinement state and eventually stop the CAN node from sending. If you enable ENERR, every AERR automatic Tx retry that fails again will cause another new AERR. Unless this Tx MOb finally gets its acknowledge, or you deliberately disable the Tx MOb, it will keep generating AERR errors forever. Personally, I like to deliberately disable an AERR Tx MOb when the CAN node error state is error passive, then after a delay re-enable and retry the Tx MOb later under my software control. If it still fails with an AERR, I just keep retrying periodic software controlled Tx attempts.
To deliberately disable any MOb you may:
1) set CANPAGE to your MOb and write the CANCDMOB command bits to disable a specific MOb.
2) set the CANGCON.ABRQ bit to disable all MObs.
3) clear the CANGCON.ENASTB bit to disable all MObs and disable the CAN module.
The only absolute MOb disable is when you set the CANGCON.SWRES bit. This resets all the CAN hardware and kills all CAN activity. If your CAN node is sending anything on the CAN bus (anything like a CAN Tx, an acknowledge bit or any error flag) you may cause CAN bus errors on other CAN nodes.
Keep in mind any deliberate MOb disable is only an attempt to disable. The CAN hardware may continue with any MOb that is actively using the CAN bus and ignore your disable attempt for that MOb. Any deliberate MOb disable attempt may fail and end with a normal TXOK/RXOK, it may fail and end with new CANSTMOB error bit(s) or it may just disable and end with no new activity, depending on how the CAN hardware responds to your attempt.
When attempting any MOb disable, the CANEN bit that corresponds to your MOb is the only thing that tells you if the CAN hardware is ignoring your attempt and still using the MOb (this is called on-going CAN communication). After the corresponding CANEN bit is cleared, then check for any CANSTMOB enabled bits (CANGIE does this enable) that are set. After the CANEN bit and any enabled CANSTMOB bits are cleared, then you know the MOb has finally finished and disabled.
You are correct about the CAN error information not being really clear. The information is there in the data sheet, but you have to dig it out little pieces at a time. It is all based on the Bosch CAN specification:
http://www.semiconductors.bosch.de/medi ... n2spec.pdf
If you understand the Bosch specification, you will understand how any CAN hardware functions in theory. Then you just have to figure out how each different CAN chip implements the specification.
*edit: fixed a typo where "now" was "no" + another typo |
Last edited by Mike B on Feb 14, 2012 - 04:54 AM; edited 2 times in total
|
| |
|
|
|
|
|
Posted: Feb 13, 2012 - 05:02 PM |
|

Joined: Jul 06, 2011
Posts: 3
|
|
Hi Mike B
Scuse me for my word-miss about active/passive ...
Your post is really helpfull ^^.
I've done some tests and I was just thinking to take the same direction on the tx fail gesture ^^
Could you confirme me that this instruction is ok to clear CANSTMOB flag:
Code:
CANSTMOB &= ~_BV(AERR) ;
thanks in advance
Iko |
|
|
| |
|
|
|
|
|
Posted: Feb 13, 2012 - 09:18 PM |
|


Joined: Jun 22, 2004
Posts: 3849
Location: South West Utah, USA
|
|
| Yes, individual CANSTMOB bits may be cleared like you did in your example. Of course even with _BV macro the write to the CANSTMOB register is always all 8 bits. In reality I have found I rarely need to clear a single CANSTMOB bit. Mostly I just do this:
Code:
CANSTMOB = 0;
The CANSTMOB behavior is when DLCW, RXOK or TXOK is set none of the error bits are set and the MOb is automatically disabled by the RXOK or TXOK. This automatic disable makes it safe to write to the MOb storage registers. However, when any CANSTMOB error bit is set there is never any DLCW, RXOK or TXOK bit set and the MOb is still enabled (except for a deliberately disabled MOb that ends with a final last error and its CANEN bit is cleared by the CAN hardware). When the MOb with CANSTMOB error bits remains enabled, you must clear the CANSTMOB error bits to exit your CAN IT interrupt or CANIT polling, yet this is not really safe because the MOb is still enabled and the CAN hardware may write to any MOb storage register anytime it wants to in any enabled MOb.
The trick is depending on how fast your CAN baud rate is set, to always rapidly respond to any CANSTMOB error activity. Then there is no real chance that any CANSTMOB error CAN frame, which has to restart another new entire CAN frame after the error, to be able to complete with a TXOK or RXOK and conflict with your CANSTMOB error response write. This rapid response means your clearing of the CANSTMOB error bits will not be able to conflict with and destroy a CAN hardware set of TXOK or RXOK. Even though the timing window for this possible write conflict is really, really tiny it is not impossible and your software rapid response to CANSTMOB activity is what makes it impossible.
If you are using CAN IT interrupts to respond to CANSTMOB activity with ENERR enabled, then you must keep all your other interrupt code properly written/implemented. For example if you place a long delay in any ISR code, if you write to any slow serial port like a USART in any ISR, if your hardware generates constant interrupts that are a higher priority than the CAN IT ISR vector for a long period, or if you keep AVR global interrupts disabled in any other non-ISR code for a long time, you will not be able to respond rapidly to any CANSTMOB activity. Polling CANSTMOB activity without a RTOS or timer based polling trigger may be non-deterministic and will most likely have highly variable CANSTMOB response delays.
If you wish it is possible to detect this CANSTMOB write conflict. After the write to clear the CANSTMOB error in a still enabled MOb check the CANEN busy bit. If the CANEN bit is cleared for no known reason (no CANCDMOB command set to disable, no ABRQ bit set and ENASTB is still set) then you have detected a write conflict that destroyed a TXOK or RXOK in CANSTMOB. The destroyed CANSTMOB TXOK or RXOK may be restored by your software (remember now the MOb CANEN bit is cleared, so it is safe to write to the MOb storage). My approach to repair the possible write conflict DLC, RXOK or TXOK flags, is to keep a copy of each MOb CANCDMOB register original command. If a CANCDMOB write conflict is detected, first the CANCDMOB command bits tells me if it is a RXOK or TXOK, then this copy of the original CANCDMOB tells me the original DLC field and allows the DLCW flag to be restored for a lost RXOK as well. One restriction is using the CANCDMOB.RPLV bit (RPLV is optional) does not work with this correction. Another restriction is when applying the CANGCON.ABRQ bit I always disable AVR interrupts, set ABRQ, write all MOb CANCDMOB command bits to disable before enabling AVR interrupts and clearing the ABRQ bit (ABRQ is a software cleared bit). Then if my CANSTMOB error bit clear write disables the MOb for no known reason test, does not catch the ABRQ bit being set, the individual CANCDMOB command = disable will prevent a false TXOK or RXOK correction. It is the on-going CAN communication that makes a final false correction possible after the ABRQ disable (which the individual CANCDMOB register command disables prevents the false correction).
Typically my interrupt CANSTMOB management looks something like this (I use up to all 15 MObs in my CAN code):
Code:
INTERRUPT CAN IT () { // Use the correct syntax for your embedded compiler.
unsigned char save_page; // Preinterrupt CANPAGE value storage.
unsigned char mob; // Temporary MOb number value.
unsigned char isr_flags; // Temporary interrupt flags value.
save_page = CANPAGE; // Save the preinterrupt CANPAGE value.
// CANGIE ENTX, ENRX and ENERR in can_init() enables the MOb interrupt
// CAMSTMOB flags that CANSIT and CANHPMOB will respond to.
// Only use CANPAGE = CANHPMOB one time for each MOb while loop.
// See CANHPMOB.CGPn bits for initial CANPAGE AINC and INDX values.
// See CANHPMOB.HPMOBn bits description for the reason 0xF0 is used.
// The CANSIT.SITn bit must be set for CANHPMOB to select that MObn value.
while ((CANPAGE = CANHPMOB) < 0xF0) {
// Extract the MOb number value of the MOb being processed.
mob = (CANPAGE >> MOBNB0);
isr_flags = CANSTMOB; // Save the MOb interrupt flags state.
// Clear the MOb interrupt flags when you process each MOb. This also
// clears the read only CANSIT.SITn bit for this MOb number n (now
// CANHPMOB will ignore this MOb when the CANSIT.SITn bit is cleared).
CANSTMOB = 0; // Immediately clear the flags.
// ******* process this active CANSTMOB interrupt MOb number *******
// isr_flags error bits set means its CANEN.ENMOBn bit is still set
// unless the MOb was deliberately disabled (CANCDMOB.CONMOB=0),
// aborted (ABRQ=1) or standby mode (ENASTB=0) was applied. None of the following
// MOb registers have any useful values during isr_flags errors.
// isr_flags TXOK bit is set for a Tx and CANEN.ENMOBn bit is cleared.
// isr_flags RXOK bit is set for a Rx and CANEN.ENMOBn bit is cleared.
// CANSTM.TIMSTMn bits have the Rx or Tx time stamp value.
// CANIDT.RTRTAG bit has the actual Rx Data or Remote frame type.
// CANCDMOB.IDE bit has the actual Rx 11 bit or 29 bit format type.
// CANIDT.IDTn bits have the actual Rx message identifier value.
// (CANIDT.IDTn bits >> 21) = 11 bit format unsigned integer ID value.
// (CANIDT.IDTn bits >> 3) = 29 bit format unsigned long ID value.
// CANCDMOB.DLC bits have the actual Rx DLC count value.
// isr_flags DLCW bit warns you if CANCDMOB.DLC was changed by a Rx.
// CANMSG bytes have the Rx CAN data (up to DLC, only for Data Frame).
// If you read any Rx CANMSG bytes always use CANCDMOB.DLC field for
// the actual number of CANMSG bytes to read. However, if DLC is over
// a value of 8, your software must treat this as a value of 8 (this
// is also what the CAN hardware does if a bad DLC is received).
// CANPAGE.INDX points at each CANMSG byte when you read or write
// CANMSG (see CANPAGE.AINC for INDX automatic increment info).
// If CANEN.ENMOBn==0 this MOb task life cycle is now complete.
} // ===> end of the while(CANHPMOB) MOb processing loop <===
// CANGIE in can_init() selects the enabled General interrupt flags.
// First save and then clear the general interrupt flags.
isr_flags = CANGIT; // Save the current general interrupt flags state.
// OVRTIM does not belong to this CAN IT interrupt vector.
// Using isr_flags instead of CANGIT prevents clearing any new interrupts.
// Clear only the General interrupt flags that will be processed next.
CANGIT = isr_flags & ~(1 << OVRTIM);
// ***** process all enabled general CANGIT interrupts using isr_flags *****
// An example of using isr_flags instead of CANGIT would be:
// if (isr_flags & (1 << BOFFIT)) - CANGIT is not used since it was cleared.
CANPAGE = save_page; // Restore the preinterrupt CANPAGE value.
}
After the CANSTMOB=0 is where any optional check for the MOb CANSTMOB write conflict correction code would go (if ENERR is set and you decide to use any correction code). Notice the CANSTMOB clear is early in each MOb processing to help with rapid response just a tiny amount. This example does not implement the AT90CANxxx family "CAN transmission after 3 bit intermission errata".
This may help sort out the MOb registers for MObs that complete without errors:
Code:
/* when (isr_flags TXOK bit is set and CANCDMOB.RPLV bit was never set)
CANSTM.TIMSTM is the only MOb register that has new info.
when (isr_flags RXOK bit is set)
CANSTM.TIMSTM has new info.
if (CANIDM4.IDEMSK bit is cleared)
CANCDMOB.IDE bit may have new info.
CANCDMOB.IDE type is required to read CANIDM and CANIDT
if (any CANIDM.IDMSKn bits are zero values, depends on IDE type)
corresponding CANIDT.IDTn bits may have new info., depends on IDE type
if (CANIDM4.RTRMSK bit is cleared)
CANIDT4.RTRTAG bit may have new info.
if (isr_flags DLCW bit is set)
CANCDMOB.DLC has new info. (always limit DLC values to 8 maximum)
if (CANIDT4.RTRTAG bit is cleared i.e. data frame)
There are new CANMSG bytes of CANCDMOB.DLC number of bytes (0 to 8 bytes)
*/
|
|
|
| |
|
|
|
|
|
Posted: Feb 15, 2012 - 05:04 AM |
|

Joined: Jul 06, 2011
Posts: 3
|
|
Hi Mike.
Thanks again for your post. you help me a lot.
You write "CANSTMOB = 0" is suffisant. But we can found in the datasheet that they must have "read-modify-write" process...Is it write in regards of asm coding?
I'm working on a AT90CAN128 at 16MHz. My can work with those spec :
- 500kbps
- MOB 5 TX
- MOB 1 RX with no id filter
- TX; RX and ERR with interruption.
In case of TX, application push a can msg in fifo_tx and raise TX ISR mechanism. The ISR pull the fifo_tx and disable the ISR mechanism when fifo_tx is empty.
In case of RX, the ISR only push in fifo_rx the can msg (if the fifo isn't full ^^)
By this way, i think i can't have write conflic on mob.
According to me, an ISR must not take lots af time because of the rest of the application .
I'm using similar process for other communication device like USART, SPI, I2C (oups TWI :p)... |
|
|
| |
|
|
|
|
|
Posted: Feb 15, 2012 - 10:20 AM |
|


Joined: Jun 22, 2004
Posts: 3849
Location: South West Utah, USA
|
|
|
ikoria wrote:
You write "CANSTMOB = 0" is suffisant. But we can found in the datasheet that they must have "read-modify-write" process...Is it write in regards of asm coding?
The data sheet is only telling you how to clear an individual bit in CANSTMOB, it is not telling you it must only be done this way. Your C language CANSTMOB &= ~_BV(AERR); does exactly the same thing assembly code would do to clear an individual bit. The only reason the data sheet is written this way is because almost all other AVR interrupt flags are cleared by writing a 1 to the bit you want to clear. Writing a zero to most AVR interrupt flag bits has no effect on the flag bit at all. Except CANSTMOB is different from most all other AVR interrupt flag registers where you must write a zero to the flag bit to clear it. Take a look at my example ISR code where CANSTMOB=0 clears all these interrupt flags in the CANSTMOB register, yet the CANGIT register is writing a 1 value back to the bits it needs to clear. The CANGIT register write a 1 to clear the flag bit is normal for an AVR interrupt flag register, the CANSTMOB write a zero to clear the flag bit is not normal for an AVR interrupt flag register. All the data sheet was trying to do was alert people that CANSTMOB does not work like a normal AVR interrupt flag register when you clear the interrupt flag bits. If CANSTMOB was not so different from normal AVR flag registers, the data sheet would not have made such a big deal about it.
For example:
CANGIT=0 does nothing to any CANGIT flag bits at all.
CANGIT=0x7F clears all the CANGIT flag bits.
CANSTMOB=0 clears all the CANSTMOB flag bits (not normal).
Why 0x7F? Because the CANGIT.CANIT bit is read only and writing anything to CANGIT never has any effect on this CANIT bit anyway. There are other CAN read only bits and read only registers, carefully check the CAN data sheet to find all of these read only registers and read only register bits.
The CAN hardware is an independent state machine. It actually does not reveal the internal operation of the CANMSG fifo to your program code when sending or receiving CAN data. When you setup a MOb for Tx, some of the things you do are to set CANPAGE to the MOb number and this also sets the CANPAGE.INDXn bits. These 3 INDXn bits point at a single CANMSG byte when you write data into CANMSG. The CANPAGE.AINC bit activates an optional auto increment of the INDXn bit value for each CANMSG byte written. So, starting with the CANPAGE.AINC bit and CANPAGE.INDXn bits at a zero value, the first CANMSG write will write to CANMSG byte 0 (and auto-increment the INDXn bit value), then next write to CANMSG byte 1, byte 2 and so on. You may write up to 8 CANMSG bytes, then the last thing you do is the CANCDMOB command write. You simply set the CANCDMOB.DLC value to match the number of CANMSG bytes you wrote. CANCDMOB is written last because it has the command bits that activate the MOb and set the CANEN MOb busy bit. The CAN state machine hardware sorts out how to send the CANMSG bytes on the CAN bus for you and it will only Tx the DLC number of CANMSG bytes always starting with the CANMSG byte 0.
The CAN state machine hardware keeps CAN Tx operations separate from CAN Rx operations, and it manages the CANMSG fifo for you. Each MOb has its own 8 CANMSG bytes and each MOb is a single Rx or Tx CAN bus task (there are "effectively" 15 different CANMSG fifos with 8 bytes in each of the 15 fifos). All you need to do is correctly write the CANMSG bytes for a Tx and correctly set the CANCDMOB.DLC value, the rest is all automatically taken care of by the CAN hardware. When you Rx CAN data the CAN hardware decodes the DLC from the live CAN bit stream, writes this Rx DLC value into CANCDMOB.DLC register bits, then reads that same number of live CAN bit stream data bytes and writes them into the CANSMG registers for the Rx MOb. After a CANSTMOB.RXOK select your MOb, set CANPAGE.AINC and CANPAGE.INDXn bits to zero. Then read the Rx updated CANCDMOB.DLC value to find out exactly how many CAN bytes were received. Next use this updated CANCDMOB.DLC value to read the CANMSG register DLC number of times. Each CANMSG byte read will get the CAN data byte (the auto-increment INDXn bits will point at the actual CANMSG byte being read) for you to store in your code, usually in a variable array. Beware, the CAN bus allows Tx DLC values that are larger then a value of 8. The CAN hardware automatically treats DLC values larger than 8 as if they are a value of 8. However, if your software does not limit a bad Rx DLC value to 8 maximum, your code will write too many CANMSG bytes into a 8 byte fixed size data byte array. Writing over an array boundary will likely crash your program .
As long as your program code writes CANPAGE.AINC and CANPAGE.INDXn bits to zero first before reading or writing some DLC number of CANMSG bytes, do not worry about the CANMSG fifo operation (the CAN hardware fifo internal operation during Tx/Rx is hidden from your software anyway).
MOb registers have a task life cycle. Your CANCDMOB command write sets the read only CANEN MOb busy bit for the MOb to start its Rx or Tx task (the start of the MOb task life cycle). When the MOb completes the CANSTMOB register RXOK or TXOK disables the MOb and clears the CANEN MOb busy bit (the end of the MOb task life cycle). While the CANEN MOb busy bit is set, the CAN state machine hardware is in complete control of all the MOb registers. The CAN hardware may write to any busy MOb register anytime it wants to. Disabling AVR global interrupts has no effect on the CAN internal state machine writing to any busy MOb register when it wants to. The only time you may safely write to any MOb register is when its CANEN MOb busy bit is cleared. If you ever write to any MOb register while its CANEN MOb busy bit is set, your software write could possibly create a write conflict with the CAN state machine hardware also writing to the same MOb register and corrupt the MOb register value. Your write to a busy MOb register could also change its value as the CAN state machine hardware is reading the MOb register and make the CAN hardware state machine operation unstable (a real problem with 16 and 32 bit long MOb registers).
The only exceptions where you may write to a busy MOb (when its CANEN bit is set to busy) is when deliberately writing CANCDMOB command bits to force a MOb disable attempt, or when writing a CANCDMOB Rx re-enable for the "CAN transmission after 3-bit intermission errata", or when ENERR is set writing CANSTMOB error bits to clear them because you must do this to exit the ISR or polling code. It is the time delay between a CAN bus error and how long it takes to send another entire new CAN frame before a RXOK or TXOK is possible, that creates a “time window” where CANSTMOB error bits may be “safely” written by your software, only if you respond rapidly to the CANSTMOB flag bit activity before clearing the CANSTMOB error bits (too stay inside this “time window”). The errata re-enable does not matter since none of the MOb register information is used for anything. The disable command write is not important because you most likely will toss out any MOb data from a deliberately disabled MOb anyway. If you ignore these rules you invite a possible bug/disaster. Since CAN is all about high reliability network data transfers, doing anything in your program code that could corrupt CAN information is a really bad idea.
*edit - I wrote this at 3 AM. After getting some sleep I corrected some mistakes I made at 3 AM . |
|
|
| |
|
|
|
|
|
|
|
|