zoukankan      html  css  js  c++  java
  • CANopenNode drvTemplate/CO_driver.h hacking

    /************************************************************************
     *            CANopenNode drvTemplate/CO_driver.h hacking
     * 说明:
     *     使用CANopenNode,drvTemplate/CO_driver.h说明了一些驱动编写相关的
     * 注意事项。
     *
     *                                    2017-3-24 深圳 南山平山村 曾剑锋
     ***********************************************************************/
    
    /**
     * CAN module object for generic microcontroller.
     *
     * This file is a template for other microcontrollers.
     *
     * @file        CO_driver.h
     * @ingroup     CO_driver
     * @author      Janez Paternoster
     * @copyright   2004 - 2015 Janez Paternoster
     *
     * This file is part of CANopenNode, an opensource CANopen Stack.
     * Project home page is <https://github.com/CANopenNode/CANopenNode>.
     * For more information on CANopen see <http://www.can-cia.org/>.
     *
     * CANopenNode is free and open source software: you can redistribute
     * it and/or modify it under the terms of the GNU General Public License
     * as published by the Free Software Foundation, either version 2 of the
     * License, or (at your option) any later version.
     *
     * This program is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     * GNU General Public License for more details.
     *
     * You should have received a copy of the GNU General Public License
     * along with this program. If not, see <http://www.gnu.org/licenses/>.
     *
     * Following clarification and special exception to the GNU General Public
     * License is included to the distribution terms of CANopenNode:
     *
     * Linking this library statically or dynamically with other modules is
     * making a combined work based on this library. Thus, the terms and
     * conditions of the GNU General Public License cover the whole combination.
     *
     * As a special exception, the copyright holders of this library give
     * you permission to link this library with independent modules to
     * produce an executable, regardless of the license terms of these
     * independent modules, and to copy and distribute the resulting
     * executable under terms of your choice, provided that you also meet,
     * for each linked independent module, the terms and conditions of the
     * license of that module. An independent module is a module which is
     * not derived from or based on this library. If you modify this
     * library, you may extend this exception to your version of the
     * library, but you are not obliged to do so. If you do not wish
     * to do so, delete this exception statement from your version.
     */
    
    
    #ifndef CO_DRIVER_H
    #define CO_DRIVER_H
    
    
    /* Include processor header file */
    /**
     * 将这里的头文件替换成与处理器相关的头文件,譬如:
     *   1. STM32:
     *     #include "common.h"
     *     #include "stm32f10x_conf.h"
     *   2. SocketCAN:
     *      #include <stddef.h>         /* for 'NULL' */
     *      #include <stdint.h>         /* for 'int8_t' to 'uint64_t' */
     *      #include <stdbool.h>        /* for 'true', 'false' */
     *      #include <unistd.h>
     *      #include <endian.h>
     *      
     *      #ifndef CO_SINGLE_THREAD
     *      #include <pthread.h>
     *      #endif
     *      
     *      #include <linux/can.h>
     *      #include <linux/can/raw.h>
     *      #include <linux/can/error.h>
     */
    #include <stddef.h>         /* for 'NULL' */
    #include <stdint.h>         /* for 'int8_t' to 'uint64_t' */
    #include <stdbool.h>        /* for 'true', 'false' */
    
    
    /**
     * @defgroup CO_driver Driver
     * @ingroup CO_CANopen
     * @{
     *
     * Microcontroller specific code for CANopenNode.
     * 微控制器CANopenNode专用代码
     *
     * This file contains type definitions, functions and macros for:
     * 该文件包含为用于以下目的的类型定义,函数,宏
     *  - Basic data types.
     *    基础数据类型
     *  - Receive and transmit buffers for CANopen messages.
     *    CANopen信息发送和接收缓冲区
     *  - Interaction with CAN module on the microcontroller.
     *    在微控制器上和CAN模块进行交互
     *  - CAN receive and transmit interrupts.
     *    CAN信息接收和发送中断
     *
     * This file is not only a CAN driver. There are no classic CAN queues for CAN
     * messages. This file provides direct connection with other CANopen
     * objects. It tries to provide fast responses and tries to avoid unnecessary
     * calculations and memory consumptions.
     * 这份文件不仅仅是用于CAN驱动,这里没有典型的处理CAN消息的队列,通过直接连接其他的CANopen的对象,
     * 主要是为了提供最快的响应速度来避免不必要的计算和内存消耗
     *
     * CO_CANmodule_t contains an array of _Received message objects_ (of type
     * CO_CANrx_t) and an array of _Transmit message objects_ (of type CO_CANtx_t).
     * Each CANopen communication object owns one member in one of the arrays.
     * For example Heartbeat producer generates one CANopen transmitting object,
     * so it has reserved one member in CO_CANtx_t array.
     * SYNC module may produce sync or consume sync, so it has reserved one member
     * in CO_CANtx_t and one member in CO_CANrx_t array.
     * CO_CANmodule_t两个数组,一个是发送消息对象CO_CANrx_t,一个是接收信息的对象CO_CANtx_t,
     * 每一个CANopen通信对象在数组中拥有一个成员,例如:
     *   1. 心跳包生产者产生一个CANopen传输对象,所以他收到一个成员在CO_CANtx_t数组中。
     *   2. 同步模块可能会产生sync和消费sync,所以他保留了一个成员在CO_CANtx_t中,也
     *     保留一个在CO_CANrx_t中
     *
     * ###Reception of CAN messages.
     * Before CAN messages can be received, each member in CO_CANrx_t must be
     * initialized. CO_CANrxBufferInit() is called by CANopen module, which
     * uses specific member. For example @ref CO_HBconsumer uses multiple members
     * in CO_CANrx_t array. (It monitors multiple heartbeat messages from remote
     * nodes.) It must call CO_CANrxBufferInit() multiple times.
     * 在CAN消息被接收之前,每一个CO_CANrx_t需要先被初始化,CO_CANrxBufferInit被CANopen模块
     * 调用,有些特定的成员被使用,例如CO_HBconsumer使用了CO_CANrx_t多个成员,其监视远程节点
     * 上的多个心跳包,所以被CO_CANrxBufferInit()调用多次。
     *
     * Main arguments to the CO_CANrxBufferInit() function are CAN identifier
     * and a pointer to callback function. Those two arguments (and some others)
     * are copied to the member of the CO_CANrx_t array.
     * CO_CANrxBufferInit()主要参数是:
     *   1. CAN identifier;
     *   2. 回调的函数指针;
     * 这两个参数(也许包括其他的)都会被作为成员拷贝的CO_CANrx_t数组中。
     *
     * Callback function is a function, specified by specific CANopen module
     * (for example by @ref CO_HBconsumer). Each CANopen module defines own
     * callback function. Callback function will process the received CAN message.
     * It will copy the necessary data from CAN message to proper place. It may
     * also trigger additional task, which will further process the received message.
     * Callback function must be fast and must only make the necessary calculations
     * and copying.
     * 回调函数是一个函数,处理特定的CANopen模块相关数据,每一个CANopen模块定义了他们
     * 自己的回调函数,回调函数将处理接收到的CAN信息。他将从CAN信息中拷贝必要的数据到
     * 合适的地方,当然他也可以触发额外的任务,额外的任务会进一步处理接收到的信息。
     * 回调函数必须处理迅速,仅仅做那些必要的数据运算以及拷贝。
     *
     * Received CAN messages are processed by CAN receive interrupt function.
     * After CAN message is received, function first tries to find matching CAN
     * identifier from CO_CANrx_t array. If found, then a corresponding callback
     * function is called.
     * 接收CAN信息是由CAN接收中断函数进行处理的,在接收完数据之后,函数会尝试从CO_CANrx_t
     * 中去查找匹配的CAN identifier,如果被找到,那么正确的回调函数就会被调用。
     *
     * Callback function accepts two parameters:
     * 回调函数接收两个参数
     *  - object is pointer to object registered by CO_CANrxBufferInit().
     *    CO_CANrxBufferInit()中注册的对象指针
     *  - msg  is pointer to CAN message of type CO_CANrxMsg_t.
     *    CO_CANrxMsg_t类型的CAN信息指针
     *
     * Callback function must return #CO_ReturnError_t: CO_ERROR_NO,
     * CO_ERROR_RX_OVERFLOW, CO_ERROR_RX_PDO_OVERFLOW, CO_ERROR_RX_MSG_LENGTH or
     * CO_ERROR_RX_PDO_LENGTH.
     * 回调函数必须是返回如下CO_ReturnError_t类型的数据。
     *
     *
     * ###Transmission of CAN messages.
     * Before CAN messages can be transmitted, each member in CO_CANtx_t must be
     * initialized. CO_CANtxBufferInit() is called by CANopen module, which
     * uses specific member. For example Heartbeat producer must initialize it's
     * member in CO_CANtx_t array.
     * 在CAN消息被发送之前,CO_CANtx_t必须先被初始化,CO_CANtxBufferInit()被CANopen模块调用,
     * 会使用指定的成员,例如,心跳包产生者必须在CO_CANtx_t中初始化成员。
     *
     * CO_CANtxBufferInit() returns a pointer of type CO_CANtx_t, which contains buffer
     * where CAN message data can be written. CAN message is send with calling
     * CO_CANsend() function. If at that moment CAN transmit buffer inside
     * microcontroller's CAN module is free, message is copied directly to CAN module.
     * Otherwise CO_CANsend() function sets _bufferFull_ flag to true. Message will be
     * then sent by CAN TX interrupt as soon as CAN module is freed. Until message is
     * not copied to CAN module, its contents must not change. There may be multiple
     * _bufferFull_ flags in CO_CANtx_t array set to true. In that case messages with
     * lower index inside array will be sent first.
     * CO_CANtxBufferInit()返回CO_CANtx_t类型的指针,其中包含CAN信息可以被写入的数据缓冲区,
     * CAN信息通过CO_CANsend()函数进行发送,如果微处理器的CAN模块的CAN输出传输缓冲区被释放,
     * CAN信息将直接被拷贝进CAN模块中。
     * 另外CO_CANsend()函数设置_bufferFull_标志位true,消息将会被CAN模块尽快发送,在信息被
     * 拷贝到CAN模块之前,信息是不能被篡改的。因此,在CO_CANtx_t数组中,会有很多的_bufferFull_
     * 标志是true,在这种情况下,小的index会先被发送出去。
     */
    
    
    /**
     * @name Critical sections
     * CANopenNode is designed to run in different threads, as described in README.
     * Threads are implemented differently in different systems. In microcontrollers
     * threads are interrupts with different priorities, for example.
     * It is necessary to protect sections, where different threads access to the
     * same resource. In simple systems interrupts or scheduler may be temporary
     * disabled between access to the shared resource. Otherwise mutexes or
     * semaphores can be used.
     * 如同在README中描述的,CANopenNode被设计于运行于不同的线程。
     * 线程在不同的系统中,实现的方式也是不同的,在微处理器中线程采用不同的优先级的中断来完成,例如
     * 像多个线程都要访问的部分是需要被保护的,在系统中这部分共享资源在访问的时候要关闭中断和任务调度,
     * 当然想互斥和信号量也是可以使用的。
     *
     * ####Reentrant functions.
     * Functions CO_CANsend() from C_driver.h, CO_errorReport() from CO_Emergency.h
     * and CO_errorReset() from CO_Emergency.h may be called from different threads.
     * Critical sections must be protected. Eather by disabling scheduler or
     * interrupts or by mutexes or semaphores.
     * 函数CO_CANsend()是在C_driver.h中的,CO_errorReport()/CO_errorReset()是在CO_Emergency.h中,
     * 他们都可能被任何线程调用,敏感的部分必须要被保护,需要采用禁止任务切换、中断,或者
     * 采用互斥、信号量来处理。
     *
     * ####Object Dictionary variables.
     * In general, there are two threads, which accesses OD variables: mainline and
     * timer. CANopenNode initialization and SDO server runs in mainline. PDOs runs
     * in faster timer thread. Processing of PDOs must not be interrupted by
     * mainline. Mainline thread must protect sections, which accesses the same OD
     * variables as timer thread. This care must also take the application. Note
     * that not all variables are allowed to be mapped to PDOs, so they may not need
     * to be protected. SDO server protects sections with access to OD variables.
     * 通常情况下,有两个线程会访问对象字典变量:主线程和定时器。CANopenNode初始化和SDO服务
     * 运行于主线程,PDOs运行于快速定时器线程,PDO的处理不能被mainline打断。因为对象字典
     * 能够同时被主线程、定时器访问,所以需要专门被保护,在引用层也是需要注意的。不过需要
     * 注意的是,并不是所有的PDO的对象都允许被映射,可能不需要被保护。
     *
     * ####CAN receive thread.
     * It partially processes received CAN data and puts them into appropriate
     * objects. Objects are later processed. It does not need protection of
     * critical sections. There is one circumstance, where CANrx should be disabled:
     * After presence of SYNC message on CANopen bus, CANrx should be temporary
     * disabled until all receive PDOs are processed. See also CO_SYNC.h file and
     * CO_SYNC_initCallback() function.
     * 专门处理CAN数据,并将其放到合适对象里,这些对象会被稍后处理,这是不需要被特殊处理的部分。
     * 这是一个事件,CANrx应该被关闭,在获取到SYNC的信息的时候,CANrx应该被短暂的关闭直到PDO信息
     * 被处理,请查看CO_SYNC.h文件和CO_SYNC_initCallback()函数
     * @{
     */
        #define CO_LOCK_CAN_SEND()  /**< Lock critical section in CO_CANsend() */
        #define CO_UNLOCK_CAN_SEND()/**< Unlock critical section in CO_CANsend() */
    
        #define CO_LOCK_EMCY()      /**< Lock critical section in CO_errorReport() or CO_errorReset() */
        #define CO_UNLOCK_EMCY()    /**< Unlock critical section in CO_errorReport() or CO_errorReset() */
    
        #define CO_LOCK_OD()        /**< Lock critical section when accessing Object Dictionary */
        #define CO_UNLOCK_OD()      /**< Unock critical section when accessing Object Dictionary */
    /** @} */
    
    
    /**
     * @defgroup CO_dataTypes Data types
     * @{
     *
     * According to Misra C
     */
        /* int8_t to uint64_t are defined in stdint.h */
        typedef unsigned char           bool_t;     /**< bool_t */
        typedef float                   float32_t;  /**< float32_t */
        typedef long double             float64_t;  /**< float64_t */
        typedef char                    char_t;     /**< char_t */
        typedef unsigned char           oChar_t;    /**< oChar_t */
        typedef unsigned char           domain_t;   /**< domain_t */
    /** @} */
    
    
    /**
     * Return values of some CANopen functions. If function was executed
     * successfully it returns 0 otherwise it returns <0.
     */
    typedef enum{
        CO_ERROR_NO                 = 0,    /**< Operation completed successfully */
        CO_ERROR_ILLEGAL_ARGUMENT   = -1,   /**< Error in function arguments */
        CO_ERROR_OUT_OF_MEMORY      = -2,   /**< Memory allocation failed */
        CO_ERROR_TIMEOUT            = -3,   /**< Function timeout */
        CO_ERROR_ILLEGAL_BAUDRATE   = -4,   /**< Illegal baudrate passed to function CO_CANmodule_init() */
        CO_ERROR_RX_OVERFLOW        = -5,   /**< Previous message was not processed yet */
        CO_ERROR_RX_PDO_OVERFLOW    = -6,   /**< previous PDO was not processed yet */
        CO_ERROR_RX_MSG_LENGTH      = -7,   /**< Wrong receive message length */
        CO_ERROR_RX_PDO_LENGTH      = -8,   /**< Wrong receive PDO length */
        CO_ERROR_TX_OVERFLOW        = -9,   /**< Previous message is still waiting, buffer full */
        CO_ERROR_TX_PDO_WINDOW      = -10,  /**< Synchronous TPDO is outside window */
        CO_ERROR_TX_UNCONFIGURED    = -11,  /**< Transmit buffer was not confugured properly */
        CO_ERROR_PARAMETERS         = -12,  /**< Error in function function parameters */
        CO_ERROR_DATA_CORRUPT       = -13,  /**< Stored data are corrupt */
        CO_ERROR_CRC                = -14   /**< CRC does not match */
    }CO_ReturnError_t;
    
    
    /**
     * CAN receive message structure as aligned in CAN module. It is different in
     * different microcontrollers. It usually contains other variables.
     */
    typedef struct{
        /** CAN identifier. It must be read through CO_CANrxMsg_readIdent() function. */
        uint32_t            ident;
        uint8_t             DLC ;           /**< Length of CAN message */
        uint8_t             data[8];        /**< 8 data bytes */
    }CO_CANrxMsg_t;
    
    
    /**
     * Received message object
     */
    typedef struct{
        uint16_t            ident;          /**< Standard CAN Identifier (bits 0..10) + RTR (bit 11) */
        uint16_t            mask;           /**< Standard Identifier mask with same alignment as ident */
        void               *object;         /**< From CO_CANrxBufferInit() */
        void              (*pFunct)(void *object, const CO_CANrxMsg_t *message);  /**< From CO_CANrxBufferInit() */
    }CO_CANrx_t;
    
    
    /**
     * Transmit message object.
     */
    typedef struct{
        uint32_t            ident;          /**< CAN identifier as aligned in CAN module */
        uint8_t             DLC ;           /**< Length of CAN message. (DLC may also be part of ident) */
        uint8_t             data[8];        /**< 8 data bytes */
        volatile bool_t     bufferFull;     /**< True if previous message is still in buffer */
        /** Synchronous PDO messages has this flag set. It prevents them to be sent outside the synchronous window */
        volatile bool_t     syncFlag;
    }CO_CANtx_t;
    
    
    /**
     * CAN module object. It may be different in different microcontrollers.
     */
    typedef struct{
        int32_t             CANbaseAddress; /**< From CO_CANmodule_init() */
        CO_CANrx_t         *rxArray;        /**< From CO_CANmodule_init() */
        uint16_t            rxSize;         /**< From CO_CANmodule_init() */
        CO_CANtx_t         *txArray;        /**< From CO_CANmodule_init() */
        uint16_t            txSize;         /**< From CO_CANmodule_init() */
        volatile bool_t     CANnormal;      /**< CAN module is in normal mode */
        /** Value different than zero indicates, that CAN module hardware filters
          * are used for CAN reception. If there is not enough hardware filters,
          * they won't be used. In this case will be *all* received CAN messages
          * processed by software. */
        volatile bool_t     useCANrxFilters;
        /** If flag is true, then message in transmitt buffer is synchronous PDO
          * message, which will be aborted, if CO_clearPendingSyncPDOs() function
          * will be called by application. This may be necessary if Synchronous
          * window time was expired. */
        volatile bool_t     bufferInhibitFlag;
        /** Equal to 1, when the first transmitted message (bootup message) is in CAN TX buffers */
        volatile bool_t     firstCANtxMessage;
        /** Number of messages in transmit buffer, which are waiting to be copied to the CAN module */
        volatile uint16_t   CANtxCount;
        uint32_t            errOld;         /**< Previous state of CAN errors */
        void               *em;             /**< Emergency object */
    }CO_CANmodule_t;
    
    
    /**
     * Endianes.
     * 大小端的问题
     *
     * Depending on processor or compiler architecture, one of the two macros must
     * be defined: CO_LITTLE_ENDIAN or CO_BIG_ENDIAN. CANopen itself is little endian.
     * 依赖于处理和编译器架构,这两个宏其中之一要被定义,cANopen本身是小端的。
     */
    #define CO_LITTLE_ENDIAN
    
    
    /**
     * Request CAN configuration (stopped) mode and *wait* untill it is set.
     * 请求CAN配置参数(停止)模式并直到被设置
     *
     * @param CANbaseAddress CAN module base address.
     */
    void CO_CANsetConfigurationMode(int32_t CANbaseAddress);
    
    
    /**
     * Request CAN normal (opearational) mode and *wait* untill it is set.
     * 请求cAN普通(操作)模式并直到被设置
     *
     * @param CANmodule This object.
     */
    void CO_CANsetNormalMode(CO_CANmodule_t *CANmodule);
    
    
    /**
     * Initialize CAN module object.
     * 初始化CAN模块对象
     *
     * Function must be called in the communication reset section. CAN module must
     * be in Configuration Mode before.
     *
     * @param CANmodule This object will be initialized.
     * @param CANbaseAddress CAN module base address.
     * @param rxArray Array for handling received CAN messages
     * @param rxSize Size of the above array. Must be equal to number of receiving CAN objects.
     * @param txArray Array for handling transmitting CAN messages
     * @param txSize Size of the above array. Must be equal to number of transmitting CAN objects.
     * @param CANbitRate Valid values are (in kbps): 10, 20, 50, 125, 250, 500, 800, 1000.
     * If value is illegal, bitrate defaults to 125.
     *
     * Return #CO_ReturnError_t: CO_ERROR_NO or CO_ERROR_ILLEGAL_ARGUMENT.
     */
    CO_ReturnError_t CO_CANmodule_init(
            CO_CANmodule_t         *CANmodule,
            int32_t                 CANbaseAddress,
            CO_CANrx_t              rxArray[],
            uint16_t                rxSize,
            CO_CANtx_t              txArray[],
            uint16_t                txSize,
            uint16_t                CANbitRate);
    
    
    /**
     * Switch off CANmodule. Call at program exit.
     * 关闭CAN模块,程序的最后需要被调用
     *
     * @param CANmodule CAN module object.
     */
    void CO_CANmodule_disable(CO_CANmodule_t *CANmodule);
    
    
    /**
     * Read CAN identifier from received message
     * 获取CAN identifier从接受到的信息中
     *
     * @param rxMsg Pointer to received message
     * @return 11-bit CAN standard identifier.
     */
    uint16_t CO_CANrxMsg_readIdent(const CO_CANrxMsg_t *rxMsg);
    
    
    /**
     * Configure CAN message receive buffer.
     * 配置CAN信息接收缓冲区
     *
     * Function configures specific CAN receive buffer. It sets CAN identifier
     * and connects buffer with specific object. Function must be called for each
     * member in _rxArray_ from CO_CANmodule_t.
     *
     * @param CANmodule This object.
     * @param index Index of the specific buffer in _rxArray_.
     * @param ident 11-bit standard CAN Identifier.
     * @param mask 11-bit mask for identifier. Most usually set to 0x7FF.
     * Received message (rcvMsg) will be accepted if the following
     * condition is true: (((rcvMsgId ^ ident) & mask) == 0).
     * @param rtr If true, 'Remote Transmit Request' messages will be accepted.
     * @param object CANopen object, to which buffer is connected. It will be used as
     * an argument to pFunct. Its type is (void), pFunct will change its
     * type back to the correct object type.
     * @param pFunct Pointer to function, which will be called, if received CAN
     * message matches the identifier. It must be fast function.
     *
     * Return #CO_ReturnError_t: CO_ERROR_NO CO_ERROR_ILLEGAL_ARGUMENT or
     * CO_ERROR_OUT_OF_MEMORY (not enough masks for configuration).
     */
    CO_ReturnError_t CO_CANrxBufferInit(
            CO_CANmodule_t         *CANmodule,
            uint16_t                index,
            uint16_t                ident,
            uint16_t                mask,
            bool_t                  rtr,
            void                   *object,
            void                  (*pFunct)(void *object, const CO_CANrxMsg_t *message));
    
    
    /**
     * Configure CAN message transmit buffer.
     * 配置CAN信息发送缓冲区
     *
     * Function configures specific CAN transmit buffer. Function must be called for
     * each member in _txArray_ from CO_CANmodule_t.
     *
     * @param CANmodule This object.
     * @param index Index of the specific buffer in _txArray_.
     * @param ident 11-bit standard CAN Identifier.
     * @param rtr If true, 'Remote Transmit Request' messages will be transmitted.
     * @param noOfBytes Length of CAN message in bytes (0 to 8 bytes).
     * @param syncFlag This flag bit is used for synchronous TPDO messages. If it is set,
     * message will not be sent, if curent time is outside synchronous window.
     *
     * @return Pointer to CAN transmit message buffer. 8 bytes data array inside
     * buffer should be written, before CO_CANsend() function is called.
     * Zero is returned in case of wrong arguments.
     */
    CO_CANtx_t *CO_CANtxBufferInit(
            CO_CANmodule_t         *CANmodule,
            uint16_t                index,
            uint16_t                ident,
            bool_t                  rtr,
            uint8_t                 noOfBytes,
            bool_t                  syncFlag);
    
    
    /**
     * Send CAN message.
     * 发送信息函数
     *
     * @param CANmodule This object.
     * @param buffer Pointer to transmit buffer, returned by CO_CANtxBufferInit().
     * Data bytes must be written in buffer before function call.
     *
     * @return #CO_ReturnError_t: CO_ERROR_NO, CO_ERROR_TX_OVERFLOW or
     * CO_ERROR_TX_PDO_WINDOW (Synchronous TPDO is outside window).
     */
    CO_ReturnError_t CO_CANsend(CO_CANmodule_t *CANmodule, CO_CANtx_t *buffer);
    
    
    /**
     * Clear all synchronous TPDOs from CAN module transmit buffers.
     * 在CAN模块中的发送缓冲区清除所有的同步TPDO
     *
     * CANopen allows synchronous PDO communication only inside time between SYNC
     * message and SYNC Window. If time is outside this window, new synchronous PDOs
     * must not be sent and all pending sync TPDOs, which may be on CAN TX buffers,
     * must be cleared.
     *
     * This function checks (and aborts transmission if necessary) CAN TX buffers
     * when it is called. Function should be called by the stack in the moment,
     * when SYNC time was just passed out of synchronous window.
     *
     * @param CANmodule This object.
     */
    void CO_CANclearPendingSyncPDOs(CO_CANmodule_t *CANmodule);
    
    
    /**
     * Verify all errors of CAN module.
     * 校验所有的额错误CAN模块
     *
     * Function is called directly from CO_EM_process() function.
     *
     * @param CANmodule This object.
     */
    void CO_CANverifyErrors(CO_CANmodule_t *CANmodule);
    
    
    /**
     * Receives and transmits CAN messages.
     * 接收、发送CAN信息
     *
     * Function must be called directly from high priority CAN interrupt.
     *
     * @param CANmodule This object.
     */
    void CO_CANinterrupt(CO_CANmodule_t *CANmodule);
    
    
    /** @} */
    #endif
  • 相关阅读:
    gsoap、c++。webservice的client。
    2.5给定两个用链表表示的整数,每个结点包含一个数位。这些数位是反向存放的,也就是个位排在链表首部。编写函数对这两个整数求和,并用链表形式返回结果。进阶:假设这些数位是正向存放的。
    c++、webServices、gsoap、tinyxml、iconv
    2.4编写代码,以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或者等于x的结点之前。
    CMD窗口快捷键
    IE7下position:relative与overflow的问题
    关于ASP.NET下,JQuery+AJAX使用JSON返回对象集合List数据的总结
    找不到可安装的 ISAM(必解决)
    jquery mini ui
    Unity3D
  • 原文地址:https://www.cnblogs.com/zengjfgit/p/6610713.html
Copyright © 2011-2022 走看看