【问题标题】:Emdedded C strcpy copies only first 10 bytes嵌入式 C strcpy 仅复制前 10 个字节
【发布时间】:2025-12-04 10:10:02
【问题描述】:

在使用 memcpy 或 strcpy 时,我在 Atmel Studio 中遇到问题。当开关计算为 TYPE3 时,仅复制前 10 个字节。当case的顺序相互交换时,其他strcpy的工作。我真的不明白为什么这会有所作为,以及为什么简单的 strcpy 不起作用。任何帮助表示赞赏。

t_RdmPacket 在包含文件中定义:

typedef union T_RdmPacket
{
    uint8_t Slot[257];  // Maximale grootte Packet = 255 bytes, + 2 Checksum bytes
    struct
    {
        uint8_t Preamble[8];
        uint8_t ManIDMsbOr0xAA;
        uint8_t ManIDMsbOr0x55;
        uint8_t ManIDLsbOr0xAA;
        uint8_t ManIDLsbOr0x55;
        uint8_t ProdIDMsbOr0xAA;
        uint8_t ProdIDMsbOr0x55;
        uint8_t ProdIDLsbOr0xAA;
        uint8_t ProdIDLsbOr0x55;
        uint8_t SerNrMsbOr0xAA;
        uint8_t SerNrMsbOr0x55;
        uint8_t SerNrLsbOr0xAA;
        uint8_t SerNrLsbOr0x55;
        uint8_t ChecksumMsbOr0xAA;
        uint8_t ChecksumMsbOr0x55;
        uint8_t ChecksumLsbOr0xAA;
        uint8_t ChecksumLsbOr0x55;
    } DiscoveryResponse;
    struct
    {
        uint8_t StartCodeRDM;       //Slot 0
        uint8_t SubStartCode;       //Slot 1
        uint8_t MessageLength;      //Slot 2                Min 24, Max 255
        struct
        {
            uint16_t    ManID;      //Slot 3 & 4    /   9 & 10
            uint16_t    ProdID;     //Slot 5 & 6    /   11 & 12
            uint16_t    SerNr;      //Slot 7 & 8    /   13 & 14
        } Destination, Source;
        uint8_t     TransactionNumber;  //Slot 15
        uint8_t     ResponseType;       //Slot 16
        uint8_t     MessageCount;       //Slot 17
        uint16_t    SubDevice;          //Slot 18 & 19
        uint8_t     CommandClass;       //Slot 20
        uint16_t    ParameterID;        //Slot 21 & 22
        uint8_t     PDL;                //Slot 23           Min 0, Max 231
        uint8_t     ParameterData[231]; //Slot 24 t/m 254
        uint16_t    Checksum;           //Slot 255 & 256
    } Packet;
} t_RdmPacket;

然后在包的处理中:

t_RdmPacket Rdm;

void sendGetDeviceModelDescriptionResponse(uint8_t *uid) {
    uint16_t checkSum;
    memset(Rdm.Packet.ParameterData, 0, 231);
    uint8_t size = 0;
    const char* text1 = "1234567890123456";
    const char* text2 = "6543210987654321";
    const char* text3 = "123456789012345";
    const char* responderText = "Multi RDM Responder";
    const char* dummyText = "Dummy RDM Responder";

    if (slaveDevice == -1) 
    {
        strcpy((char*)Rdm.Packet.ParameterData, responderText);
        size = 19;
    }
    else
    {
        switch(SlaveResponder[slaveDevice].DeviceModelID)
        {
            case TYPE1:
                strcpy((char*)Rdm.Packet.ParameterData, text1);
                size = 16;
                break;
            case TYPE2:
                strcpy((char*)Rdm.Packet.ParameterData, text2);
                size = 16;
                break;
            case TYPE3:
                strcpy((char*)Rdm.Packet.ParameterData, text3);
                size = 15;
                if (Rdm.Packet.ParameterData[11]==0)
                {
                    // I get here, I don't know why..
                    PORTD SET_B(3); // Debug LED On
                }
                break;
            default:
                strcpy((char*)Rdm.Packet.ParameterData, dummyText);
                size = 19;
                break;
        }
    }

    createRdmHeader(uid);
    Rdm.Packet.ResponseType = RESPONSE_TYPE_ACK;
    Rdm.Packet.CommandClass = GET_COMMAND_RESPONSE;
    Rdm.Packet.PDL = size;

    Rdm.Packet.MessageLength = 24 + Rdm.Packet.PDL;
    checkSum = calculateCheckSum();
    Rdm.Slot[Rdm.Packet.MessageLength] = (checkSum & 0xFF00) >> 8;
    Rdm.Slot[Rdm.Packet.MessageLength + 1] = checkSum & 0x00FF;

    setWaitTimer();
}

【问题讨论】:

  • Packet.ParameterDatas 的类型是什么?
  • Packet.ParameterData 的类型是 uint8_t: uint8_t Packet.ParameterData[231] 我已经用这个信息更新了问题。
  • 我认为问题出在 strcpy 的第二个参数上,imo 它应该是字符串的地址而不是确切的字符串。我不知道你的编译器对这些字符串做了什么。
  • 请在代码中准确声明Packet结构和Packet变量
  • 也许您不小心将Packet 存储在只读内存中?请提供minimal reproducible example

标签: strcpy atmega atmelstudio


【解决方案1】:

我将扩展我的评论。
AFAIK 我知道函数 strcpy() 有两个参数 strcpy(char * to, char* from),其中 tofrom 是地址。您将它与确切的字符串一起使用,也许没有警告,因为您的 IDE 禁用了它。确保在编译时使用 -Wall

我认为你应该尝试使用一些const char * constant_value = "5432154321543215",而不是使用第二个参数作为字符串调用 strcpy。 对我来说很难说你的 strcpy 实现是什么。

首先,在您的情况下,我会确保您会看到编译中的所有警告。

【讨论】: