library for C++ CANOpen implementation. mbed independant, but is easy to attach into with mbed.

Dependents:   ppCANOpen_Example DISCO-F746NG_rtos_test

Example:

Import programppCANOpen_Example

I am no longer actively working on the ppCANOpen library, however, I want to publish this project so that anyone who wants to pick up any of the pieces can have a good example. This is a a project I was working on using the ppCANOpen library. It has a pretty in deep use of the object dictionary structure. And a number of functions to control high voltage pinball drivers, if you're into that sort of thing.

drivers/mbed-Nucleo-F091RC/canopen_api.cpp

Committer:
ptpaterson
Date:
2016-02-13
Revision:
5:22a337cdc0e3
Parent:
4:2034b04c86d2

File content as of revision 5:22a337cdc0e3:

/**
 ******************************************************************************
 * @file
 * @author  Paul Paterson
 * @version
 * @date    2015-12-14
 * @brief   CANOpen api for STM32 Nucleo-F091RC in mbed
 ******************************************************************************
 * @attention
 *
 * <h2><center>&copy; COPYRIGHT(c) 2015 Paul Paterson
 *
 * All rights reserved.

 This program is free 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 3 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/>.
 */

#include "canopen_api.h"
#include "canopen_config.h"

#include "CanOpenMessage.h"

#include "mbed.h" 
#include "CAN.h"  /* use with CANNucleo library */

#include "stdio.h"


void *pServiceObject = 0;

/* Can declarations ---------------------------------------------------------*/
CAN * can; //(CANOPEN_PIN_RX, CANOPEN_PIN_TX);
ServiceProviderRxInterruptCallback  serviceRxCallback = 0; 
void CanReadInterruptCallback (void) {
    if (serviceRxCallback && pServiceObject) {
        serviceRxCallback(pServiceObject);   
    }
}

/* Ticker declarations ---------------------------------------------------------*/
Ticker updateTicker;
ServiceProviderTickCallback serviceTickCallback = 0;
void UpdateTickerCallback(void) {
    if (serviceTickCallback && pServiceObject) {
        serviceTickCallback(pServiceObject);   
    }   
}

int CanOpenApiInit  (void *object, ServiceProviderRxInterruptCallback rxCallback, ServiceProviderTickCallback tickCallback)
{
    printf ("----------- CANOPEN API: API INIT\r\n");
    
    /* CAN instance to do all of the communication
     *
     * For some reason, I cannot use "static CAN can".  It will compile,
     * but code get's stuck during initialization, and will not even enter
     * main(). Works great like this though! Only one ServiceProvider, though,
     * so mem leaks should not be an issue if we don't delete it???
     */
    //static CAN can(CANOPEN_PIN_RX, CANOPEN_PIN_TX);
    //can = new CAN(CANOPEN_PIN_RX, CANOPEN_PIN_TX); 
    can = new CAN(CANOPEN_PIN_RX, CANOPEN_PIN_TX);
    //can.reset();
    
    /* init the callback system ---------------------------------------------*/
    pServiceObject = object;
    
    serviceRxCallback = rxCallback;
    serviceTickCallback = tickCallback;
    
    can->attach(CanReadInterruptCallback);
    updateTicker.attach(UpdateTickerCallback, .0005);
    
    return 1;
}

int CanOpenApiRead (CanOpenMessage *canOpenMsg)
{
    int result = 0;
    
    /* CAUTON ********************************
     * Could be used in interrupt!!!
     * ***************************************
     */
    //printf("canopen_api: CanOpenApiRead()\r\n");
    
    if (can) {
        
        CANMessage canMsg;
        
        result = can->read (canMsg);
        if (result) {
            canOpenMsg->id          = canMsg.id;
            canOpenMsg->dataCount   = canMsg.len, 
            canOpenMsg->type        = canMsg.type   == CANData      ? CANOPEN_TYPE_DATA         : CANOPEN_TYPE_REMOTE;
            canOpenMsg->format      = canMsg.format == CANStandard  ? CANOPEN_FORMAT_STANDARD   : CANOPEN_FORMAT_EXTENDED;
            
            // NOTE: memcpy is freezing execution
            //memcpy(canOpenMsg->data, canMsg.data, canMsg.len);
            canOpenMsg->data[0] = canMsg.data[0];
            canOpenMsg->data[1] = canMsg.data[1];
            canOpenMsg->data[2] = canMsg.data[2];
            canOpenMsg->data[3] = canMsg.data[3];
            canOpenMsg->data[4] = canMsg.data[4];
            canOpenMsg->data[5] = canMsg.data[5];
            canOpenMsg->data[6] = canMsg.data[6];
            canOpenMsg->data[7] = canMsg.data[7];
            
            // DEBUG
            //printf("   ID:      %d\r\n", (int)canOpenMsg->id);
            //printf("   Count:   %d\r\n", (int)canOpenMsg->dataCount);
            //printf("   Type:    %d\r\n", (int)canOpenMsg->type);
            //printf("   Format:  %d\r\n", (int)canOpenMsg->format);
            //printf("   Data[0]: %d\r\n", (int)canOpenMsg->data[0]);
        }
        
    }
    return result;
}

int CanOpenApiWrite (CanOpenMessage *canOpenMsg)
{
    int result = 0;
    
    CANMessage canMsg;
    canMsg.id       = canOpenMsg->id;
    canMsg.len      = canOpenMsg->dataCount, 
    canMsg.type     = canOpenMsg->type   == CANOPEN_TYPE_DATA       ? CANData     : CANRemote;
    canMsg.format   = canOpenMsg->format == CANOPEN_FORMAT_STANDARD ? CANStandard : CANExtended;
    
    // NOTE: memcpy is freezing execution
    //memcpy(canMsg.data, canOpenMsg->data, canOpenMsg->dataCount); 
    canMsg.data[0] = canOpenMsg->data[0];
    canMsg.data[1] = canOpenMsg->data[1];
    canMsg.data[2] = canOpenMsg->data[2];
    canMsg.data[3] = canOpenMsg->data[3];
    canMsg.data[4] = canOpenMsg->data[4];
    canMsg.data[5] = canOpenMsg->data[5];
    canMsg.data[6] = canOpenMsg->data[6];
    canMsg.data[7] = canOpenMsg->data[7];
                    
    result = can->write (canMsg);
    
    
    return result;
}

static int timeSyncOffset = 0;

uint32_t CanOpenApiGetHardwareTime (void)
{
    return HAL_GetTick();
}