有没有可能在没有标准库的情况下写入控制台?c / c++
is it possible write to console without stdlibs? c/c++
我正在手臂微处理器上编程,并试图通过UART使用打印语句进行调试。我不想添加stdlibs
只是为了调试。有没有办法打印到控制台没有stdio.h
/iostream.h
?我可以写自己的printf()
吗?
或者,我可以使用DMA控制器并直接写入UART。但是我想避免这种可能性。使用内置的测试函数"echo"或我知道我已经正确配置了UART。
简短的回答:是的,完全有可能同时执行你的两个解决方案。
如果你想支持所有的数据类型和格式,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()。
请注意,这是一个粗略的草图,我敢肯定代码中有一些错误-如果你想支持浮点数或"宽度",你将不得不在这方面多做一点工作…
(注意额外的参数—对于输出到FILE *
的文件指针,对于sprintf
,您可以传递缓冲区和缓冲区位置的结构,或者类似的东西)
"控制台"的概念在您正在使用的特定系统的上下文中没有多大意义。通常在嵌入式程序中没有控制台的真正概念。
你正在寻找的是一种从系统中获取数据的方法。如果您想使用UART,并且您没有使用像GNU/linux这样的高级操作系统,那么您将需要编写自己的I/O驱动程序。通常这意味着首先通过寄存器写配置UART来实现所需的butrate/奇偶校验/流量控制。对于任何类型的健壮IO,你都希望它是中断驱动的,所以你需要为tx和rx编写isr,它们利用循环缓冲区。
完成这些之后,您可以按照Mats的指示编写自己的printf。
由于通过嵌入式系统中的串行端口打印出信息会修改主程序的时序,因此我发现的最佳解决方案是发送2字节编码的小消息(有时1字节工作得很好),然后使用PC中的程序解码这些消息并提供必要的信息,其中可以包括统计数据和您可能需要的一切。通过这种方式,我只是在主程序中增加了一点开销,而让PC来完成处理消息的繁重工作。也许像这样:
-
1字节消息:bits 7:4 =模块ID, bits 3:0 =调试信息
-
2字节消息:bits 15:12 =模块ID, bits 11:8 =调试信息,bits 7:0 = data.
然后,在PC软件中,您必须声明一个表,其中包含映射到给定模块ID/调试信息对的消息,并使用它们在屏幕上打印。
也许它不像伪printf函数那样灵活,因为您需要在PC中解码一组固定的消息,但它不会增加太多的开销,正如我之前提到的。
希望有帮助。
费尔南多我发现在后台调试中,将字符排队到一个循环缓冲区中,然后由art传输寄存器上的轮询例程耗尽,这是我选择的方法。
排队例程基于字符、字符串和可变大小(十六进制或固定宽度的十进制)。高级缓冲区例程可以用保留字符指示溢出。
该方法对目标操作的开销/影响最小,可以(小心地)在中断例程中使用,并且该思想很容易转移,因此我忽略了我使用过的所有系统上的调试器。
- C++:将控制台输出存储在宏中更好吗
- 在while循环中输入带有std::cin的字符串后,控制台会输出大量胡言乱语
- SSH通过/sbin/SSH无法读取RSA密钥文件(从控制台运行)
- C++控制台应用程序阻止退出
- 如何修复此iFile以将.txt输出到控制台
- 为什么控制台要求输入,即使代码中没有输入
- 在Qt Creator中,如何在连接到正在运行的进程后查看控制台输出
- 控制台输出在 Qt5 中未正确显示
- C++出现控制台错误.我无法识别源代码的问题
- C++程序不会从 Windows 控制台运行
- 有人可以向我解释为什么控制台输出 0 吗?
- Visual Studio 2017 停止工作,并在打开后显示许多控制台窗口
- 如何从 Win32 C++ 应用程序输出到父控制台窗口?
- Win32 API 控制台光标在 WriteConsole 后不移动
- 如何获取控制台窗口的宽度?
- 如何在 Win32 C++控制台应用程序中调用 UWP 类库
- 如何从Windows控制台调用.exe(C++)以在不同的目录(或任何目录)中创建文件夹?
- 来自Visual Studio中控制台项目的exe文件?
- 为什么即使使用 for 循环遍历我的向量,它也没有输出到控制台?(C++)
- 使用 std::string_view 的子字符串控制台输出