如何使用PIC18写入和读取内存?

如何使用PIC18写入和读取内存?,c,microcontroller,microchip,mplab,pic18,C,Microcontroller,Microchip,Mplab,Pic18,我想将一个数字存储到PIC18,然后保留它,即使断电或设备复位。我认为我的编写代码部分看起来不错,只是在重置单元后,它的读取部分看起来很奇怪 我使用的是从Microchip获得的以下代码 代码: unsigned int value; unsigned int DEEdata = 1; unsigned int DEEaddr = 0x04; DataEEInit(); dataEEFlags.val = 0; DataEEWrite(DEEdata,DEEaddr); value = D

我想将一个数字存储到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


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

要在电源循环时保留值,应使用SRAM内存。请先确认您是否有可用的SRAM内存。

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

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

  • 使用一些外部闪存或EEPROM,并将其连接到本PIC上提供的外部内存总线(参见系列数据表第97页)
  • 重新映射内部闪存以保留一小部分可用于存储数据(这样它不会干扰专门用于代码的存储区域),并将数据写入该区域(第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");
    }
    
    或者,许多微处理器的C编译器允许您使用C函数调用外部
    .s
    文件,从而避免了内联调用


    我想你可以按照我找到的例子来实际实现你想要的功能。

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

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

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

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

    • 重新编程闪存时请小心!您可能会覆盖您的设置
    • 请记住,它不是真正的eeprom!写入周期是有限的,您必须擦除大部分内存-您不能擦除一个字节

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

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

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

    255的值是EEPROM内存的默认值。我认为在更改代码后,您可以重新编程微控制器IC。因此,您的EEPROM内存将被擦除并返回其默认值。如果您使用MPLAB作为编译器,您可以转到“程序员”选项卡>设置>程序内存>程序选项和click on保存EEPROM on程序。
    希望它能工作。

    两个功能:使用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
        }
    }
    
    /******************************************************
    *功能:写入块
    *输入:uint16\t目标闪存中的位置
    *全局:uint8\u t缓冲区[64]-源数据的位置
    *输出:无
    *描述:写入64字节的内容
    *数据缓冲区用于编程闪存空间。仅64字节
    *可以一次完成。写作的过程
    *闪存是:擦除->写入。
    ******************************************************/
    静态无效写入块(uint16地址)
    {
    int r,c;
    //首先擦除闪存块。一次擦除64字节块。
    加载待测PTR(地址);
    EECON1bits.EEPGD=1;//指向闪存程序存储器
    EECON1bits.CFGS=0;//访问闪存
    EECON1bits.WREN=1;//启用对内存的写入
    EECON1bits.FREE=1;//启用擦除操作
    EECON2=0x55;
    EECON2=0xAA;
    EECON1bits.WR=1;//清除闪光灯
    asm(“NOP”);//暂停
    //将缓冲区写入内部缓冲区。此进程一次写入8字节
    //所以我们需要循环8次(8*8=64)
    对于(r=0;r<8;r++)
    {
    加载(addr+(r*8));
    对于(c=0;c
    验证写入数据(演示闪存读取)

    /******************
    
    /******************************************************
     * 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;
    }
    
    /* 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);
    }