PIC16F18877汇编读写数据EEPROM失败,求技术指导
PIC16F18877数据EEPROM读写故障排查与修正
问题概述
首次通过汇编实现PIC16F18877的数据EEPROM读写,目标流程为:读取地址0xF001的数据→写入0x25→读回验证。但实际测试中:
- 初始读取返回
0x0(调试窗口显示EEPROM全为0xFF) - 写入后读回仍为
0x0(已提前清空寄存器排除旧值干扰) - 添加读取等待循环后触发无限循环
非工作代码
主操作代码
MOVLW 01h MOVWF eeprom_addr_low MOVLW 0F0h MOVWF eeprom_addr_high ;READ EEPROM BANKSEL NVMADRL MOVLW eeprom_addr_low MOVWF NVMADRL MOVLW eeprom_addr_high MOVWF NVMADRH BSF NVMCON1,6 ;NVMREGS BSF NVMCON1,0 ;RD MOVF NVMDATL,W MOVWF eeprom_data_low MOVF NVMDATH,W MOVWF eeprom_data_high ;WRITE EEPROM BANKSEL NVMADRH MOVF eeprom_addr_high,W MOVWF NVMADRH MOVF eeprom_addr_low,W MOVWF NVMADRL BSF NVMCON1,2 ;WREN BSF NVMCON1,6 ;LWL0 writeLoop: MOVLW 025h MOVWF NVMDATL MOVLW 00h ;0x00 MOVWF NVMDATH MOVLW eeprom_addr_low ;01h MOVWF NVMADRL MOVLW eeprom_addr_high ;0F0h MOVWF NVMADRH BSF NVMCON1,2 ;WREN unlockSeq: BCF INTCON,7 ;GIE MOVLW 055h MOVWF NVMCON2 MOVLW 0AAh MOVWF NVMCON2 BSF NVMCON1,1 ;WR BSF INTCON,7 ;GIE BCF NVMCON1,2 ;WREN readBack: MOVLW 00h MOVWF NVMDATL ;Just clearing it to confirm if the readback is working for debugging purposes MOVWF NVMDATH MOVLW eeprom_addr_low MOVWF NVMADRL MOVLW eeprom_addr_high MOVWF NVMADRH BSF NVMCON1,6 BSF NVMCON1,0 MOVF NVMDATL,W MOVWF eeprom_data_low MOVF NVMDATH,W MOVWF eeprom_data_high
无限循环的等待代码
waitForRead: BTFSC NVMCON1,0 GOTO waitForRead
核心问题分析与修正
1. 地址配置错误
PIC16F18877的数据EEPROM绝对地址范围为0xF000~0xF0FF,但NVM地址寄存器NVMADRH的正确值应为0x0F(对应数据EEPROM的NVM bank),而非代码中使用的0xF0。绝对地址0xF001对应:
NVMADRH = 0x0FNVMADRL = 0x01
2. NVMREGS位配置错误
NVMCON1<6>(NVMREGS)用于选择NVM访问类型:
- 置1:访问特殊功能寄存器的NVM空间
- 清零:访问数据EEPROM/程序存储器
代码中读写操作均置1,导致实际未访问数据EEPROM。
3. 未等待操作完成
- 读取操作:
RD位(NVMCON1<0>)会在读取完成后自动清零,需等待该位清零后再读取NVMDATL - 写入操作:
WR位(NVMCON1<1>)会在写入完成后自动清零,需等待该位清零后再进行读回验证
之前的等待循环进入无限循环,本质是地址/NVMREGS配置错误导致硬件无法完成读取操作。
4. 写入操作冗余与错误设置
- 写入前重复设置地址与
WREN,属于冗余操作 - 数据EEPROM为字节宽度,
NVMDATH无意义,无需设置 WREN需在解锁序列前保持置1,代码中在解锁后立即清零,可能导致写入未完成
修正后的完整代码
; 初始化地址:数据EEPROM绝对地址0xF001 → NVMADRH=0x0F, NVMADRL=0x01 MOVLW 01h MOVWF eeprom_addr_low MOVLW 0Fh MOVWF eeprom_addr_high ; -------------------------- ; 读取初始数据 ; -------------------------- BANKSEL NVMADRL MOVF eeprom_addr_low,W MOVWF NVMADRL MOVF eeprom_addr_high,W MOVWF NVMADRH BCF NVMCON1,6 ; NVMREGS=0,访问数据EEPROM BSF NVMCON1,0 ; 启动读取 waitForReadInit: BTFSC NVMCON1,0 ; 等待RD位清零(读取完成) GOTO waitForReadInit MOVF NVMDATL,W MOVWF eeprom_data_low ; 仅读取低字节,数据EEPROM为字节宽度 ; -------------------------- ; 写入数据0x25 ; -------------------------- BANKSEL NVMADRL MOVF eeprom_addr_low,W MOVWF NVMADRL MOVF eeprom_addr_high,W MOVWF NVMADRH MOVLW 025h MOVWF NVMDATL ; 设置要写入的数据 BSF NVMCON1,2 ; WREN=1,允许写入 BCF NVMCON1,6 ; NVMREGS=0,访问数据EEPROM ; 执行解锁序列 BCF INTCON,7 ; 关闭全局中断 MOVLW 055h MOVWF NVMCON2 MOVLW 0AAh MOVWF NVMCON2 BSF NVMCON1,1 ; 启动写入 waitForWrite: BTFSC NVMCON1,1 ; 等待WR位清零(写入完成) GOTO waitForWrite BSF INTCON,7 ; 恢复全局中断 BCF NVMCON1,2 ; WREN=0,禁止写入 ; -------------------------- ; 读回验证 ; -------------------------- BANKSEL NVMADRL MOVF eeprom_addr_low,W MOVWF NVMADRL MOVF eeprom_addr_high,W MOVWF NVMADRH BCF NVMCON1,6 BSF NVMCON1,0 waitForReadBack: BTFSC NVMCON1,0 GOTO waitForReadBack MOVF NVMDATL,W MOVWF eeprom_data_low ; 读回验证数据
关键注意事项
- 数据EEPROM的NVM bank为
0x0F,绝对地址0xF0xx对应NVMADRH=0x0F、NVMADRL=0xx - 访问数据EEPROM必须将
NVMREGS位清零 - 读写操作必须等待对应标志位清零后再访问数据寄存器,避免读取无效数据
- 写入解锁序列必须严格按照
0x55→0xAA的顺序写入NVMCON2 - 数据EEPROM为字节存储,仅需操作
NVMDATL寄存器
内容的提问来源于stack exchange,提问作者Dominick
相关产品推荐
相关产品推荐

