MPLAB XC8 编译器 - 反汇编视图中的指令太多 PIC10F200

问题描述 投票:0回答:1

我正在尝试编译此代码以生成 PWM 信号 15us 高电平和 9us 低电平。

#include <xc.h>
void g()
{
    for(char val=0; val<20; val++)
    {
        GPIO = 0xFF;
        NOP(); NOP(); NOP(); NOP(); NOP();
        NOP(); NOP(); NOP(); NOP(); NOP();
        NOP(); NOP(); NOP(); NOP();

        // Write all GPIO pins LOW
        GPIO = 0;
        NOP(); NOP(); NOP();
    }
}

void main(void) {

    // Set all pins at output
    TRIS = 0x00;
    GPIO = 0;

    while(1) {
        g();        
    }
}

问题在于FOR循环的返回需要太多指令。我原以为要少拿一点。在这种情况下,仅使用 3 个

NOP();
函数,仍然有 15 个刻度。

CLRF GPIO  // GPIO = 0;
NOP
NOP
NOP
MOVLW 0x1
MOVWF wtemp1
MOVF wtemp1, W
ADDWF __pcstackBANK0, F
MOVLW 0x14
SUBWF __pcstackBANK0, W
BTFSC STATUS, 0x0
RETLW 0x0
GOTO 0x4  // Return to beginning of loop

编译器XC8:

  • -xassembler-with-cpp -mwarn=-3 -Wa,-a -O2 -fasmfile -maddrqual=忽略

我应该怎么做才能压缩操作码?和mplab有关系吗?

p.s 我无法使用

-O3
标志,因为它不包含在我的许可证中。

assembly disassembly pic mplab
1个回答
0
投票

我没有你的工具链,所以我无法进行周期计数,但这段代码应该为你提供一个微调版本的基础,该版本可以可靠地生成 15us 高、9us 低。我还提供了示例变量延迟,如果您打算在某个阶段执行 PWM,我认为这些延迟应该是 PIC 友好的机器代码。

@KonstantinMurugov 建议的第一个也是最基本的技巧是将内部

for
循环转为倒计时(PIC 以 DECFSZ 形式提供硬件支持)。我已经把它变成了 while 循环。

然后下一个技巧是将短延迟移到循环的中间,您可以在其中精确控制它,并调整较长高延迟的填充,直到获得两者所需的时间。我最初的猜测是基于有关代码生成和开销的一些假设,因此您可能需要对其进行一些调整才能使时间常数准确。同样出于测试目的,将

val
设置为 1,以便系统误差出现在前几个周期中。然后用 2 和 3 重新测试,以确保它在每个嵌套循环中生成正确的波形。为了使其完全正确,您可能必须减少最内层循环中的
NOP()
计数并将它们添加到其他地方。

#include <xc.h>

void g()
{
   char val = 20; 
   // for fine tuning set this to 1 so that the loop exits each time (then recheck with val = 2,3)
   do
   {
       NOP(); NOP(); NOP(); NOP(); 
       GPIO = 0;
       NOP(); NOP(); NOP(); NOP();
       GPIO = 0xff;
       NOP(); NOP(); NOP(); NOP(); 
   } while (val--);  
   // this form of countdown loop is friendly to PIC DECFSZ instruction  
}

// since `PWM` was mentioned in the original question here are two primitives.
// call overheads are disastrous so allow maximum inlining for speed 
// in some ways cycle counting is easier in assembler where you can have
// precise control of the instructions inside the various loops.

void delay(char x)
{   // delay by individual NOPs (a variant on Duff's device)
    // it should be PIC friendly but I don't have the toolchain to check.
    switch (x)
    {
     case 7: NOP();
     case 6: NOP();
     case 5: NOP();
     case 4: NOP();
     case 3: NOP();
     case 2: NOP();
     case 1: NOP();
     case 0:;
     default:;
    }
}

void delay2(char x)
{   // delay by countdown loop 2 cycles at a time
    while (x--)
       ;
}

void main(void) {

  // Set all pins at output
  TRIS = 0x00;
  GPIO = 0xff;
  NOP(); NOP(); NOP(); NOP(); // so that first cycle is correct length

  while (1) {
    g();
  }
  // NB you may have to tweak it again if while(1) becomes a conditional test
}

您必须在模拟器中运行它,然后调整 NOP 的确切数量以获得您想要的波形。不过应该不会太远。

© www.soinside.com 2019 - 2024. All rights reserved.