打印
[应用相关]

发一个关于 CANOPEN 的例程。CiA401 德国CiA网站下载

[复制链接]
2665|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
東南博士|  楼主 | 2018-9-3 09:20 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/*
* Main.c
*
*  Created on: 15.01.2014
*      Author: oe
*      emtas GmbH
*/

/* header of standard C - libraries
---------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>

/* header of project specific types
---------------------------------------------------------------------------*/
#include <gen_define.h>

#include <co_canopen.h>
#include <co_401.h>
#include <usr_401.h>

#include <stm32f4_discovery.h>
#include <stm32f4xx_gpio.h>
#include <stm32f4xx_rcc.h>
#include <stm32f4xx_usart.h>

/* list of external used functions, if not in headers
--------------------------------------------------------------------------*/
void SystemInit(void);
void SystemCoreClockUpdate(void);
int codrvHardwareInit(void);

/* list of local defined functions
---------------------------------------------------------------------------*/
static RET_T nmtInd(BOOL_T  execute, CO_NMT_STATE_T newState);
static void hbState(UNSIGNED8   nodeId, CO_ERRCTRL_T state,
        CO_NMT_STATE_T  nmtState);
static RET_T sdoServerReadInd(BOOL_T execute, UNSIGNED8 sdoNr, UNSIGNED16 index,
        UNSIGNED8   subIndex);
static RET_T sdoServerCheckWriteInd(BOOL_T execute, UNSIGNED8 node,
        UNSIGNED16 index, UNSIGNED8 subIndex, const UNSIGNED8 *pData);
static RET_T sdoServerWriteInd(BOOL_T execute, UNSIGNED8 sdoNr,
        UNSIGNED16 index, UNSIGNED8 subIndex);
static void pdoInd(UNSIGNED16);
static void pdoRecEvent(UNSIGNED16);
static void canInd(CO_CAN_STATE_T);
static void commInd(CO_COMM_STATE_EVENT_T);
static void ledGreenInd(BOOL_T);
static void ledRedInd(BOOL_T);
static void evaTimeOver(void *pData);
void InitUSART2(int speed);

/* global variables
---------------------------------------------------------------------------*/

/* local defined variables
---------------------------------------------------------------------------*/
static CO_TIMER_T        evaTimer;   /**< local timer used as one-shot timer */

static int speed = 125;                 /**< CAN speed used in Kbit/s */

