【问题标题】:C18 Passing a char array to functionC18 将 char 数组传递给函数
【发布时间】:2014-04-10 13:35:29
【问题描述】:

我是 C 编程和微控制器的新手。我正在使用带有 C18 的 PIC18F24K20 微控制器。我将其设置为使用 USART 发送和接收功能从计算机输入接收信息。我的目标是将接收到的单词与已知单词进行比较,并根据接收到的单词将某些内容传输回计算机。下面是相关代码。

#include "p18f24k20.h"
#include "delays.h"
#include "string.h"
#include "stdlib.h"


void CommTransmit ( rom char * );

void main (void)
{
    char buf[11], data, T;
    int i;

    i = 0;
    memset(buf, 0, sizeof buf);

    while(1)
    {
        if (PIR1bits.RCIF)
        {
            data = USART_receive();
            if (data != 47)             // 47 is /, indicates end of string
            {
                buf[i] = data;
                i++;
            }
            else
            {
                // T = strcmppgm2ram(buf,(const far rom char*)"test");
                CommTransmit(buf);
                USART_transmit('t');
                buf[0] = 0'
            }
        }
    }
}


void CommTransmit ( rom char *CommVariable )
{
    char test;

    test = strcmppgm2ram(CommVariable, (const far rom char*)"test");
    if (test == 0)
    {
        USART_transmit('g');
    }
}

代码当前设置为进行测试以尝试确定问题所在。如果我按原样运行它,计算机将收到一个“t”,就好像微控制器通过 CommTransmit 函数运行一样。但是,它从不传输“g”。即使我在 CommTransmit 函数中调用了 USART_transmit('g'),在 if 语句之外和之后,它也永远不会被调用(就像它卡在 strcmppgm2ram 函数中一样?)但它仍然传输't'。

这也很奇怪,因为如果我在 CommTransmit 函数处设置一个中断并逐行运行,它似乎可以正常工作。但是,如果我查看 MPLAB IDE 中的 CommVariable,它永远不会是它应该的样子(尽管在被调用到函数中之前的“buf”变量是正确的)。据我所知,CommVariable 在我观察时的值取决于数组的大小。

从阅读中,我认为这可能是由微控制器如何存储变量(程序与数据存储器?)引起的,但我不确定。非常感谢任何帮助!

编辑:我还应该补充一点,如果我在 CommTransmit 行之前的 else 语句中取消注释 T = strcmppgm2ram 行,它可以正常工作(当两个字符串相同时,T = 0)。我相信当我通过函数时数组会发生变化,这会导致 strcmppgm2ram 函数无法正常工作。

【问题讨论】:

  • 嗨。我没有在 C18 上编程(但在其他嵌入式系统上);但我怀疑(const far rom char*)"test"。如果字符串文字不在内存的正确区域,则此强制转换不会移动它,它只会发送一个虚假指针。没有演员会怎样?
  • 顺便检查一下i < 11data != 47 的情况下
  • 鉴于看似随机的行为,听起来您在某处有一些与内存相关的错误。一些指针或数组错误破坏了内存,可能在 strcmppgm2ram() 中。那是用户定义的函数还是某个库函数?此外,由于这是一个 PIC,堆栈溢出总是一个可能的候选者。
  • @lundin strcmppgm2ram() 是一个库函数。以下是 string.h 文件的内容:signed char strcmppgm2ram (auto const char s1, auto const MEM_MODEL rom char *s2); /* name strcmpram2pgm * {\bf strcmpram2pgm} 函数执行 {\bf strcmp} 其中 {\bf s1} * 指向程序存储器, {\bf s2} 指向数据存储器。 * 参数 s1 指向程序存储器中字符串的指针 * 参数 s2 指向数据存储器中字符串的指针 */
  • CommTransmit 函数的参数可疑。为什么是rom?您正在将堆栈上的变量传递给它。 (一般来说,我更喜欢在 main 之外声明缓冲区以避免使用堆栈。)

标签: c arrays embedded pic18 c18


【解决方案1】:

查看 strcmppgm2ram

的签名
signed char strcmppgm2ram(const char * str1, const rom char * str2 );

我不明白您为什么要为 CommVariable 设置 rom char *。来自MPLAB® C18 C Compiler User’s Guide

2.4.3 ram/rom Qualifiers章节

因为 PICmicro 单片机使用单独的程序存储器和 在其设计中的数据存储器地址总线,MPLAB C18 需要 扩展以区分位于程序存储器中的数据和 数据位于数据存储器中。 /---/ 指针可以指向数据存储器(ram 指针)或程序 内存(ROM 指针)。 指针被假定为 ram 指针,除非 声明为 rom。

而在2.7.3 字符串常量中:

MPLAB C18 独立地址空间的一个重要结果 是指向程序存储器中数据的指针和指向程序存储器中数据的指针 数据存储器不兼容。 /---/ 因为他们指的是不同的 地址空间。 /---/ MPLAB C18 自动将所有字符串常量放入程序存储器中。 这种类型的字符串常量是“位于程序中的字符数组 内存”, (const rom char []).

对于第二个参数,类型转换为 const far rom char* 的目的也不清楚。这可能会导致堆栈损坏,因为远指针具有更大的大小(24 位)。所以,看起来应该改写为:

void CommTransmit (const char *CommVariable )
{
    if (!strcmppgm2ram(CommVariable, "test")) {
         USART_transmit('g');
    }
}

【讨论】:

    猜你喜欢
    • 2012-05-10
    • 1970-01-01
    • 2023-03-25
    • 2012-10-23
    • 2016-03-27
    • 2014-04-03
    • 1970-01-01
    相关资源
    最近更新 更多