Arduino/Attiny85:ISR和港口管理延迟

Arduino/Attiny85:ISR和港口管理延迟,arduino,interrupt,avr,isr,attiny,Arduino,Interrupt,Avr,Isr,Attiny,我试图在一个引脚上设置一个与另一个输出相关的反向输出,该输出播放音调(),但在8MHz时钟下有35us或在1MHz时钟下有158us的延迟。似乎存在固定的16us+142时钟周期延迟,因为延迟与时钟频率不成反比。它们非常非常长!为什么? 代码如下: /*根据ATTINY85: 1:I/O5 PB5 A0 RS 2:I/O3 PB3 A3-盖革倒置耳机输出 3:I/O4 PB4 A2-盖革耳机输出 4:GND 5:I/O0 PB0 MOSI SDA-电池测试/盖革发光二极管熄灭 6:I/O1 PB

我试图在一个引脚上设置一个与另一个输出相关的反向输出,该输出播放
音调()
,但在8MHz时钟下有35us或在1MHz时钟下有158us的延迟。似乎存在固定的16us+142时钟周期延迟,因为延迟与时钟频率不成反比。它们非常非常长!为什么?

代码如下:

/*根据ATTINY85:
1:I/O5 PB5 A0 RS
2:I/O3 PB3 A3-盖革倒置耳机输出
3:I/O4 PB4 A2-盖革耳机输出
4:GND
5:I/O0 PB0 MOSI SDA-电池测试/盖革发光二极管熄灭
6:I/O1 PB1味噌
7:I/O2 PB2 A1 SCLK SCL INT0-盖革探针输入(通过NPN晶体管)
8:Vcc
*/
#包括
字节状态;
易失字节P;
int B;
int Bo;
字节LED=0;
无符号长t=0;
空心颗粒()
{
P=1;
}
行业特殊风险(PCINT0)
{

如果(!(PINB&(1在执行ISR代码之前有许多延迟

首先是硬件延迟。这些延迟记录在数据表中,包括通知和锁定输入已更改、完成当前指令、将指令指针推到堆栈上以及执行跳转到ISR的时间。

接下来是软件延迟。首先是从中断向量到IST地址的跳转,然后编译器在ISR的开头放入一系列指令,以确保所有寄存器都已保存,并且具有正确的预期值。这称为“前导”

对于硬件延迟,您可以做的不多,但您可以显著减少软件延迟-特别是对于像您这样的非常简单的ISR。一种方法是制作一个“裸”ISR,只保存您更改的寄存器。对于上面的代码,您可能只需更改一个寄存器即可

我认为也可以不使用任何数据寄存器,通过使用写入PIN寄存器翻转位的技巧来实现ISR功能。

你应该能够通过谷歌搜索找到更多关于这一切的信息,如果你需要这些方面的具体指导,也可以在这里报告

另一种方法-使用内置硬件反向输出

该芯片上的定时器1有一个内置的反相输出,它将自动输出您正在寻找的反相信号,并且在反相和非反相输出之间的延迟将远小于1个周期(假设您没有故意在转换之间添加
死区时间


这需要对定时器寄存器进行编程,以启用反转输出,并且反转输出仅在特定引脚上可用-但这通常不是问题。

谢谢您的回答。没关系,但我发现延迟为16us+142个时钟周期,或者158us@1MHz时钟…那是一个很长的延迟!是不是每一个tim的延迟都是常数e?还要记住,arduino库经常关闭全局中断。那么您的电路是什么样子的?您是否考虑过在软件中使用硬件生成的反向输出?硬件直接输出和反向输出之间的差异小于1个周期。是的,延迟是恒定的。音调()切换管脚;管脚更改触发中断;它运行if管脚B4…(然后)端口B3…,或者端口B3…和B3在16us+142个时钟周期内切换。您是否不想使用硬件反向输出而不是在软件中进行输出?在以前的设备中,我使用CD40106桥接驱动压电蜂鸣器。这一次,我认为通过软件进行输出会非常简单。我认为另一个输出可以uld已在几个时钟周期内切换…1)在什么和什么之间延迟?2)您如何知道有延迟?3)为什么要混合基于arduino的中断处理(attachInterrupt)和本机ISR?