Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] Not Working - Internal EEP code for PIC18F45K40

Status
Not open for further replies.

FrustratedEngineer

Newbie level 6
Joined
Nov 30, 2015
Messages
12
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
122
Hi,

I am working on PIC18F45K40. I am using Internal EEP as Data memory. My task is to Read/Write Data on EEP.
Here is a source code...

Main routine


Code:
 volatile U8 au8Data[5]= {0x01, 0x02, 0x05, 0x07, 0x08};
    volatile U8 u8Index;
    
    WriteData(&au8Data[0], 10, 5);
    ReadData(&au8Data[0], 10, 5);
    //Deliberately added to check variable value in debug mode
    for(u8Index=0; u8Index < 5; u8Index++)
    {
        au8Data[u8Index] = 0x00; 
    }

Sub routines

Code:
void WriteData(U8* Pu8Src, U8 u8Area, U8 u8Len)
{
    U8 u8Index;
    if( (Pu8Src != NULL)&&(u8Len > 0))
    {
        for(u8Index=0; u8Index < u8Len; u8Index++)
        {
            WriteByte((u8Area+u8Index), Pu8Src[u8Index]);
        }
    }
}


void ReadData(U8* Pu8Dest, U8 u8Area, U8 u8Len)
{
    U8 u8Index;
    if( (Pu8Dest != NULL)&&(u8Len > 0))
    {
        for(u8Index=0; u8Index < u8Len; u8Index++)
        {
            Pu8Dest[u8Index] = ReadByte(u8Area+u8Index);
        }
    }    
}


/**--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 * OnChip EEPROM SFRs
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------**/
#define D_CPU_EEP_REG_ADDR_LOW        NVMADRL
#define D_CPU_EEP_REG_ADDR_HIGH       NVMADR
#define D_CPU_EEP_REG_DATA_LOW        NVMDAT
#define D_CPU_EEP_BIT_EN_WR              NVMCON1bits.WR
#define D_CPU_EEP_BIT_STATUS_WR       NVMCON1bits.WREN
#define D_CPU_EEP_BIT_STATUS_RD       NVMCON1bits.RD

#define D_CPU_EEP_SET_MEM_AS_DATA()     {\
    NVMCON1bits.NVMREG0 = 0;\
    NVMCON1bits.NVMREG1 = 0;\
}
#define D_CPU_EEP_UNLOCK_SEQUENCE() {\
NVMCON2 = 0x55;\
NVMCON2 = 0xAA;\
} 

void  WriteByte(U8 u8Address, U8 u8Byte)
{
    U8 u8IntrReg = INTCONbits.GIE; 
    
    D_CPU_EEP_SET_MEM_AS_DATA();
    D_CPU_EEP_REG_ADDR_LOW = u8Address;
    D_CPU_EEP_REG_ADDR_HIGH = 0xFF;
    D_CPU_EEP_REG_DATA_LOW = u8Byte;
    D_CPU_EEP_BIT_EN_WR = D_BIT_HIGH; 
    D_CPU_DISABLE_INT();
    D_CPU_EEP_UNLOCK_SEQUENCE();
    D_CPU_EEP_BIT_STATUS_WR = D_BIT_HIGH; 
    while(D_BIT_HIGH == D_CPU_EEP_BIT_EN_WR)
    {
        //Wait for Writing to be finished
    }
//    D_CPU_ENABLE_INT();
    INTCONbits.GIE = u8IntrReg;
    D_CPU_EEP_BIT_STATUS_WR = D_BIT_LOW; 

    ///Assembly code from Datasheet
    /*
        ; Data Memory Address to write
        BCF NVMCON1, NVMREG0 ; Setup Data EEPROM access
        BCF NVMCON1, NVMREG1 ; Setup Data EEPROM access
        MOVF EE_ADDRL, W ;
        MOVWF NVMADRL ; Setup Address low byte
        MOVF EE_ADDRH, W ;
        MOVWF NVMADRH ; Setup Address high byte (if applicable)
        ; Data Memory Value to write
        MOVF EE_DATA, W ;
        MOVWF NVMDAT ;
        ; Enable writes
        BSF NVMCON1, WREN ;
        ; Disable interrupts
        BCF INTCON, GIE ;
        ; Required unlock sequence
        MOVLW 55h ;
        MOVWF NVMCON2 ;
        MOVLW AAh ;
        MOVWF NVMCON2 ;
        ; Set WR bit to begin write
        BSF NVMCON1, WR ;
        ; Wait for write to complete
        BTFSC NVMCON1, WR
        BRA $-2
        ; Enable INT
        BSF INTCON, GIE ;
        ; Disable writes
        BCF NVMCON1, WREN ;
     */
}


U8   ReadByte(U8 u8Address)
{
    U8 u8Byte;    
    
    D_CPU_EEP_SET_MEM_AS_DATA();
    D_CPU_EEP_REG_ADDR_LOW = u8Address;
    D_CPU_EEP_REG_ADDR_HIGH = 0xFF;
    D_CPU_EEP_BIT_STATUS_RD = D_BIT_HIGH;     
    NOP();
    NOP();
    u8Byte = D_CPU_EEP_REG_DATA_LOW;
    return u8Byte;
    
    ///Assembly code from Datasheet
    /*
    BCF NVMCON1, NVMREG0 ; Setup Data EEPROM Access
    BCF NVMCON1, NVMREG1 ; Setup Data EEPROM Access
    MOVF EE_ADDRL, W ;
    MOVWF NVMADRL ; Setup Address low byte
    MOVF EE_ADDRH, W ;
    MOVWF NVMADRH ; Setup Address high byte (if applicable)
    BSF NVMCON1, RD ; Issue EE Read
    MOVF NVMDAT, W ; W = EE_DATA
     */
}

when I check the output of the main routine in debug mode, I always get 0xFF in the array.
Please tell me where is it going wrong.

Note -
1. I have already browsed through google/microchip website for the sample code of this MCU but didn't get any.
2. The MCC generated code and the code I wrote matches fairly.
 
Last edited:

Hi,

1. I have already browsed through google/microchip website for the sample code of this MCU but didn't get any.
2. The MCC generated code and the code I wrote matches fairly.
There is ASM code in the datasheet.
It should be no problem for you to cross check this ASM code with your C code or the ASM code cenerated by the compiler.

Klaus
 

Compare your code thoroughly with ASM example, you are mixing up WREN and WR bit I think.

There are by the way ready-to-use C routines or libarary functions for EEPROM access in effectively any PIC compiler (e.g. Microchip, CCS, mikroC).
 

It is always a good idea to use assembler for the various unlock sequences rather than C code. The MCU requires that the instructions are executed sequentially with no intervening code (which includes interrupts) and the C compiler (any of them) need not follow this requirement.
Also make sure that you do not use the debugger to stop anywhere in the reading or writing code as the MCU will (again) see this as instructions that are not executed sequentially.
BTW - 0xFF is the value that the FLASH memory has for erased cells. If you are always reading this value it means that the write has not succeeded.
Finally, be careful of how you use the emulated EEPROM in FLASH - you will need to check the data sheet for the minimum erase/write cycles that the FLASH can provide but it can be exceeded quite quickly if you use this capability for the wrong functions. It can often be better to use an external EEPROM that is designed for many erase/write cycles.
Susan
(PS: Don't assume MCC generated code is always "good".)
 

The problem is solved.
The issue was... By mistake I interchanged WR and WREN.

Moderators can close the thread.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top