我喜欢把任务分开。例如,当我为我的 Atmel AVR 制作一个循环缓冲区时,我将其全部写入 Code::Blocks 并使用常规 GCC 编译器而不是 AVR GCC 编译器对其进行编译,然后为它创建一个单元测试。我使用了一个特殊的头文件来提供我想要使用的正确数据类型(例如 uint8_t)。我在单元测试中发现了错误,修复了它们,然后将修复的代码转移到 AVR Studio 并集成它。之后,我使用编写的支持函数和 ISR 将缓冲区放入有用的代码中(即,从缓冲区弹出一个字节,将其推入 UART 数据输出寄存器,将字符串常量附加到缓冲区以用于 printf 函数等)。然后我使用 AVR 模拟器来确保我的 ISR 和函数被调用,并且正确的数据显示在寄存器中。
与 AVR Studio 相比,我更喜欢 Code::Blocks 的调试功能,所以我尽可能使用上述方法。当我不能时,我通常只处理硬件。例如,我有一个自动产生方波的计时器。我能做的最好的就是看到针头在模拟器中被旋转。在那之后,我只需要连接一个范围并确保。
我喜欢在调试问题时使用多层次的方法。例如,对于时钟,第一层是“在时钟引脚上放置一个探针,看看那里是否有信号”。如果没有,请探测 uC 上的引脚并寻找信号。然后,我在我的一个 UART 中编写了一个调试接口,我可以在其中查看特定的寄存器值并确保它们是它们应该是的。因此,如果它不起作用,下一步就是“调用寄存器值并确保它是正确的”。
每当您计划调试时,请尝试提前四个步骤左右。这里应该有+5V,但如果没有怎么办?在调试界面中写入一种切换引脚的方法,看看是否会改变它。如果这不起作用怎么办?做其他事情,等等等等。你会遇到“我不知道为什么这该死的东西不起作用!!!!” 但希望你能事先弄清楚原因。