int main(void)
{
        /* Generic Board initialization */
        SystemInit();
        SystemCoreClockUpdate();

        /* initialize on-board LEDs */
        STM_EVAL_LEDInit(LED3);        /* orange                                        */
        STM_EVAL_LEDInit(LED4); /* green, used by CANopen        */
        STM_EVAL_LEDInit(LED5); /* red                                                */
        STM_EVAL_LEDInit(LED6);        /* blue                                                */

        /* initialize USART2/USB for printf() debug messages */
        InitUSART2(115200); /* use a high speed, because TX polling */
       
        printf("\n\n************** START ***************\n\n");
        printf("Slave CiA 401 example, compiled %s\n", __DATE__);
       
        /* init customer CAN hardware */
        codrvHardwareInit();
        /* additional hardware initialization */
        p401HardwareInit();

        printf("CAN init with %d Kbit/s\n", speed);
        if (codrvCanInit(speed) != RET_OK)  {
                exit(1);

        }
        if (coCanOpenStackInit(NULL) != RET_OK)  {
            printf("error init library\n");
            exit(1);
        }

        if (codrvTimerSetup(CO_TIMER_INTERVAL) != RET_OK)  {
            exit(2);
        }

    /* register event functions */
    if (coEventRegister_NMT(nmtInd) != RET_OK)  {
        exit(3);
    }
    if (coEventRegister_ERRCTRL(hbState) != RET_OK)  {
        exit(4);
    }
    if (coEventRegister_SDO_SERVER_READ(sdoServerReadInd) != RET_OK)  {
        exit(5);
    }
    if (coEventRegister_SDO_SERVER_CHECK_WRITE(sdoServerCheckWriteInd) != RET_OK)  {
        exit(6);
    }
    if (coEventRegister_SDO_SERVER_WRITE(sdoServerWriteInd) != RET_OK)  {
        exit(7);
    }
    if (coEventRegister_PDO(pdoInd) != RET_OK)  {
        exit(8);
    }
    if (coEventRegister_PDO_REC_EVENT(pdoRecEvent) != RET_OK)  {
        exit(9);
    }
    if (coEventRegister_LED_GREEN(ledGreenInd) != RET_OK)  {
        exit(10);
    }
    if (coEventRegister_LED_RED(ledRedInd) != RET_OK)  {
        exit(11);
    }
    if (coEventRegister_CAN_STATE(canInd) != RET_OK)  {
        exit(12);
    }
    if (coEventRegister_COMM_EVENT(commInd) != RET_OK)  {
        exit(13);
    }

    /* --- 401 specific ------------------------------------------------*/
    /* profile 401 HW acess registration */
    if (co401Init() != RET_OK)  {
        // printf("error init 401 profile handler\n");
        exit(14);
    }

    if (coEventRegister_401(
                byte_in_piInd,      /* digital in  HW API function   */
                byte_out_printfInd,     /* digital out HW API function   */
                analog_in_piInd,    /* the analog in HW API function */
                analog_out_printfInd    /* analog out HW API function    */
                ) != RET_OK)  {
        printf("Registration of 401 HW access functions failed\n");
        exit(15);
    }
    /* -----------------------------------------------------------------*/

        /* set up a timer to signal that the evaluation period is over soon.
         * The battery example is build        using an CANopen stack library
         * which only works for a specified period of time. If this duration
         * is over, CANopen simply stops working */
        if(coTimerStart(&evaTimer, 60*60*1000000ul, evaTimeOver, NULL, CO_TIMER_ATTR_ROUNDUP) != RET_OK) {
                exit(16);
        }

    printf("Enable CAN and go into application loop\n\r\n");
    codrvCanEnable();
        while (1)  {
                coCommTask();
                co401Task();
        }
}

/* Evaluation period is over, switch blue LED on */
static void evaTimeOver(void *pData)
{
        (void)pData; /* not used */
    printf("\nBe prepared, application will stop working soon\n");
        STM_EVAL_LEDOn(LED6);
}

/*********************************************************************
The following are definitions of communication indication functions.
The application can use these functions to process communication events
application specific. This example, implementing the CiA 401 profile,
is only using the indications to display it using simple printf()
messages.
**********************************************************************/
/*********************************************************************/
RET_T nmtInd(
    BOOL_T  execute,
    CO_NMT_STATE_T  newState
)
{
        printf("USR: nmtInd: New Nmt state %d - execute %d\n", newState, execute);
        return(RET_OK);
}


/*********************************************************************/
void pdoInd(
    UNSIGNED16  pdoNr
)
{
        printf("USR: pdoInd: pdo %d received\n", pdoNr);
}


/*********************************************************************/
void pdoRecEvent(
    UNSIGNED16  pdoNr
)
{
        printf("USR: pdoRecEvent: pdo %d time out\n", pdoNr);
}


/*********************************************************************/
void hbState(
    UNSIGNED8   nodeId,
    CO_ERRCTRL_T state,
    CO_NMT_STATE_T  nmtState
)
{
        printf("USR: hbInd: HB Event %d node %d nmtState: %d\n", state, nodeId, nmtState);
        return;
}



/*********************************************************************/
static RET_T sdoServerReadInd(
    BOOL_T      execute,
    UNSIGNED8   sdoNr,
    UNSIGNED16  index,
    UNSIGNED8   subIndex
)
{
        // printf("USR: sdo server read ind: exec: %d, sdoNr %d, index %x:%d\n",
        //  execute, sdoNr, index, subIndex);

        return(RET_OK);
}


