在 PIC C18 中调用时出现问题,参数出现乱码 - 也许使用指向结构的指针?

发布于 2024-12-01 05:08:09 字数 2414 浏览 5 评论 0原文

我正在尝试使用 PICC18 进行相当简单的呼叫。

使用 MPLAB 模拟器,我看到参数甚至在进入函数时也完全是乱码。

我有以下 typedef

typedef struct
{
    //  t_ax25AddressChar callsign[6];
    unsigned char callsign[6];
    union
    {
        struct
        {
            unsigned isRepeated:1; // MSB - 1=repeated
            unsigned reserved:2; // Reserved
            unsigned ssid:4; // SSID
            unsigned isLast:1; // LSB - Is the last address
        };
        unsigned char value;
    } flags;
} t_ax25Callsign;

(我的 TODO 列表包括计算出我需要指定位域的顺序)

它嵌入在另一个结构中

typedef struct
{
    union
    {
        struct
        {
            t_ax25Callsign to;
            t_ax25Callsign from;
            t_ax25Callsign path[APRS_MAX_REPEATERS];
        };
        t_ax25Callsign allCallsigns[APRS_MAX_REPEATERS + 2];
    } address;
    // PID and Control are hard coded for APRS
    const char message[APRS_MAX_MESSAGE_LENGTH + 1]; // null terminated message string
} t_aprsPacket;

并分配在分页 RAM 中的某个位置(在 main.c 中)

#pragma udata   
static t_aprsPacket s_packet;

aprs.h 中定义的方法

extern void aprsMakeCallsignPgm(t_ax25Callsign *buffer,
                                const rom char *callsign, unsigned char ssid);

(我确实尝试过在 string.h 的示例中添加“far”没有效果 - 在这个 PIC 上我没有 64K,所以真的应该将所有内容重新编译为“near”)

aprs.c 中的实现是

void aprsMakeCallsignPgm(t_ax25Callsign *buffer,
                     const rom char *callsign,
                     unsigned char ssid)
{
    int i = 0;
    volatile char ch;
    for(i=0; i<6 && (ch = callsign[i]) != 0; i++)
    {
        buffer->callsign[i] = ch << 1;
    }
    for(   ; i<6; i++)
    {
        buffer->callsign[i] = (' '<<1);
    }

    buffer->flags.value = 0;
    buffer->flags.ssid = ssid;
}

(它)最好先让它工作。这个实现让我在循环中看到 ch 中的内容。)

main.c 中 main() 的几个调用都

aprsMakeCallsignPgm(&(s_packet.address.from), "M0RJC", (unsigned char)9);
aprsMakeCallsignPgm(&(s_packet.address.to), "APRS", 0);
s_packet.address.to.flags.isLast = 1;
strcpypgm2ram(s_packet.message, "Hard coded test message");

没有帮助。任何一个。

前三行可以编译,但在 MPLAB 模拟器中运行时,函数实现的参数中会产生乱码。

strcpy 行给出编译器警告“警告 [2066] 赋值中类型限定符不匹配”。如果它能告诉我哪个作业就好了。

我在这里做错了什么?

谢谢

  • 理查德

I am trying to make a fairly simple call using PICC18.

Using the MPLAB simulator I am seeing the arguments, even on entry to the function, being completely garbled.

I have the following typedef

typedef struct
{
    //  t_ax25AddressChar callsign[6];
    unsigned char callsign[6];
    union
    {
        struct
        {
            unsigned isRepeated:1; // MSB - 1=repeated
            unsigned reserved:2; // Reserved
            unsigned ssid:4; // SSID
            unsigned isLast:1; // LSB - Is the last address
        };
        unsigned char value;
    } flags;
} t_ax25Callsign;

(My TODO list includes working out the order I need to specify bitfields)

That is embedded in a further struct

typedef struct
{
    union
    {
        struct
        {
            t_ax25Callsign to;
            t_ax25Callsign from;
            t_ax25Callsign path[APRS_MAX_REPEATERS];
        };
        t_ax25Callsign allCallsigns[APRS_MAX_REPEATERS + 2];
    } address;
    // PID and Control are hard coded for APRS
    const char message[APRS_MAX_MESSAGE_LENGTH + 1]; // null terminated message string
} t_aprsPacket;

and allocated somewhere in paged RAM (in main.c)

