0

我想将一个数字存储到 PIC18,然后即使断电或设备重置也能保留它。我认为我的编写代码部分看起来不错,只是单元重置后它的读取部分看起来很奇怪。

我正在使用从 Microchip 获得的以下代码。

代码:

unsigned int value;
unsigned int DEEdata = 1;
unsigned int  DEEaddr = 0x04;

DataEEInit();
dataEEFlags.val = 0;

DataEEWrite(DEEdata,DEEaddr);
value = DataEERead(DEEaddr);
Nop();
printf("%d",value);

输出:1

但是,当我重置单元并仅使用读取代码时,我总是得到 255。

代码阅读

DataEEInit();
value = DataEERead(DEEaddr);
printf("%d",value);

输出:255

为什么会这样?我假设可能没有保存该值或读取部分不正确。谢谢!

4

7 回答 7

2

两个功能:使用 64 字节缓冲区 @ 8 字节块写入闪存和读取/比较闪存功能。

对于设备:PIC18F46K80

头文件的东西:

#define PRGM_BUFFER_SIZE 8
#define TABLE_WRITE_SIZE 64

#define LOAD_TBL_PTR(x) { TBLPTRU = ((((x)>>8)>>8)&0xff);\
                      TBLPTRH = (((x) >> 8) & 0xff);\
                      TBLPTRL = ((x) & 0xff);\
                    }

写入闪存功能:

/******************************************************
 * Function     : write_block
 * Input        : uint16_t position in destination flash
 * Global       : uint8_t buffer[64] - Location of source data
 * Output       : None
 * Description  : Writes the contents of the 64 byte
 * data buffer to program flash space.  Only 64 bytes
 * can be written at once.   The process of writing
 * to flash is: Erase->Write.
 ******************************************************/
static void write_block(uint16_t addr)
{
    int r, c;

    // Erase flash block first.  Erases a 64 byte block at a time.

    LOAD_TBL_PTR(addr);

    EECON1bits.EEPGD = 1;   // Point to flash program memory
    EECON1bits.CFGS = 0;    // Access flash memory
    EECON1bits.WREN = 1;    // Enable write to memory
    EECON1bits.FREE = 1;    // Enable Erase operation

    EECON2 = 0x55;
    EECON2 = 0xAA;

    EECON1bits.WR = 1;      // Clear the flash

    asm("NOP");             // Stall

    // Write buffer to internal buffer.  This process writes 8 bytes at a time
    // so we need to loop 8 times (8*8 = 64).)

    for (r = 0; r < 8; r++)
    {
        LOAD_TBL_PTR((addr + (r * 8)));

        for (c = 0; c < PRGM_BUFFER_SIZE; c++)
        {
            TABLAT = buffer[(r * 8) + c];

            asm("TBLWT*+");      // Push byte and then inc to next internal buffer cell
        }

        // Write the block to flash

        asm("TBLRD*-");         // Point back to original row

        // Write internal buffer to flash

        EECON1bits.EEPGD = 1;   // Point to flash program memory
        EECON1bits.CFGS = 0;    // Access flash program memory
        EECON1bits.WREN = 1;    // Enable write to memory
        INTCONbits.GIE = 0;     // Disable interrupts

        EECON2 = 0x55;
        EECON2 = 0xAA;

        EECON1bits.WR = 1;      // Start programming flash
        INTCONbits.GIE = 1;     // Re-enable interrupts
        EECON1bits.WREN = 0;    // Disable write to memory
    }
}

验证写入的数据(演示闪存读取)

/******************************************************
 * Function     : compare_block
 * Input        : uint16_t position in destination flash
 * Global       : uint8_t buffer[64] - Location of previous written data
 * Output       : bool true=successful, false=did not match
 * Description  : Reads a 64 byte block of flash memory and
 * compares it to the data found in the global buffer.
 ******************************************************/
static bool compare_block(uint16_t addr)
{
    bool retVal = true; // succeeds
    uint8_t i = 0;

    INTCONbits.GIE = 0;     // Disable interrupts

    LOAD_TBL_PTR(addr);

    for (i = 0; i < TABLE_WRITE_SIZE && retVal == true; i++)
    {
        asm("TBLRD*+");

        if (buffer[i] != TABLAT)
            retVal = false;
    }

    INTCONbits.GIE = 1;     // Enable interrupts

    return retVal;
}

你的,布莱恩·威尔卡特

于 2016-11-25T22:09:22.973 回答
1

SRAM不能用于存储非易失性数据...

SRAM在电源循环期间会丢失数据...

选项: 1. 如果可用,使用内部 EEPROM。2. 通过 I2C 或 SPI 的外部 EEPROM。3. PIC18 数据仿真库。

于 2014-06-04T16:41:13.860 回答
1

您使用的设备除了 Flash 之外没有内部非易失性存储器,通常用于存储代码。

我可以看到您有两个选择:

  1. 使用一些外部闪存或 EEPROM 并将其连接到此 PIC 上可用的外部存储器总线(参见系列数据表的第 97 页)。
  2. 重新映射内部闪存以保留一小部分可用于存储您的数据(这样它就不会干扰专门用于代码的内存区域)并将您的数据写入该区域(第 87 页)。

我已经多年没有使用 PIC,因此无法为您提供太多的实现细节,但我怀疑您可以从 Microchip 的网站获得很多示例。

