1

我正在尝试在我的 PIC18F87J11 上写入闪存,但我在理解汇编时遇到了问题。我的 PIC 的数据表只有程序集,我正在使用 C 编译器。我想知道是否有人可以帮我将这部分代码翻译成 C 语言。此代码可在此处找到,第 7.5 节。

MOVLW CODE_ADDR_UPPER ; Load TBLPTR with the base address
MOVWF TBLPTRU
MOVLW CODE_ADDR_HIGH
MOVWF TBLPTRH
MOVLW CODE_ADDR_LOW
MOVWF TBLPTRL
MOVLW DATA0
MOVWF TABLAT
TBLWT*+
MOVLW DATA1
MOVWF TABLAT
TBLWT*
PROGRAM_MEMORY
BSF EECON1, WPROG ; enable single word write
BSF EECON1, WREN ; enable write to memory
BCF INTCON, GIE ; disable interrupts
MOVLW H'55'
MOVWF EECON2 ; write H'55'
MOVLW H'AA'
MOVWF EECON2 ; write H'AA'
BSF EECON1, WR ; start program (CPU stall)
BSF INTCON, GIE ; re-enable interrupts
BCF EECON1, WPROG ; disable single word write
BCF EECON1, WREN ; disable write to memory

我知道这不是一个典型的问题,但如果我能得到一些帮助,那就太棒了。

4

1 回答 1

7

将其分解为几个步骤可能是最简单的。我要做的第一件事是在查看装配之前查看需要完成的总体概述。这可以在您的参考资料的 7.5.2 中找到。

重要的是要注意,当 WPROG 位被设置并且存储器位置必须已经被擦除时,执行字写入的能力被启用。以下是步骤:

  1. 将要写入的数据的地址装入表指针寄存器。
  2. 将 2 个字节写入保持寄存器并执行表写入。
  3. 将 WREN 位(EECON1<2>)置 1 以使能字节写入。
  4. 禁用中断。
  5. 将 H'55' 写入 EECON2。
  6. 将 H'AA' 写入 EECON2。
  7. 设置 WR 位。这将开始写周期。
  8. CPU 将在 Tiw 写入期间停止(参见参数 D133A)。
  9. 重新启用中断。

然后,为了清楚起见,我们可以将组件分解为给定的步骤。我还注释了每一行代码,以便您可以看到程序集在做什么(我永远不会在实际代码中这样做,因为它只会分散注意力)。

1. 用要写入的数据地址加载表指针。

MOVLW    CODE_ADDR_UPPER    ;Move the value CODE_ADDR_UPPER to the working register.
MOVWF    TBLPTRU            ;Move the working register to TBLPTRU.
MOVLW    CODE_ADDR_HIGH     ;Move the value CODE_ADDR_HIGH to the working register.
MOVWF    TBLPTRH            ;Move the working register to TBLPTRH
MOVLW    CODE_ADDR_LOW      ;Move the value CODE_ADDR_LOW to the working register.
MOVWF    TBLPTRL            ;Move the working register to TBLPTRL.

2. 将 2 个字节写入保持寄存器并执行表写入。

MOVLW    DATA0     ;Move DATA0 to the working register.
MOVWF    TABLAT    ;Move the working register to TABLAT.
TBLWT*+            ;Write the data stored in TABLAT to the position 
                   ;defined in TBLPTR and then, increment TBLPTR.
MOVLW    DATA1     ;Move DATA1 to the working register.
MOVWF    TABLAT    ;Move the working register to TABLAT.
TBLWT*             ;Write the data stored in TABLAT to the position defined in TBLPTR.

其余步骤包含在 PROGRAM_MEMORY 部分中。

PROGRAM_MEMORY    ; This is just a label.
    ;STEP 3
    BSF    EECON1, WPROG    ;Set the WPROG bit in the EECON1 register.
    BSF    EECON1, WREN     ;Set the WREN bit in the EECON1 register.

    ;STEP 4
    BCF    INTCON, GIE      ;Clear the GIE bit in the INTCON register.

    ;STEP 5
    MOVLW    H'55'          ;Move 0x55 to the working register
    MOVWF    EECON2         ;Write 0x55 to EECON2 register.

    ;STEP 6
    MOVLW    H'AA'          ;Move 0xAA to the working register.
    MOVWF    EECON2         ;Write 0xAA to the EECON2 register.

    ;STEP 7 AND 8
    BSF    EECON1, WR       ;Set the WR bit in the EECON1 register.

    ;STEP 9
    BSF    INTCON, GIE      ;Set the GIE bit in the INTCON register.
    BCF    EECON1, WPROG    ;Clear the WPROG bit in the EECON1 register.
    BCF    EECON1, WREN     ;Clear the WREN bit in the EECON1 register. 

由于我既没有 PIC 编译器也没有 IDE,我知道下面的 C 代码并不完美(请随意编辑)。但是,这应该让您很好地了解如何基于汇编示例构建 C 代码。

static void FlashWriteWord(unsigned int store_addr, unsigned char * data)
{
    /* 1. Load Table Pointer with the address of the data to be written. */
    TBLPTR = store_addr;

    /* 2. Write the 2 bytes into the holding registers and perform a table write. */
    TABLAT = data;
    _asm
       TBLWTPOSTINC    /* Table writes are performed as inline assembly functions. */
    _endasm

    data++;
    _asm
        TBLWT          /* Table writes are performed as inline assembly functions. */
    _endasm

    /* 3. Set the write enable bit to enable byte writes. */
    EECON1bits.WPROG = 1;
    EECON1bits.WREN = 1;

    /* 4. Disable interrupts. */
    INTCONbits.GIE = 0;

    /* 5. Write H'55' to EECON2. */
    EECON2 = 0x55;

    /* 6. Write H'AA' to EECON2. */
    EECON2 = 0xAA;

    /* 7. Set the WR bit.  This will begin the write cycle. */
    /* 8. The CPU will stall for the duration of the write for Tiw (see Parameter D133A). */
    EECON1bits.WR = 1;

    /* 9. Re-enable interrupts. */
    INTCONbits.GIE = 1;
    EECON1bits.WPROG = 0;
    EECON1bits.WREN = 0;
}

希望有帮助!

于 2013-05-22T23:57:46.393 回答