硬汉嵌入式论坛

 找回密码
 立即注册
查看: 1191|回复: 3
收起左侧

[CAN/FDCAN] CANopenNode主机做SDO通信测试代码

[复制链接]

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
111540
QQ
发表于 2023-10-14 07:39:09 | 显示全部楼层 |阅读模式

主机对应的是SDO客户端,从机对应的是SDO服务器,这点不要搞反了。

[C] 纯文本查看 复制代码
/**
 * @defgroup CO_SDOclient SDO client
 * CANopen Service Data Object - client protocol.
 *
 * @ingroup CO_CANopen_301
 * @{
 * SDO client is able to access Object Dictionary variables from remote nodes.
 * Usually there is one SDO client on CANopen network, which is able to
 * configure other CANopen nodes. It is also possible to establish individual
 * SDO client-server communication channels between devices.
 *
 * SDO client is used in CANopenNode from CO_gateway_ascii.c with default SDO
 * CAN identifiers. There is quite advanced usage in non-blocking function.
 *
 * If enabled, SDO client is initialized in CANopen.c file with
 * @ref CO_SDOclient_init() function.
 *
 * Basic usage:
 * @code{.c}
CO_SDO_abortCode_t read_SDO(CO_SDOclient_t *SDO_C, uint8_t nodeId,
                            uint16_t index, uint8_t subIndex,
                            uint8_t *buf, size_t bufSize, size_t *readSize)
{
    CO_SDO_return_t SDO_ret;

    // setup client (this can be skipped, if remote device don't change)
    SDO_ret = CO_SDOclient_setup(SDO_C,
                                 CO_CAN_ID_SDO_CLI + nodeId,
                                 CO_CAN_ID_SDO_SRV + nodeId,
                                 nodeId);
    if (SDO_ret != CO_SDO_RT_ok_communicationEnd) {
        return CO_SDO_AB_GENERAL;
    }

    // initiate upload
    SDO_ret = CO_SDOclientUploadInitiate(SDO_C, index, subIndex, 1000, false);
    if (SDO_ret != CO_SDO_RT_ok_communicationEnd) {
        return CO_SDO_AB_GENERAL;
    }

    // upload data
    do {
        uint32_t timeDifference_us = 10000;
        CO_SDO_abortCode_t abortCode = CO_SDO_AB_NONE;

        SDO_ret = CO_SDOclientUpload(SDO_C,
                                     timeDifference_us,
                                     false,
                                     &abortCode,
                                     NULL, NULL, NULL);
        if (SDO_ret < 0) {
            return abortCode;
        }

        sleep_us(timeDifference_us);
    } while(SDO_ret > 0);

    // copy data to the user buffer (for long data function must be called
    // several times inside the loop)
    *readSize = CO_SDOclientUploadBufRead(SDO_C, buf, bufSize);

    return CO_SDO_AB_NONE;
}

CO_SDO_abortCode_t write_SDO(CO_SDOclient_t *SDO_C, uint8_t nodeId,
                             uint16_t index, uint8_t subIndex,
                             uint8_t *data, size_t dataSize)
{
    CO_SDO_return_t SDO_ret;
    bool_t bufferPartial = false;

    // setup client (this can be skipped, if remote device is the same)
    SDO_ret = CO_SDOclient_setup(SDO_C,
                                 CO_CAN_ID_SDO_CLI + nodeId,
                                 CO_CAN_ID_SDO_SRV + nodeId,
                                 nodeId);
    if (SDO_ret != CO_SDO_RT_ok_communicationEnd) {
        return -1
    }

    // initiate download
    SDO_ret = CO_SDOclientDownloadInitiate(SDO_C, index, subIndex,
                                           dataSize, 1000, false);
    if (SDO_ret != CO_SDO_RT_ok_communicationEnd) {
        return -1
    }

    // fill data
    size_t nWritten = CO_SDOclientDownloadBufWrite(SDO_C, data, dataSize);
    if (nWritten < dataSize) {
        bufferPartial = true;
        // If SDO Fifo buffer is too small, data can be refilled in the loop.
    }

    //download data
    do {
        uint32_t timeDifference_us = 10000;
        CO_SDO_abortCode_t abortCode = CO_SDO_AB_NONE;

        SDO_ret = CO_SDOclientDownload(SDO_C,
                                       timeDifference_us,
                                       false,
                                       bufferPartial,
                                       &abortCode,
                                       NULL, NULL);
        if (SDO_ret < 0) {
            return abortCode;
        }

        sleep_us(timeDifference_us);
    } while(SDO_ret > 0);

    return CO_SDO_AB_NONE;
}


通信格式:

12.png
回复

使用道具 举报

0

主题

5

回帖

5

积分

新手上路

积分
5
发表于 2023-10-25 16:44:01 | 显示全部楼层
感谢分享,期待后续课程
回复

使用道具 举报

4

主题

170

回帖

182

积分

初级会员

积分
182
发表于 2023-11-27 14:27:15 | 显示全部楼层
这个移植简单吗
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
111540
QQ
 楼主| 发表于 2023-11-27 15:25:11 | 显示全部楼层
fyyxxm 发表于 2023-11-27 14:27
这个移植简单吗

简单,底层驱动都是做好的,简单配置即可。此贴一楼末尾有主从机例子。

BSP视频教程第28期:CANopen协议栈专题,CANopen主从机组网实战,CAN词典工具使用方法以及吃透PDO玩法(2023-11-01)
https://www.armbbs.cn/forum.php?mod=viewthread&tid=121619
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-11-1 07:36 , Processed in 0.217162 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表