【问题标题】:Unwanted Jump to interrupt MPLAB X IDE v.3.30不需要的跳转以中断 MPLAB X IDE v.3.30
【发布时间】:2016-05-13 16:02:59
【问题描述】:

我是微控制器编程的新手,我正在尝试为 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");
    }
}

【问题讨论】:

  • 您是说 PIC12F1571 吗?没有设备 PICLF1571。

标签: c assembly embedded


【解决方案1】:

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

还要明白,PIC12闪存是word-write/row-erase,一行是16个word。所以擦除操作也会擦除整个向量表和程序区的开头。您实际上是在修改代码,但不是以任何有意义的方式(如果它完全有意义的话)。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多