/*********************************************************************/
static RET_T sdoServerCheckWriteInd(
    BOOL_T      execute,
    UNSIGNED8   sdoNr,
    UNSIGNED16  index,
    UNSIGNED8   subIndex,
    const UNSIGNED8 *pData
)
{
        // printf("USR: sdo server check write ind: exec: %d, sdoNr %d, index %x:%d\n",
        //  execute, sdoNr, index, subIndex);

        return(RET_OK);
}


/*********************************************************************/
static RET_T sdoServerWriteInd(
    BOOL_T      execute,
    UNSIGNED8   sdoNr,
    UNSIGNED16  index,
    UNSIGNED8   subIndex
)
{
        // printf("USR: sdo server write ind: exec: %d, sdoNr %d, index %x:%d\n",
        //  execute, sdoNr, index, subIndex);

        return(RET_OK);
}


/*********************************************************************/
static void canInd(
CO_CAN_STATE_T  canState
)
{
        switch (canState)  {
                case CO_CAN_STATE_BUS_OFF:
                        printf("USR: CAN: Bus Off\n\n");
                        break;
                case CO_CAN_STATE_BUS_ON:
                        printf("USR: CAN: Bus On\n\n");
                        break;
                case CO_CAN_STATE_PASSIVE:
                        printf("USR: CAN: Passiv\n\n");
                        break;
                case CO_CAN_STATE_UNCHANGED:
                        printf("USR: CAN: unchanged\n");
                        break;
                default:
                        break;
        }
}


/*********************************************************************/
static void commInd(
    CO_COMM_STATE_EVENT_T   commEvent
)
{

switch (commEvent)  {
    case CO_COMM_STATE_EVENT_BUS_OFF:
        // printf("COMM-Event Bus Off\n");
        break;
    case CO_COMM_STATE_EVENT_BUS_OFF_RECOVERY:
        // printf("COMM-Event Bus Off\n");
        break;
    case CO_COMM_STATE_EVENT_BUS_ON:
        // printf("COMM-Event Bus On\n");
        break;
    case CO_COMM_STATE_EVENT_PASSIVE:
        // printf("COMM-Event Bus Passive\n");
        break;
    case CO_COMM_STATE_EVENT_ACTIVE:
        // printf("COMM-Event Bus Active\n");
        break;
    case CO_COMM_STATE_EVENT_CAN_OVERRUN:
        // printf("COMM-Event CAN Overrun\n");
        break;
    case CO_COMM_STATE_EVENT_REC_QUEUE_FULL:
        // printf("COMM-Event Rec Queue Full\n");
        break;
    case CO_COMM_STATE_EVENT_REC_QUEUE_OVERFLOW:
        // printf("COMM-Event Rec Queue Overflow\n");
        break;
    case CO_COMM_STATE_EVENT_TR_QUEUE_FULL:
        // printf("COMM-Event Tr Queue Full\n");
        break;
    case CO_COMM_STATE_EVENT_TR_QUEUE_OVERFLOW:
        // printf("COMM-Event Tr Queue Empty\n");
        break;
    case CO_COMM_STATE_EVENT_TR_QUEUE_EMPTY:
        // printf("COMM-Event Tr Queue Empty\n");
        break;
    default:
        break;
}

}

/*********************************************************************/
/* LED indication functions, control on-board LEDs */
static void ledGreenInd(
                BOOL_T        on
        )
{
#if 1
        if(on) {
                STM_EVAL_LEDOn(LED4);
        } else {
                STM_EVAL_LEDOff(LED4);
        }
#endif
}


/*********************************************************************/
static void ledRedInd(
                BOOL_T        on
        )
{
#if 1
        if (on) {
                STM_EVAL_LEDOn(LED4);
        } else {
                STM_EVAL_LEDOff(LED4);
        }
#endif
}