从本质上讲,您的代码不起作用的原因是您试图访问不存在的内存。如果它在那里,那么接口不正确。

编辑:

我浏览了 Microchip 网站上 PIC18 的代码示例页面,找不到任何用于写入程序存储器的 C 示例。不幸的是,看起来您必须在汇编程序中实现它。我不知道 MPLAB 编译器的语义,但一般来说,如果你要内联执行它,它会是这样的

void my_assembler_function(void)
{
    // Inline assembler code, actioned via C.
    asm("MOV x y");
    asm("MOV y z");
}

.s或者,许多用于微处理器的 C 编译器允许您使用 C 函数调用来调用外部文件,从而避免您进行内联操作。

我认为您可以按照我在此处找到的示例来实际实现您所追求的功能。

于 2013-05-14T12:42:15.617 回答
1

这是对PIC18的解释:

/* EEPROM Read and Write Functions -- WORKING
 * Used PIC18F45K22 and MPLAB and C18
 * Read and Write functions work.
 * EEPROM has 256 bytes of memory (256 distinct characters)
 * Select "Window" -> "PIC Memory Views" -> "EE Data Memory"
 * Download program to PIC18
 * Hold PIC in Reset (circle arrow with pause button)
 * Open EE Data Memory Tab and click "Read Device Memory" button (Top left of EE Data tab) while PIC is held in Reset
 */

这是有用的代码:

#include <p18cxxx.h>
#include <p18f45k22.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>

#pragma config FOSC = INTIO67, PLLCFG = OFF, PRICLKEN = ON, FCMEN = ON,     PWRTEN = OFF
#pragma config BOREN = SBORDIS, BORV = 250, WDTEN = OFF, WDTPS = 2048,    PBADEN = OFF, WRTD = OFF
#pragma config HFOFST = OFF, MCLRE = EXTMCLR, STVREN = ON, LVP = OFF, DEBUG = ON, CPD = OFF

void EE_Write(unsigned char addr, unsigned char value);
unsigned char EE_Read(unsigned char addr);

unsigned char test;

void main(void){
    OSCTUNEbits.PLLEN = 1;
    OSCCON = 0x4C; //Set to use internal clock.
    OSCCON2 = 0x00; // No 4x PLL

    TRISB = 0x00;
    ANSELB = 0x00;
    PORTB = 0x00;

    EE_Write(05, 0x5A);
    Delay10KTCYx(50);
    test = EE_Read(05);

    Delay10KTCYx(50);
    PORTB = 0xFF;

    Delay10KTCYx(50);
    PORTB = 0x00;

}

void EE_Write(unsigned char addr, unsigned char value)         
{         
    unsigned char SaveGIE = 0;         

    // Set EEPROM address                
    EEADR  = addr%256;         
    // Set EEPROM data         
    EEDATA = value;         
    // Select Data         
    EECON1bits.EEPGD = 0;         
    // Select EEPROM         
    EECON1bits.CFGS = 0;         
    // Enable write         
    EECON1bits.WREN = 1;         
    // Save current global interrupt enable state         
    SaveGIE = INTCONbits.GIE;         
    // Disable interrupts         
    INTCONbits.GIE = 0;         
    // Write unlock sequence         
    EECON2 = 0x55;         
    EECON2 = 0xaa;         
    // Start write         
    EECON1bits.WR = 1;         
    // Restore previous interrupts enable state         
    INTCONbits.GIE = SaveGIE;         
    // Wait for write completion         
    while(EECON1bits.WR);        
    // Disable writes         
    EECON1bits.WREN = 0;         
}

unsigned char EE_Read(unsigned char addr){

    while(EECON1bits.RD || EECON1bits.WR); // check the WR&RD bit to see    if a RD/WR is in progress
    EEADR = addr; // Write the address to EEADR.
    EECON1bits.CFGS = 0;
    EECON1bits.EEPGD = 0;
    EECON1bits.RD = 1; // Set the RD bit to trigger the eeprom read  operation.
    return(EEDATA);
}
于 2018-03-20T22:56:56.043 回答
0

除了内部闪存之外,一些 PIC18 微控制器还有一个内部 EEPROM。18F87J11 没有此功能,因此您有 2 个选项:

1)写入闪存 - 这是您的程序存储的地方。确保写入/读取周期数适合您的应用程序。

2) 使用外部 i2c 或 spi 内存进行配置设置

您使用的 DataEEWrite 来自 microchip 的“eeprom 仿真”库(链接在下面的评论中。有几件事需要注意:

  • 重新编程闪存时要小心!您可能会覆盖您的设置
  • 请记住,它不是真正的 eeprom!写入周期有限,您必须擦除大部分内存 - 您无法擦除单个字节
于 2013-05-15T15:05:05.180 回答
0

255 的值是 EEPROM 存储器的默认值。我认为更改代码后,您再次对微控制器 IC 进行编程。因此,您的 EEPROM 存储器将被擦除并恢复为默认值。如果您使用 MPLAB 作为编译器,您可以转到“Programmer”选项卡 > Settings.. > Program Memory > Program Options 并单击 Preserve EEPROM on Program。希望它有效。

于 2016-04-12T05:08:15.357 回答
-2

To retain the values on power cycle, SRAM memory should be used. Please confirm if you have SRAM memory available first.

于 2013-05-07T16:37:13.393 回答