2

我正在使用带有PIC18F87J11的 MPLAB C18 编译器,并且我正在尝试使用内联汇编将一些值保存到闪存中,这是 C 和汇编代码的组合。

看起来我可以正确地写入和读取闪存,但是一旦我重启我的 PIC,然后尝试读取我之前从特定地址保存的内容,我就不会得到相同的值。我正在保存0x09地址0xB22A。就像我说的那样,如果我保存该值然后立即读取它,一切都会正确显示,但是在重置 PIC 时我得到了0x00.

我不是永久保存到闪存还是这里真正发生了什么?

这是我的代码:

擦除内存行

_asm 
MOVLW 0x00
MOVWF TBLPTRU,BANKED
MOVLW 0xB2
MOVWF TBLPTRH,BANKED
MOVLW 0x2A
MOVWF TBLPTRL,BANKED  
_endasm
EECON1bits.FREE = 1; 
INTCONbits.GIE = 0;

_asm 
MOVLW 0x55
MOVWF EECON2,BANKED
MOVLW 0xAA
MOVWF EECON2,BANKED
_endasm
EECON1bits.WR = 1;
INTCONbits.GIE = 1;

写入闪存

_asm 
MOVLW    0x00
MOVWF    TBLPTRU,BANKED
MOVLW    0xB2
MOVWF    TBLPTRH,BANKED
MOVLW    0x2A
MOVWF    TBLPTRL,BANKED
MOVLW    0x09
MOVWF    TABLAT,BANKED
TBLWTPOSTINC
MOVLW    0x09
MOVWF    TABLAT,BANKED
TBLWT
_endasm

EECON1bits.WPROG = 1;
EECON1bits.WREN = 1;
INTCONbits.GIE = 0; 
_asm 
MOVLW 0x55
MOVWF EECON2,BANKED  
MOVLW 0xAA
MOVWF EECON2,BANKED 
 _endasm
EECON1bits.WR = 1;
INTCONbits.GIE = 1;
EECON1bits.WPROG = 0; 
EECON1bits.WREN = 0;

从闪存读取

_asm  
 MOVLW 0x00
 MOVWF TBLPTRU,BANKED  
 MOVLW 0xB2 
 MOVWF TBLPTRH,BANKED
 MOVLW 0x2A 
 MOVWF TBLPTRL,BANKED 
READ_WORD: 
 TBLRDPOSTINC  
 MOVF TABLAT, 0,BANKED 
 MOVWF WORD_EVEN,ACCESS
 TBLRDPOSTINC  
 MOVF TABLAT, 0,BANKED
 MOVWF WORD_ODD,ACCESS
 _endasm

printf("\r\n");
PrintChar(WORD_EVEN);
printf("\r\n");
PrintChar(WORD_ODD);

原始代码可以在第 6 章的数据表中找到,但请记住,我必须对其进行一些修改才能与 C 一起使用。我不确定它们之间有什么区别ACCESSBANKED因为我怀疑它们可能与问题。

4

1 回答 1

2

看起来您已经找到了解决方案:问题在于使用BANKED.

EECON2等是驻留在 bank 15 中的特殊功能寄存器 (SFR)。访问它们的最快方法是使用ACCESS,它在计算地址时忽略了 bank 寄存器。

它看起来像您使用的汇编语言,ACCESS表示 0 和表示 1。指令BANKED中需要这些值之一。movwf数据表在其示例中使用实际数字,而不是符号常量。

数据表还解释了 RAM 的存储方式。

基本上,有一个寄存器保存 4 位,代表银行 0 到 15。这个数字被添加到给指令的 8 位数字之前,以提供所有 12 位。这允许更快的执行。要存储在正确的位置,您需要先将此寄存器设置为正确的库。

其中两个库,0 和 15,也映射到通用寄存器和特殊功能寄存器。由于这些是最常使用的,因此获得它们的快速方法是在指令中使用一个标志来在计算地址时忽略银行寄存器,并直接转到您想要的 GPR 或 SFR。

您的问题是您将标志设置为使用与寄存器所在位置不同的内存库。

于 2013-08-13T04:04:42.117 回答