void InitUSART2(int speed)
{
USART_InitTypeDef USART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;

        speed = speed;
        /* Enable clocks */
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

        /* Configure UART2_Tx pin PA2 */
        GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_2;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
        GPIO_Init (GPIOA, &GPIO_InitStructure);

        /* Connect USART2 pins to AF2 */
        GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);

        /* Configure UART2_Rx pin PA3 */
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
        GPIO_Init (GPIOA, &GPIO_InitStructure);
        GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2);

        USART_StructInit(&USART_InitStructure);
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
        USART_InitStructure.USART_StopBits = USART_StopBits_1;
        USART_InitStructure.USART_Parity = USART_Parity_No ;
        USART_InitStructure.USART_BaudRate = speed;
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
        USART_InitStructure.USART_Mode = (USART_Mode_Tx | USART_Mode_Rx);

        USART_Init(USART2, &USART_InitStructure);
        /* enable USART2 */
        USART_Cmd(USART2, ENABLE);
}

/* exit() is implemented to switch on the error LED
* and stay in a while() loop
* proto type is in stdlib.h
*/
void exit(int exitcode)
{
        printf("Run time error %d", exitcode);
        STM_EVAL_LEDOn(LED4);
        while(1);
}

/* vim: set ts=4 sw=4 spelllang=en : */


沙发
東南博士|  楼主 | 2018-9-3 09:22 | 只看该作者
/*
* CANopen Stack definitions for 401 - generated by CANopen DeviceDesigner 1.1.7
* Mon Sep 30 11:14:28 2013
*/

/* protect against multiple inclusion of the file */
#ifndef GEN_DEFINE_H
#define GEN_DEFINE_H 1

/* Definition of CANopen NodeID */
#define CO_NODE_ID        32

/* Definition of numbers of CANopen services */
#define CO_SDO_SERVER_CNT        1u
#define CO_PDO_TRANSMIT_CNT        2u
#define CO_PDO_RECEIVE_CNT        6u
#define CO_MAX_MAP_ENTRIES        4u
#define CO_PDO_DYN_MAP_ENTRIES        8u
#define CO_SYNC_SUPPORTED        1u
#define CO_EMCY_PRODUCER        1u

/* Definition of number of call-back functions for each service*/
#define CO_EVENT_SDO_SERVER_READ        2u
#define CO_EVENT_SDO_SERVER_WRITE        2u
#define CO_EVENT_SDO_SERVER_CHECK_WRITE        1u
#define CO_EVENT_PDO        2u
#define CO_EVENT_NMT        2u
#define CO_EVENT_ERRCTRL        1u
#define CO_EVENT_LED        1u
#define CO_EVENT_CAN        2u
#define CO_EVENT_EMCY        1u

/* number of used COB objects */
#define CO_COB_CNT        14u

/* Definition of CAN queue sizes */
#define CO_CONFIG_REC_BUFFER_CNT        5u
#define CO_CONFIG_TRANS_BUFFER_CNT        5u

/* application-specific defines as defined in CANopen DeviceDesigner */
#define CO_PROFILE_401 1
#define  CO_TIMER_INTERVAL       10000L
#define CO_RTR_NOT_SUPPORTED
/* end of application-specific defines */

/* do not modify comments starting with 'user-specific section:' */
/* user-specific section: start */
// #define DEBUG_SEND_TESTMESSAGE

/* user-specific section: end */

#endif /* GEN_DEFINE_H */

使用特权

评论回复
板凳
晓伍| | 2018-9-3 09:38 | 只看该作者
非常感谢楼主分享

使用特权

评论回复
地板
磨砂| | 2018-9-3 09:43 | 只看该作者
外设还需要加什么芯片

使用特权

评论回复
5
東南博士|  楼主 | 2018-9-3 09:48 | 只看该作者
不过 好像 CANOPEN 似乎很晦涩难懂   看了很久 才感觉刚刚理解了一点点

使用特权

评论回复
6
木木guainv| | 2018-9-4 11:08 | 只看该作者
有应用成功的吗

使用特权

评论回复
7
Diyer2015| | 2018-9-4 14:34 | 只看该作者
感觉 没有经过 熟练工程师的培训 没有上过培训课 似乎很难!

使用特权

评论回复
8
yyyyy1231312| | 2021-10-27 16:11 | 只看该作者
#include <co_canopen.h> CANopen的
请问这个头文件有没有,感谢。vx17852021353

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

381

主题

6080

帖子

34

粉丝