Reputation: 1233
I want to store a number to PIC18 then retain it even if the power is lost or the unit is reset. I think my writing code portion looks fine, just the reading portion of it looks strange after the unit is reset.
I am using the following code which I got from Microchip.
Code:
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);
The ouput: 1
However when I reset the unit and only use the reading code I always get 255.
Code to read:
DataEEInit();
value = DataEERead(DEEaddr);
printf("%d",value);
The output: 255
Why is this happening? I am assuming maybe the value is not being saved or the reading portion is incorrect. Thank you!
Upvotes: 0
Views: 13236
Reputation: 21
This is an explanation of the 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
*/
This is helpful code:
#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);
}
Upvotes: 2
Reputation: 345
Two functions: write to flash using 64-byte buffer @ 8-byte blocks and a read/compare flash function.
For device: PIC18F46K80
Stuff for a header file:
#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);\
}
Write to flash function:
/******************************************************
* 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
}
}
Verify written data (demonstrates flash read)
/******************************************************
* 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;
}
Yours, Bryan Wilcutt
Upvotes: 2
Reputation: 79
The value of 255 is default value for EEPROM memory. I think after changing the code, you program microcontroller IC again. So, your EEPROM memory will be erased and return to its default value. If you use MPLAB as compiler, you can go to 'Programmer'tab > Settings.. > Program Memory > Program Options and click on Preserve EEPROM on Program. Hope it works.
Upvotes: 0
Reputation: 11
SRAM can not be used to store Non-volatile data...
SRAM will loose data during power cycle...
Options: 1. Use internal EEPROM if available. 2. External EEPROM through I2C or SPI. 3. PIC18 Data Emulation Library.
Upvotes: 1
Reputation: 845
Some PIC18 micros have an internal EEPROM in addition to the internal flash. The 18F87J11 does not have this so you have 2 options:
1) Write to the flash memory - this is where your program is stored. make sure the number of write/read cycles is ok for your application.
2) Use an external i2c or spi memory for your configuration settings
The DataEEWrite you are using are from an 'eeprom emulation' library from microchip (linked in the comments below. There are a couple of things to be careful of:
Upvotes: 0
Reputation: 1863
The device you're using doesn't have internal non-volatile memory apart from its Flash, generally used for storing code.
You have two options that I can see:
I haven't worked with PICs for years, so can't offer you much in the way of implementation detail but I suspect there are many examples you can source from Microchip's website.
In essence, the reason your code doesn't work is because you're trying to access memory that isn't there. If it is there, then the interface is not correct.
EDIT:
I've had a look through the code examples page for the PIC18 on Microchip's website and can't find any C examples for writing to the program memory. Unfortunately, it looks like you'll have to implement it in assembler. I don't know the semantics for the MPLAB compiler but, generally, it'll be something like this if you're going to do it inline:
void my_assembler_function(void)
{
// Inline assembler code, actioned via C.
asm("MOV x y");
asm("MOV y z");
}
Alternatively, many C compilers for microprocessor's allow you to call an external .s
file with a C function call, saving you from doing it inline.
I think you can follow the example I found here to actually implement the functionality you're after.
Upvotes: 1
Reputation: 94
To retain the values on power cycle, SRAM memory should be used. Please confirm if you have SRAM memory available first.
Upvotes: -2