使用C18库的PIC18延迟功能的长时延

时间:2013-06-30 14:10:29

标签: c delay pic18 c18

我使用的是F18 = 10MHz的PIC18。因此,如果我使用Delay10KTCYx(250),我得到10,000 x 250 x 4 x(1 / 10e6)= 1秒。

如何使用C18中的延迟功能进行很长时间的延迟,比如20秒?我在考虑使用20行Delay10KTCYx(250)。还有另一种更有效和优雅的方式吗?

提前致谢!

2 个答案:

答案 0 :(得分:2)

强烈建议您避免使用内置延迟功能,例如Delay10KTCYx()

为什么你会问?

这些延迟函数非常不准确,它们可能会导致您的代码以意想不到的方式进行编译。这是一个使用Delay10KTCYx()函数可能导致问题的示例。

我们假设您有一个PIC18微处理器,它只有两个硬件定时器中断。 (通常他们有更多,但只是说只有两个)。

现在让我们假设您手动将第一个硬件定时器中断设置为每秒闪烁一次,以驱动心跳监视器LED。我们假设您设置了第二个硬件定时器中断,每隔50毫秒就会中断一次,因为您希望在50毫秒内完成某种数字或模拟读取。

现在,最后,让我们说在您的主程序中,您希望延迟100,000个时钟周期。所以你在主程序中调用了Delay10KTCYx(10)。你认为发生了什么? PIC18如何神奇地计算100,000个时钟周期?

将会发生以下两件事之一。它可能会劫持"您的其他硬件定时器中断之一,可以获得100,000个时钟周期。这会导致您的心跳传感器在1秒内没有计时,或者导致您的数字或模拟读数在每50毫秒以外的某个时间发生。

或者,延迟函数只调用一堆Nop()并声称1 Nop()= 1个时钟周期。没有考虑的是"间接费用"在Delay10KTCYx(10)函数内。它必须递增计数器以跟踪事物,并且确定需要超过1个时钟周期来递增计时器。由于Delay10KTCYx(10)在其周围循环,因此无法为您提供100,000个时钟周期。根据很多因素,您可能会比预期更多或更少地使用时钟周期。

延迟10KTCYx(10)只应在需要"近似"多少时间。如果您已经将硬件定时器中断用于其他目的,则不应使用预先设定的延迟功能。当使用Delay10KTCYx(10)进行非常长的延迟时,编译器甚至可能无法成功编译。

我强烈建议您设置一个计时器中断,以便以已知的间隔中断硬件。比如说50,000个时钟周期。然后,每次硬件中断时,在用于该定时器中断的ISR代码中,递增计数器并再次将定时器重置为0个周期。当足够的50,000个时钟周期到期等于20秒时(或者换句话说,在您的示例中,200个定时器中断,每个中断50,000个周期),重置您的计数器。基本上我的建议是你应该总是手动处理PIC中的时间而不是依赖于预先设置的延迟功能 - 而是构建自己的延迟功能,这些功能集成到芯片的硬件定时器中。是的,这将是额外的工作 - "但为什么我不能使用这个简单而漂亮的内置延迟功能,为什么他们甚至会把它放在那里如果它会破坏我的计划吗?" - 但这应该成为第二天性。就像你应该在启动时手动配置PIC18中的每个单一寄存器一样,无论你是否使用它,都可以防止意外事件的发生。

您将获得更准确的时序 - 以及PIC18中更可预测的行为方式。使用预先设定的延迟功能是灾难的一个方法......它可能有用......它可能适用于多个项目......但是你的代码迟早会在你身上发现所有的错误并且你会感到疑惑为什么我保证罪魁祸首将是预先设定的延迟功能。

答案 1 :(得分:0)

要创建很长时间,请使用内部计时器。这有助于避免应用程序中的阻塞,您可以检查运行时间。有关如何设置定时器及其中断的信息,请参考PIC数据手册。

如果你想要一个非常高精度的1S时间,我建议你考虑一个外部RTC设备或内部RTC,如果micro有一个。