【问题标题】:How to concatenate vars in c programmed pic?如何在 c 编程的 pic 中连接变量?
【发布时间】:2009-09-13 07:39:18
【问题描述】:

我在 hitech C 中编写了一张 16f84a 图片来驱动 hd44780 液晶显示器。到目前为止,我已经初始化了液晶显示器,并且可以将单个字符和字符串写入液晶显示器。现在我需要做这样的事情:

var = 250;
lcd_write_string("MyVar 有值:" + var);
所以 lcd 应该显示“MyVar has value: 250”

首先我应该如何连接一个 var 和一个字符串? 其次,变量 var 包含一个 8 位二进制数(十进制 0-255)。如果 var = 23; 8 位数字必须分成 2 以表示 ascii 中的 2 和 3,然后由 lcd 显示。我怎样才能做到这一点?看来我必须进行基数 10 转换或 if 树来拆分所有 2 位数字,然后显示在 lcd 中。有没有更简单的方法解决这个问题?

谢谢!

【问题讨论】:

  • 快速谷歌表明该 PIC 有许多编译器。答案将取决于您使用的是哪一个。

标签: c concatenation pic microchip hd44780


【解决方案1】:

你为什么不直接使用printf("%d", var)

var = 250;
char *static_msg = "MyVar has value:";
char msg[sizeof(static_msg) + 4];

sprintf(msg, "%s %d", static_msg, var);
lcd_write_string(msg);

【讨论】:

  • 谢谢大家,qrdl 的回答有效。但是,使用 printf 会加载外部库并需要更多内存。我让它像这样工作:lcd_write_num(var/10); lcd_write_num(var % 10);但它仅适用于 2 位数字。问题是 16f84a 的内存太少,使用这两种方法中的任何一种实际上都会使图片超载。我最终使用了 16f628a,现在使用 qrdl 的方法一切正常。非常感谢!
  • 找到了另一个关于数字操作而不是串联的选项。检查:mikroe.com/en/books/picbook/5_chapter.htm
【解决方案2】:

假设您的工具集不包含标准 C 库,或者您想自己弄清楚如何执行此操作,我将采用以下方法:

声明一个包含 LCD 可以显示的字符数的缓冲区。将您的固定字符串写入该缓冲区的开头。确定你的变量将有多少个字符(我在这里遗漏了一些数学,但我认为这是一个合理的练习)。使用该长度和固定字符串的长度,找出缓冲区中数字的位置。使用与以前相同的数学结构,将数字一个一个地写入该空间。 C 语言有一个技巧(标准要求),可以让您通过表达式'0' + digit 找出十进制数字的字符值。希望你能看到它是如何工作的。最后,以您的lcd_write_string 函数期望的方式终止缓冲区,并在缓冲区上调用它。

正如其他受访者所指出的,这基本上实现了标准库的printf 系列函数的一小部分。我认为弄清楚实现是值得的,即使您可以(并且应该!)在生产代码中使用该库。

因为这闻起来有点像家庭作业,所以我还没有进一步详细说明。如果您在特定方面需要帮助,我会查找问题的更新。

【讨论】:

    【解决方案3】:

    如果 C 编译器自带标准 C 库函数,那么sprintf 可以类似于printf 使用,以生成字符串。

    sprintf 可用于生成格式化字符串(如char*),大概可以发送到lcd_write_string 函数。

    【讨论】:

      【解决方案4】:

      sprintf() 的问题是您不知道在调用 sprintf() 之前需要分配多少字节。我通常使用下面的 ksprintf() 作为替代。

      typedef struct __kstring_t {
        size_t l, m;
        char *s;
      } kstring_t;
      
      int ksprintf(kstring_t *s, const char *fmt, ...)
      {
        va_list ap;
        int l;
        va_start(ap, fmt);
        l = vsnprintf(s->s + s->l, s->m - s->l, fmt, ap); // not working with glibc 2.0
        va_end(ap);
        if (l + 1 > s->m - s->l) {
          s->m = s->l + l + 2;
          kroundup32(s->m);
          s->s = (char*)realloc(s->s, s->m);
          va_start(ap, fmt);
          l = vsnprintf(s->s + s->l, s->m - s->l, fmt, ap);
        }
        va_end(ap);
        s->l += l;
        return l;
      }
      

      要使用它:

      kstring_t *str = calloc(1, sizeof(kstring_t));
      ksprintf(str, "%s, %d\n", aString, aInteger);
      ksprintf(str, "a second line: %s\n", aString2);
      free(str->s); free(s);
      

      ksprintf() 不适用于 glibc 2.0,因为 vsnprintf 不返回字符串中的字节数。您需要在分配中重复加倍内存。 Linux 手册页“man snprintf”也给出了一个例子。在您的系统上,您应该检查 vsnprintf() 的行为,它是 C99,而不是 C90。

      【讨论】:

        【解决方案5】:

        另一种方法是使用 lcd_write_string 作为函数指针并执行以下操作:

        printf(lcd_write_string,"MyVar has value: %d",var)
        

        这在 CCS Pic C 编译器上可以正常工作,如果 lcd_write_string 被声明为

        void lcd_write_string (char c);
        

        【讨论】:

        • 这只有在 CCS 编译器的情况下才有效。这是此编译器的一种解决方法,因为它无法将完整的常量字符串作为参数传递,因此它将函数定义为 char 并允许程序员克服此编译器缺陷,自动生成内部循环以打印它。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多