C 如何使用内联汇编写入闪存?
我正在使用MPLAB C18编译器,并尝试使用内联汇编将一些值保存到闪存中,内联汇编是C和汇编代码的组合C 如何使用内联汇编写入闪存?,c,assembly,embedded,microcontroller,pic,C,Assembly,Embedded,Microcontroller,Pic,我正在使用MPLAB C18编译器,并尝试使用内联汇编将一些值保存到闪存中,内联汇编是C和汇编代码的组合 _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
_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;
看起来我可以正确地写入和读取闪存,但只要我关闭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
_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
_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
_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
_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);
从闪存存储器读取
_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一起使用。我不确定
ACCESS
和BANKED
之间的区别,因为我怀疑它们可能与问题有关 看起来您已经找到了解决方案:问题在于如何使用银行
_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;
EECON2
等是驻留在气缸组15中的特殊功能寄存器(SFR)。访问它们的最快方法是使用access
,它在计算地址时忽略银行寄存器
_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;
在您使用的汇编语言中,ACCESS
表示0,BANKED
表示1。movwf
指令中需要这些值之一。数据表在其示例中使用实际数字,而不是符号常量
_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;
数据表还解释了RAM的存储方式
_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;
基本上,有一个as寄存器,它保存4位,表示组0到15。这个数字在给指令的8位数字前加上前缀,给出全部12位。这允许更快的执行。要存储在正确的位置,需要先将此寄存器设置为正确的银行
_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;
其中两个组0和15也映射到通用寄存器和特殊功能寄存器。因为这些是最常用的,所以快速获取它们的方法是在指令中使用一个标志,在计算地址时忽略银行寄存器,直接转到所需的GPR或SFR
_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
_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;