是否可以在没有stdlibs的情况下写入控制台? C / C ++

时间:2013-05-08 21:33:59

标签: c++ c microcontroller uart

我正在使用arm微处理器进行编程,并尝试通过UART使用print语句进行调试。我不想仅为调试添加stdlibs。有没有办法在没有stdio.h / iostream.h的情况下打印到控制台?我可以自己编写printf()吗?

或者我可以使用DMA控制器直接写入UART。但是,我想避免这是可能的。使用内置的测试功能“echo”或 “远程环回”我知道我已正确配置UART。

4 个答案:

答案 0 :(得分:9)

简短回答:是的,完全可以同时完成两种解决方案。

如果要支持所有数据类型和格式,printf函数非常复杂。但是编写可以在几个不同的基础上输出字符串或整数的东西并不难(大多数人只需要十进制和十六进制,但是一旦你有十进制和十六进制,八进制可能只会增加另外3-4行代码)。

通常,printf的写法如下:

 int printf(const char *fmt, ...)
 {
     int ret;
     va_list args; 

     va_start(args, fmt)
     ret = do_xprintf(outputfunc, NULL, fmt, args); 
     va_end(args);
     return ret;
}

然后do_xprintf()为所有变体(printf,sprintf,fprintf等)做了所有努力工作

int do_xprintf(void (*outputfunc)(void *extra, char c), void *extra, const char *fmt, va_list args)
{
    char *ptr = fmt;
    while(1)
    {
       char c = *ptr++;

       if (c == '%')
       {
            c = *ptr++; // Get next character from format string. 
            switch(c)
            {
               case 's': 
                  char *str = va_arg(args, const char *);
                  while(*str)
                  {
                      count++;
                      outputfunc(extra, *str);
                      str++;
                  }
                  break; 
               case 'x': 
                  base = 16;
                  goto output_number;

               case 'd':
                  base = 10;
         output_number:
                  int i = va_arg(args, int);
                  // magical code to output 'i' in 'base'. 
                  break;

               default:
                  count++;
                  outputfunc(extra, c);
                  break;
         }
         else
             count++;
             outputfunc(extra, c);
     }
     return count;
 }                

现在,您需要做的就是填写上面代码的几个部分并编写一个输出到串口的outputfunc()。

请注意,这是粗略的草图,我确信代码中有一些错误 - 如果你想支持浮点或“宽度”,你将需要更多地工作...... < / p>

(关于额外参数的注意事项 - 输出到FILE *将成为文件指针,对于sprintf,您可以传递缓冲区的结构和缓冲区中的位置,或类似的东西)

答案 1 :(得分:2)

&#34; console&#34;的概念在您使用的特定系统的上下文之外没有太多意义。通常在嵌入式程序中没有控制台的真实概念。

您正在寻找的是一种从系统中获取数据的方法。如果您想使用UART,并且您没有使用像GNU / linux这样的高级操作系统,则需要编写自己的I / O驱动程序。通常,这意味着首先通过寄存器写操作将UART配置为所需的分配/奇偶校验/流控制。对于任何类型的强大IO,您都希望它是中断驱动的,因此您需要为使用循环缓冲区的tx和rx编写ISR。

完成后,您可以编写自己的printf,如Mats所示。

答案 2 :(得分:1)

我找到了后台调试,将字符排入循环缓冲区,然后通过uart传输寄存器上的轮询程序排出,这是我选择的方法。

排队例程基于字符,字符串和可变大小(十六进制或固定宽度十进制)。豪华缓冲程序可以指示溢出的保留字符。

该方法对目标操作的开销/影响最小,可以在中断例程中使用(小心),并且这个想法很容易转移,所以我忽略了我使用过的所有系统上的调试器。

答案 3 :(得分:1)

由于通过嵌入式系统中的串口打印信息会修改主程序的时序,我发现的最佳解决方案是发送一个以2个字节编码的小消息(有时1个字节工作正常),然后使用PC中的程序解码这些消息并提供必要的信息,其中包括统计数据和您可能需要的所有信息。 这样,我只是在主程序中添加了一点开销,让PC完成了处理消息的艰苦工作。 也许是这样的:

  • 1字节消息:位7:4 =模块ID,位3:0 =调试信息。

  • 2字节消息:位15:12 =模块ID,位11:8 =调试信息,位7:0 =数据。

然后,在PC软件中,您必须声明一个表格,其中包含映射到给定模块ID /调试信息对的消息,并使用它们在屏幕上打印。

也许它不像伪printf函数那么灵活,因为你需要一组固定的消息来解码,但它并没有增加太多的开销,正如我之前提到的那样。

希望它有所帮助。

费尔南多