#pragma udata   
static t_aprsPacket s_packet;

The method defined in aprs.h

extern void aprsMakeCallsignPgm(t_ax25Callsign *buffer,
                                const rom char *callsign, unsigned char ssid);

(I did try putting a "far" in there following string.h's example. No effect - and on this PIC I don't have 64K so really ought to recompile everything as 'near')

The implementation in aprs.c is

void aprsMakeCallsignPgm(t_ax25Callsign *buffer,
                     const rom char *callsign,
                     unsigned char ssid)
{
    int i = 0;
    volatile char ch;
    for(i=0; i<6 && (ch = callsign[i]) != 0; i++)
    {
        buffer->callsign[i] = ch << 1;
    }
    for(   ; i<6; i++)
    {
        buffer->callsign[i] = (' '<<1);
    }

    buffer->flags.value = 0;
    buffer->flags.ssid = ssid;
}

(It could be optimised. Best get this working first. This implementation lets me see what's in ch as it goes round the loop.)

A couple of calls from main() in main.c are

aprsMakeCallsignPgm(&(s_packet.address.from), "M0RJC", (unsigned char)9);
aprsMakeCallsignPgm(&(s_packet.address.to), "APRS", 0);
s_packet.address.to.flags.isLast = 1;
strcpypgm2ram(s_packet.message, "Hard coded test message");

That cast to (unsigned char) didn't help either.

The first three lines compile, but when run in the MPLAB simulator produce gibberish in the arguments in the function implementation.

The strcpy line gives a compiler warning "Warning [2066] type qualifier mismatch in assignment". It would be nice if it told me which assignment.

What have I done wrong here?

Thanks

  • Richard

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

临走之时 2024-12-08 05:08:09

我正在调用一个使用 FSR2 的汇编器 init 例程,因此损坏了 C 堆栈。
我将其更改为使用 FSR0,现在它可以工作了。

执行相同操作的较短代码是

void aprsMakeCallsignPgm(t_ax25Callsign *buffer,
                         const rom char *callsign,
                         unsigned char ssid)
{
    int i; 
    overlay char *dst = buffer->callsign;
    for(i = 6; i && (*dst++ = (*callsign++ << 1)); i--);
    dst--; // Rewind that 0. Good job flags is there to save from overrun
    for(   ; i ; i--) *dst++ = (' '<<1);

    buffer->flags.value = (ssid & 0x0F) << 1;
}

我在“调试”模式下编译的,因此没有优化。看看它在这种模式下的表现很有用,因为我只有编译器的评估版本。新版本节省了 66 个程序位置和 3 字节 RAM。它还告诉我,位字段的正确方法是

   struct
    {
        unsigned isLast:1;     // LSB - Is the last address
        unsigned ssid:4;       // SSID
        unsigned reserved:2;   // Reserved
        unsigned isRepeated:1; // MSB - 1=repeated
    };

我采用 <<运算符不包括进位。

谢谢
- 理查德

(我会将此问题标记为删除 - 但请注意,它已被标记为最喜欢的,因此不想将其从某人的脚下扫除)

I was calling an assembler init routine which was using FSR2, so corrupting the C stack.
I changed it to use FSR0 instead and it now works.

The shorter code that does the same thing is

void aprsMakeCallsignPgm(t_ax25Callsign *buffer,
                         const rom char *callsign,
                         unsigned char ssid)
{
    int i; 
    overlay char *dst = buffer->callsign;
    for(i = 6; i && (*dst++ = (*callsign++ << 1)); i--);
    dst--; // Rewind that 0. Good job flags is there to save from overrun
    for(   ; i ; i--) *dst++ = (' '<<1);

    buffer->flags.value = (ssid & 0x0F) << 1;
}

I'm compiling in "debug" mode, so not optimising. It's useful to see how it does in this mode as I only have the evaluation version of the compiler. The new versions saves 66 program locations and 3 bytes of RAM. It also teaches me that the correct way round for bitfields is

   struct
    {
        unsigned isLast:1;     // LSB - Is the last address
        unsigned ssid:4;       // SSID
        unsigned reserved:2;   // Reserved
        unsigned isRepeated:1; // MSB - 1=repeated
    };

I take the << operator as not including carry.

Thanks
- Richard

(I would mark this question for remove - but note it has been marked a favourite so don't want to sweep it from underneath someone's feet)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文