繁体   English   中英

不需要的跳转中断MPLAB X IDE v.3.30

[英]Unwanted Jump to interrupt MPLAB X IDE v.3.30

我是微控制器编程的新手,我正在尝试为PICLF1571编写一个定时器程序。 每次从睡眠中唤醒时,都应该写入闪存。 当我用模拟调试它时,它能够写一次,但是一旦它循环,程序就会陷入中断程序。 如果我注释掉中断例程,模拟跳转到另一个地方或转到0x00。 我看到程序卡住的唯一一次是使用函数flash_write时。

如果没有触发标志,可能会导致中断发生的原因是什么?

引脚设置

void init(void){
    ANSELA = 0x0;           //|-> Pin setup
    TRISA = 0x0;
    TRISAbits.TRISA5 = 1;
    PORTA = 0x0;
    LATA = 0x0;
    INTCONbits.GIE = 1;     //|-> Interrupt setup
    INTCONbits.IOCIE = 1;
    IOCAP = 0x0;
    IOCAPbits.IOCAP5 = 0;
    INTCONbits.IOCIF = 0;
    IOCAF = 0x0;
    IOCAFbits.IOCAF5 = 0;
    WDTCONbits.SWDTEN = 1;  //|-> Watchdog Timer setup
    WDTCONbits.WDTPS = 0b00001;// reconfigure for correct speed
    //currently        0b10001
}

主要

//#include <stdio.h>
#include <xc.h>
#include "init.h"
#include "Interrupt.h"
#include "flash.h"

int main(void){
    init();
    unsigned short ad = 1;
    unsigned short f = 0x3FFF;
    unsigned short a = 0x0000;
    unsigned short ret = 0x0000;
    flash_erase(0x0000);
    while(1) {
        asm("sleep");
        flash_write(a,f);

        //flash_erase(a);
        //flash_read1(a,&ret);
    }
    return 1;
}

flash_write函数。 基于数据表中的流程图的说明

void flash_write(unsigned short addr, unsigned short data){
    INTCONbits.GIE = 0; //||]->start write
    PMCON1bits.CFGS = 0;//||]
    PMADRH = (unsigned char)((addr >> 8) & 0xFF);
    PMADRL = (unsigned char)(addr & 0xFF);
    PMCON1bits.FREE = 0;//||]->enable write
    PMCON1bits.LWLO = 1;//||]
    PMCON1bits.WREN = 1;//||]
    PMDATH = (unsigned char)((data >> 8) & 0xFF);
    PMDATL = (unsigned char)(data & 0xFF);
    PMCON1bits.LWLO = 0;
    PMCON2 = 0x55;      //||]->unlock sequence
    PMCON2 = 0xAA;      //||]
    PMCON1bits.WR = 1;  //||]
    NOP();              //||]
    NOP();              //||]
    PMCON1bits.WREN = 0;//]->end write 
    INTCONbits.GIE = 1;
    asm("RETURN");
}

中断程序

#include <xc.h>
void interrupt button(void){
    if (INTCONbits.IOCIE == 1 && IOCAFbits.IOCAF5 == 1 ){
        int time = 0;
        while (PORTAbits.RA5 == 1){//RA5 in sim never changes. always 0
            time++;
            if (time >= 20000 && PORTAbits.RA5 == 1){
                LATA = 0x0;
                asm("NOP");
                break;
           }
            if ( time < 20000 && PORTAbits.RA5 == 0){
                asm("NOP");
                break;
           }
        }
        IOCAF = 0x0;
        INTCONbits.IOCIF = 0;
        asm("RETFIE");
    }
}

0000h是复位向量地址; 一旦写入,后续复位将跳转到0x3fff,这不是一个只有0x3ff闪存字的设备上的有效地址。 请注意,由于0x3fff是闪存的擦除状态,因此在这种情况下写入实际上没有单独擦除引起的效果。

另外要了解的是,PIC12闪存是字写/行擦除,行是16个字。 因此擦除操作也将擦除整个向量表和程序区域的开始。 你本质上是修改代码,但不是以一种有意义的方式修改(如果它完全有意义的话)。

您应该使用适当的链接器指令保留一个闪存区域,并远离向量表(可能是0x3f0处的整个最后一行),以防止链接器在运行时要在要写入的空间中定位代码。

另一个问题是PIC12F1571上的闪存单元耐用性仅为10000次擦除/写入周期 - 您确定每次设备启动时都要写入同一地址吗? 如果您“删除”保留行并在擦除行并重新启动之前依次写入16个字中的每个字,则会将耐久性提高到160000个周期。 添加更多行以获得更大的耐力。 由于擦除闪存的值为0x3fff(14位字),要查找“当前值”,您需要扫描保留行中的最后一个值不是0x3fff(因此0x3fff隐式地不是有效的实际值)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM