Funzioni ed FB per gestione CAN bus ----------------------------------- Il Controller Area Network, noto anche come CAN-bus, è uno standard seriale per bus di campo di tipo multicast, per collegare diverse unità di controllo elettronico (ECU). Il CAN è stato espressamente progettato per funzionare senza problemi anche in ambienti fortemente disturbati dalla presenza di onde elettromagnetiche e può utilizzare come mezzo trasmissivo una linea a differenza di potenziale bilanciata come la RS-485. L'immunità ai disturbi EMC può essere ulteriormente aumentata utilizzando cavi di tipo twisted pair (doppino intrecciato). Sebbene inizialmente applicata in ambito automotive, come bus per autoveicoli, attualmente è usata in molte applicazioni industriali di tipo embedded, dove è richiesto un alto livello di immunità ai disturbi. Il bit rate può raggiungere 1 Mbit/s per reti lunghe meno di 40 m. Velocità inferiori consentono di raggiungere distanze maggiori (ad es. 125 kbit/s per 500 m). Il protocollo di comunicazione del CAN è standardizzato come ISO 11898-1 (2003). **Filter, ID e Mask** E' possibile impostare con la funzione **SysCANSetMode** un filtro sulla ricezione dei pacchetti CAN in pratica il controller può essere impostato per ricevere solo i messaggi desiderati. Il valore di **Mask** è utilizzato per determinare quali bit nell'identificatore del frame ricevuto vengono confrontati con il valore di **Filter**. Se un bit di **Mask** è impostato a zero il corrispondente bit nell'identificatore del messaggio non viene controllato, indipendentemente dal valore del bit di **Filter**. Se un bit di **Mask** è impostato a uno il corrispondente bit nell'identificatore del messaggio viene controllato, con il corrispondente bit di **Filter**, e se il valore dei bit corrispondono il messaggio verrà accettato. SysCANSetMode, set the CAN controller mode ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |image0| +-----------------------+-----------------------+ | **Type** | **Library** | | | | | | | +=======================+=======================+ | Function | XTarget_07_0 | +-----------------------+-----------------------+ Questa funzione imposta il modo sul controller CAN. E' possibile definire il valore di bit rate, il filtro e la maschera di accettazione pacchetti. Il bit 31 di **Filter** se FALSE forza il controller CAN ad accettare solo i messaggi standard a 11 bits, se settato a TRUE forza il controller CAN ad accettare solo i messaggi extended a 29 bits. Se **Filter** e **Mask** sono impostati a 0 il controller CAN riceve tutti i messaggi sia standard che extended. La funzione ritorna TRUE se eseguita correttamente, FALSE se errore. Parametri funzione: +-----------------------------------+-----------------------------------+ | **BitRate** (USINT) | Valore definizione bit rate CAN | | | bus, `CAN bit rate | | | definition <#TabCANBitRateDefs>`_ | | | _. | +-----------------------------------+-----------------------------------+ | **Filter** (UDINT) | Valore di filtro pacchetti CAN. | +-----------------------------------+-----------------------------------+ | **Mask** (UDINT) | Valore di maschera filtro | | | pacchetti CAN. | +-----------------------------------+-----------------------------------+ La funzione ritorna: +--------+--------------------------------------------------------------------+ | (BOOL) | **TRUE:** Eseguita correttamente. | | | | | | **FALSE:** In caso di errore esecuzione, esempio parametri errati. | +--------+--------------------------------------------------------------------+ **Codici di errore** In caso di errore la funzione torna **FALSE** e con `SysGetLastError <#FctSysGetLastError>`__ è possibile rilevare il codice di errore. +---------+----------------------------------+ | 9957005 | Funzione non supportata. | +---------+----------------------------------+ | 9957990 | Non implementata nel simulatore. | +---------+----------------------------------+ **Esempi** """"""""""""" E' riportato un semplice programma che esegue l'impostazione del controller CAN con bit rate a 125 Kbit. Tutti i pacchetti in arrivo sono ricevuti dal controller. +-----------------------------------------------------------------------+ | **Definizione variabili** | +-----------------------------------------------------------------------+ | |image2| | +-----------------------------------------------------------------------+ **Esempio ST** .. code-block:: none (\* Set the controller to accept only standard messages with ID from 8 thru to 15. \*) SysCANSetMode(CAN_500KBIT, 16#00000008, 16#000007F8); (\* Set the controller to accept only extended messages with ID from 4 thru to 7. \*) SysCANSetMode(CAN_500KBIT, 16#80000004, 16#1FFFFFFC); (\* Ricevo solo i msg extended con ID da 4 a 7 *) (\* Set the controller to accept all messages. \*) SysCANSetMode(CAN_500KBIT, 16#00000000, 16#00000000); SysIsCANRxTxAv, checks if CAN Rx or Tx is available ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |image3| +-----------------------+-----------------------+ | **Type** | **Library** | +=======================+=======================+ | Function | XTarget_07_0 | +-----------------------+-----------------------+ Questa funzione controlla: **Select:=FALSE:** Se vi è almeno un messaggio nel buffer di ricezione CAN. **Select:=TRUE:** Se vi è spazio per un messaggio nel buffer di trasmissione CAN. La funzione ritorna TRUE se la condizione selezionata è vera. Parametri funzione: +-----------------------------------+-----------------------------------+ | **Select** (BOOL) | **FALSE:** Se vi è almeno un | | | messaggio nel buffer di ricezione | | | CAN. | | | | | | **TRUE:** Se vi è spazio per un | | | messaggio nel buffer di | | | trasmissione CAN. | +-----------------------------------+-----------------------------------+ La funzione ritorna: +--------+------------------------------------------+ | (BOOL) | **TRUE:** Condizione selezionata è vera. | +--------+------------------------------------------+ **Codici di errore** In caso di errore la funzione torna **FALSE** e con `SysGetLastError <#FctSysGetLastError>`__ è possibile rilevare il codice di errore. +---------+----------------------------------+ | 9956005 | Funzione non supportata. | +---------+----------------------------------+ | 9956990 | Non implementata nel simulatore. | +---------+----------------------------------+ **Esempi** """"""""""""" E' riportato un semplice programma che esegue il controllo se un messaggio CAN è stato ricevuto, ne esegue la ricezione ed invia in console di spionaggio il messaggio ricevuto. +-----------------------------------------------------------------------+ | **Definizione variabili** | +-----------------------------------------------------------------------+ | |image5| | +-----------------------------------------------------------------------+ **Esempio ST** *(PTP116B100, ST_SysCANRxMsg)* .. code-block:: none (\* Execute programs inizializations. \*) IF (SysFirstLoop) THEN i:=SysCANSetMode(CAN_250KBIT, 16#00000000, 16#00000000); END_IF; (\* Read a CAN message (No filters so all received messages are read). \*) IF NOT(SysIsCANRxTxAv(FALSE)) THEN RETURN; END_IF; IF NOT(SysCANRxMsg(16#00000000, 16#00000000, ADR(CANMsg))) THEN RETURN; END_IF; (\* Spy of received message. \*) i:=SysVarsnprintf(ADR(SBf), SIZEOF(SBf), 'MsgID:%08X', UDINT_TYPE, ADR(CANMsg.MsgID)); i:=SysLWVarsnprintf(ADR(SBf), SIZEOF(SBf), ', Length:%d -', USINT_TYPE, ADR(CANMsg.Length)); FOR j:=0 TO CANMsg.Length-1 DO i:=SysLWVarsnprintf(ADR(SBf), SIZEOF(SBf), ' %02X', USINT_TYPE, ADR(CANMsg.Data[j])); END_FOR; i:=SysSpyData(SPY_ASCII, 16#00000001, ADR('Rx'), ADR(SBf)); SysCANRxMsg, receives a CAN message ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |image6| +----------+--------------+ | **Type** | **Library** | | | | +----------+--------------+ | Function | XTarget_07_0 | +----------+--------------+ Questa funzione riceve un messaggio CAN e lo trasferisce nella variabile il cui indirizzo è definito in **Msg**. E' possibile definire un **Mask** ed un **ID** per ricevere i soli messaggi CAN desiderati. La funzione ricerca nello stack dei messaggi un messaggio il cui ID posto in AND con **Mask** coincide con **ID** messo in AND con **Mask**. La funzione ritorna TRUE se messaggio ricevuto. Parametri funzione: +--------------------------+--------------------------------------+ | **Mask** (UDINT) | Codice maschera ID messaggio. | +--------------------------+--------------------------------------+ | **ID** (UDINT) | ID check ID messaggio. | +--------------------------+--------------------------------------+ | **Msg** (@SYSCANMESSAGE) | Indirizzo buffer messaggio ricevuto. | +--------------------------+--------------------------------------+ La funzione ritorna: +--------+-------------------------------+ | (BOOL) | **TRUE:** Messaggio ricevuto. | +--------+-------------------------------+ **Codici di errore** In caso di errore la funzione torna **FALSE** e con `SysGetLastError <#FctSysGetLastError>`__ è possibile rilevare il codice di errore. +---------+----------------------------------+ | 9955005 | Funzione non supportata. | +---------+----------------------------------+ | 9955990 | Non implementata nel simulatore. | +---------+----------------------------------+ **Esempi** """"""""""""" E' riportato un semplice programma che esegue il controllo se un messaggio CAN è stato ricevuto, ne esegue la ricezione ed invia in console di spionaggio il messaggio ricevuto. +-----------------------------------------------------------------------+ | **Definizione variabili** | +-----------------------------------------------------------------------+ | |image8| | +-----------------------------------------------------------------------+ **Esempio ST** *(PTP116B100, ST_SysCANRxMsg)* .. code-block:: none (\* Execute programs inizializations. \*) IF (SysFirstLoop) THEN i:=SysCANSetMode(CAN_250KBIT, 16#00000000, 16#00000000); END_IF; (\* Read a CAN message (No filters so all received messages are read). \*) IF NOT(SysIsCANRxTxAv(FALSE)) THEN RETURN; END_IF; IF NOT(SysCANRxMsg(16#00000000, 16#00000000, ADR(CANMsg))) THEN RETURN; END_IF; (\* Spy of received message. \*) i:=SysVarsnprintf(ADR(SBf), SIZEOF(SBf), 'MsgID:%08X', UDINT_TYPE, ADR(CANMsg.MsgID)); i:=SysLWVarsnprintf(ADR(SBf), SIZEOF(SBf), ', Length:%d -', USINT_TYPE, ADR(CANMsg.Length)); FOR j:=0 TO CANMsg.Length-1 DO i:=SysLWVarsnprintf(ADR(SBf), SIZEOF(SBf), ' %02X', USINT_TYPE, ADR(CANMsg.Data[j])); END_FOR; i:=SysSpyData(SPY_ASCII, 16#00000001, ADR('Rx'), ADR(SBf)); SysCANTxMsg, transmit a CAN message ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |image9| +----------+--------------+ | **Type** | **Library** | | | | +----------+--------------+ | Function | XTarget_07_0 | +----------+--------------+ Questa funzione trasmette un messaggio CAN, occorre creare il messaggio e poi passarne alla funzione l'indirizzo in **Msg**. La funzione ritorna TRUE se messaggio trasmesso. Parametri funzione: +--------------------------+--------------------------------------------+ | **Msg** (@SYSCANMESSAGE) | Indirizzo buffer messaggio da trasmettere. | +--------------------------+--------------------------------------------+ La funzione ritorna: +--------+--------------------------------+ | (BOOL) | **TRUE:** Messaggio trasmesso. | +--------+--------------------------------+ **Codici di errore** In caso di errore la funzione torna **FALSE** e con `SysGetLastError <#FctSysGetLastError>`__ è possibile rilevare il codice di errore. +---------+----------------------------------+ | 9954005 | Funzione non supportata. | +---------+----------------------------------+ | 9954990 | Non implementata nel simulatore. | +---------+----------------------------------+ **Esempi** """"""""""""" E' riportato un semplice programma che esegue la trasmissione di un messaggio CAN. +-----------------------------------------------------------------------+ | **Definizione variabili** | +-----------------------------------------------------------------------+ | |image11| | +-----------------------------------------------------------------------+ **Esempio ST** .. code-block:: none (\* Here check if there is a space in Tx buffer and send a CAN message. \*) IF (SysIsCANRxTxAv(TRUE)) THEN CANMsg.RmReq:=FALSE; (\* eFALSE:Data frame, eTRUE:Remote request \*) CANMsg.Length:=2; (\* Data length \*) CANMsg.MsgID:=16#00000000; (\* Message ID (FF:Bit 31) (11 or 29 Bit) \*) CANMsg.Data[0]:=16#01; (\* Message data \*) CANMsg.Data[1]:=16#00; (\* Message data \*) TxOk:=SysCANTxMsg(ADR(CANMsg)); (\* Transmission Ok \*) END_IF; .. |image0| image:: media/image1.jpg :width: 1.82292in :height: 0.82292in .. |image1| image:: media/image2.jpg :width: 7.08681in :height: 0.29931in .. |image2| image:: media/image2.jpg :width: 7.08681in :height: 0.29931in .. |image3| image:: media/image3.jpg :width: 1.62569in :height: 0.48056in .. |image4| image:: media/image4.jpg :width: 7.08681in :height: 0.91319in .. |image5| image:: media/image4.jpg :width: 7.08681in :height: 0.91319in .. |image6| image:: media/image5.jpg :width: 1.44861in :height: 0.81528in .. |image7| image:: media/image6.jpg :width: 7.08681in :height: 0.91319in .. |image8| image:: media/image6.jpg :width: 7.08681in :height: 0.91319in .. |image9| image:: media/image7.jpg :width: 1.45694in :height: 0.46875in .. |image10| image:: media/image8.jpg :width: 7.08681in :height: 0.52361in .. |image11| image:: media/image8.jpg :width: 7.08681in :height: 0.52361in