Answers:
模块化是您的朋友。编写主循环以通过调用函数来完成其工作,这些函数会调用函数...,直到您的函数达到简单的级别为止。从主循环开始,再向下一级,使存根函数起作用;要么为空:
function foo(){
;
}
还是假的:
function read_temperature(){
return(95);
}
,它什么也没做,只是返回呼叫级别所需的任何值,该呼叫级别才能继续。当该级别起作用时,向下移动一个级别并开始填写同样调用存根函数的简单代码。逐渐取消对某个函数的存根,直到您拥有一个可以运行的应用程序。
要调试返回错误值的函数,或者创建一个不受其他应用程序影响的函数,您可以构建脚手架-一个简单的草图,仅向函数提供一些示例值,并在函数内打印出参数值以及一些中间值,直到您对函数的哪个部分失败有一定了解。我什至做了伪造的功能,它们提示我在终端上返回一个值。(显然,只有在系统可以忍受人类相对冰川速度的情况下,这项技术才能起作用!脚手架的另一种用途。)
存根可以很好地代表与硬件接口的功能,从而使您可以在进入数据表,时序问题和其他细节(如没有零件!)之前开始启动应用程序。你的进步。
说到时序问题,在程序的特定点切换输出引脚,例如进入和退出ISR,会在Arduino引脚上产生方波,其频率或占空比可以使您深入了解内部时序您的程序。直接端口I / O形式,例如
PORTC ^= 0x01;
,会使通话时间失真小于通话digitalWrite()
。如果您有便携式“示波器”或具有测量频率和/或占空比能力的DMM之一,则很有用。
同样,您可以使用模拟输出引脚从程序内部向仪表输出一个数值,而不会过多地干扰时序或使用串行I / O功能使代码the肿。也可以在此处使用直接I / O形式。
3其他技术:
通过在每个阶段进行缓慢的测试来建立程序的功能,这样您一次只能面对一小部分错误。
围绕命令解释器构建程序,以便您可以像此处一样一次处理各节 。
在重要时间跳出并使用示波器。
Visual Studio 的Visual Micro插件提供了Arduino Debug。包括源代码的跟踪和中断,还允许“监视”和/或修改表达式和变量。
从ARM之类的豪华工具或其他平台(带有适当工具的AVR,PIC)来看,我同意Arduino调试功能太有限。但这是入门级的入门工具。
Serial.print()是您的朋友。对于我的特定项目(学院),我没有连接任何LED,所以它是Serial.print()。如果我想测试代码是否在语句中正常运行,通常会放置Serial.print(“ A”);。,然后转到B,C等。我将调试字母与预期的效果进行了比较。
除此之外,没有断点或代码步进。Arduino只不过是一块带有AVR atmega芯片,一个引导加载程序+开发环境和大量软件库的电路板。不幸的是,使用引导加载程序会限制调试功能。
比直接使用serial.print更好,请使用宏。例:
#ifdef TRACE1
#define trace1(s) serial.print(s)
#define traceln1(s) serial.println(s)
#else
#define trace1(s)
#define traceln1(s)
#endif
像这样使用它:
function doIt(param1, param2) {
trace1("->doIt("); trace1("param1: "); trace1(param1); trace1(" param2: "); trace1(param2); traceln1(")");
...
traceln1("<-doIt");
}
您可能具有(#ifdef TRACE2 ...)
更多详细信息的不同跟踪级别。
您可能会使用“ F”宏(trace1(F("param1"));)
。“ F”宏防止字符串使用极有限数量的SRAM。
闪烁LED,在串行端口上打印内容,并一次编写和调试一小段代码,有时只有几行。
有时您可以模块化。例如,如果在C语言中,您可以开发和测试不与主机,其他处理器上的硬件接触的计算功能,则可以在测试台上包装该功能以提供输入并检查输出等。
另一种类似的方法可能是使用一个指令集模拟器(如果您可以使用它)(如果没有,这是一个非常有教育意义的项目,在您完成其中的一些实验后,您可以在一个周末或两个星期内尝试一次)。如果有人拥有处理器的Verilog或VHDL克隆(例如OpenCore),甚至更好,则可以尝试GHDL,Verilator或Icarus Verilog。它可能足够接近以包含您感兴趣的外围设备,并且您可以了解内部发生的信号电平。
当然,它可能不是一个完美的克隆,但可能已经足够了。Verilator使得使用C / C ++创建外围设备真的非常容易,因此您可以模拟连接了AVR设备的任何内容。
UART输出和闪烁的LED和/或闪烁的GPIO线,并使用示波器或电压表。不发疯的关键是编写和调试小部分代码。我最好一次写10行,并执行100次测试,而不是1000行,然后尝试一次调试它们。特别是当您找到大多数数据表和程序员时,有关硬件的参考手册并不总是正确的。总是需要一些骇客行为。