我希望在上升沿信号输入后制作一个非常短的脉冲。
这里的难点在于我想控制(达到高分辨率)脉冲前的延迟时间和脉冲持续时间。我可以通过自己将nops串联起来,硬编码延迟来轻松控制这一点,但是我不知道如何以一定的任意延迟来执行它,具有相同的准确度。
经过很多头痛追逐计时器,然后最终意识到我最终受到中断例程进入/退出时间的限制,我现在正试图通过nops来控制我的延迟。
我假设这个C开关语句将是我想要的(编译之后,希望它会变得高效并且只是将程序计数器更改为正确的位置),但它会产生一些非常奇怪的行为......
switch(delayTime){
case 10:
__asm__ __volatile__("nop");
case 9:
__asm__ __volatile__("nop");
case 8:
__asm__ __volatile__("nop");
case 7:
__asm__ __volatile__("nop");
case 6:
__asm__ __volatile__("nop");
case 5:
__asm__ __volatile__("nop");
case 4:
__asm__ __volatile__("nop");
case 3:
__asm__ __volatile__("nop");
case 2:
__asm__ __volatile__("nop");
case 1:
__asm__ __volatile__("nop");
}
PORTD = 0x10;
...
理想情况下,我想基本上运行一些编译成这个的代码:(这是C和汇编的一些奇怪的伪代码,仍然不知道如何在汇编中做一些)
0x005 Reg1 = 0xFF-val1 %(where somehow 0xFF is known? / found out?)
0x006 Reg2 =0x1FF-val2
0x007 IJMP Reg1
0x008 NOP
0x009 NOP
0x00A NOP
...
0x0FF MOV 0x40, PORTD % assign the value 0x40 to the static variable "PORTD"
0x100 IJMP Reg2
0x101 NOP
0x102 NOP
0x103 NOP
0x104 NOP
...
0x1FF MOV 0x00, PORTD % assign the value 0x00 to the static variable "PORTD"
我总体上不确定如何在运行时/运行期间找到代码的内存位置,这样该程序的“0xFF”和“0x1FF”方面实际上并不是那么糟糕(看起来它是超级危险的只是,得到代码的汇编,然后硬编码...我宁愿不这样做)。另外,虽然很容易用200多个nops充满它,但是如何让IJMP cmd以我想要的方式运行? (老实说,我甚至不知道这是否是我想要的命令)..
我想我一般都在寻找一些汇编命令(我似乎无法找到),它允许我“将N添加到程序计数器”,我可以确保该命令在汇编中运行在它之前至少有N + 1个装配命令,硬编码。
作为旁注,所有这些都是在一个中断例程中执行的,所以我对使用PC感觉并不是那么糟糕...而且,我知道对于多达500次操作来说有点阻塞,但是对于手头的任务来说,时间比作为一个例程的阻塞程度更重要。
答案 0 :(得分:1)
我不熟悉AVR指令集,但一般的想法是使用CALL
指令将程序计数器(PC)放在堆栈上。然后使用POP
将PC移动到Z寄存器。然后你可以ADD
向Z寄存器输入一些数字,并使用IJMP
跳转到结果地址。
沿着这些方向做点什么
delay: call delay1 ; push the PC onto the stack
delay1: pop r30 ; pop the PC into the Z registers
pop r31
add r30,r0 ; add some amount to the PC value
addc r31,r1
ijmp ; use IJMP to jump to the resulting address
nop
nop
nop
...
随机想法:
delay1
起,添加到Z的值必须相对于call
将delay1
的地址压入堆栈。换一种说法,
需要添加的最小金额是6,因为那是
从delay1
到第一个nop
。ijmp
。你应该增加r1 / r0(减少数量
nops)相应的。就像我说的那样,我不是AVR指令集的专家,所以你应该把它作为一般性的建议,并准备花一些时间来制定细节。祝你好运!