Author Topic: PIC16F877A Program Memory Write  (Read 5120 times)

0 Members and 1 Guest are viewing this topic.

Offline melihariciiTopic starter

  • Contributor
  • Posts: 14
  • Country: tr
PIC16F877A Program Memory Write
« on: October 30, 2016, 08:59:47 pm »
(Soory for my english  :) )
I read to datasheet and I was use the next example assembly program but I cant be succesful .

I am use PIC16F877A 

0000|0000|0000|0000|
|-EEADRH-|-EEADR---|

1-) I am be sure to writeable program memory with config bits
2-) write to EEADR to low addres
3-) write to EEADRH to high addres
4-) write to EEDATA
5-) write to EEDATH (this both data be 0xBB)
6-) and EECON1's 7th bits will be  set for EEPGD
7-) write EECON2 0x55 and 0xAA sequentially
8-) write EECON1 WR bits sets

and nothing happened

what I make wrong please help me .
please use simple english :)

Thanks everyone.
« Last Edit: October 31, 2016, 12:20:21 am by meliharicii »
 

Offline Andy Watson

  • Super Contributor
  • ***
  • Posts: 2340
Re: PIC16F877A Program Memory Write
« Reply #1 on: October 30, 2016, 09:59:05 pm »
Step 6. Bit 7 should be set to access program memory.
What are you writing in, C or assembly?
 
The following users thanked this post: meliharicii

Offline melihariciiTopic starter

  • Contributor
  • Posts: 14
  • Country: tr
Re: PIC16F877A Program Memory Write
« Reply #2 on: October 30, 2016, 10:25:01 pm »
I am trying in C
 

Offline Andy Watson

  • Super Contributor
  • ***
  • Posts: 2340
Re: PIC16F877A Program Memory Write
« Reply #3 on: October 30, 2016, 11:19:59 pm »
If you are operating on program memory (rather than data eeprom) the later devices need to be programmed in blocks of four writes. See section 3.6 of the data sheet.

http://ww1.microchip.com/downloads/en/DeviceDoc/39582C.pdf
 
The following users thanked this post: meliharicii

Offline StillTrying

  • Super Contributor
  • ***
  • Posts: 2892
  • Country: se
  • Country: Broken Britain
Re: PIC16F877A Program Memory Write
« Reply #4 on: October 31, 2016, 12:37:48 am »
BSF EECON1,WREN ; Enable writes
.........
BCF EECON1,WREN ; Disable writes

Seem to be missing, and probably others!
.  That took much longer than I thought it would.
 
The following users thanked this post: meliharicii

Offline JPortici

  • Super Contributor
  • ***
  • Posts: 3921
  • Country: it
Re: PIC16F877A Program Memory Write
« Reply #5 on: October 31, 2016, 06:20:13 am »
post your code.
 
The following users thanked this post: meliharicii

Offline melihariciiTopic starter

  • Contributor
  • Posts: 14
  • Country: tr
Re: PIC16F877A Program Memory Write
« Reply #6 on: November 01, 2016, 09:36:55 pm »
Code: [Select]
void WritePM(unsigned char datl,unsigned char dath,unsigned char addrl,unsigned char addrh){
    unsigned char addr;
    unsigned char datal=datl;
    unsigned char datah=dath;
    unsigned char tmp;
    unsigned char loop=1;
    addr=&datal;
   
    EEADRH=addrh;
    EEADR=addrl;
    FSR=addr;
   
    while(loop){
        EEDATA=INDF;
        FSR=FSR+1;
        EEDATH=INDF;
        FSR=FSR+1;
        EECON1=EECON1|0x80; // EEPGD bits set   1000 0000 =0x80
        EECON1=EECON1|0x4;  //  WREN bit set    0000 0100 =0x4
        INTCON=INTCON&0x7F; //  GIE clear       0111 1111 =0x7F
        EECON2=0x55;
        EECON2=0xAA;
        EECON1=EECON1|0x2; //WR bit set         0000 0010 =0x2
        EECON1=EECON1&0xFB;//WREN bit clear     1111 1011 =0xFB
        INTCON=INTCON|0x80;//GIE set            1000 0000 =0x80
        EEADR=EEADR+1;
        tmp=EEADR;
        tmp=tmp&0x03;
        tmp=tmp^0x03;
        if(tmp==0){
            loop=0;
        }
    }
}

sorry about late answer , what does it look like?
« Last Edit: November 01, 2016, 09:47:42 pm by meliharicii »
 

Offline Andy Watson

  • Super Contributor
  • ***
  • Posts: 2340
Re: PIC16F877A Program Memory Write
« Reply #7 on: November 01, 2016, 09:57:36 pm »
I am wondering if the EEPROM can be written using C. The PIC Midrange Reference manual states that the sequence write 55, write aa and then set WR bit must be performed exactly. The 16F877 manual also states that one or two instructions following the initiation of a write will be ignored and treated as a NOP. I think it may be necessary to code the writing sequence into assembly code.

 
The following users thanked this post: meliharicii

Offline melihariciiTopic starter

  • Contributor
  • Posts: 14
  • Country: tr
Re: PIC16F877A Program Memory Write
« Reply #8 on: November 01, 2016, 10:22:28 pm »
I tried  write EEPROM with C. its worked but I am trying to write program memory. Not good result. you think I should write assembly ?
 

Offline Andy Watson

  • Super Contributor
  • ***
  • Posts: 2340
Re: PIC16F877A Program Memory Write
« Reply #9 on: November 01, 2016, 11:41:37 pm »
The assembly code example in the manual calls for two NOPs to follow the EECON1 Write.
Code: [Select]
        EECON1=EECON1|0x2; //WR bit set         0000 0010 =0x2
       NOP
       NOP
        EECON1=EECON1&0xFB;//WREN bit clear     1111 1011 =0xFB

Does your compiler allow in-line assembly?

Edit: The program read operation also requires two NOPs  following the RD initiation instruction.
« Last Edit: November 01, 2016, 11:44:14 pm by Andy Watson »
 
The following users thanked this post: meliharicii

Offline melihariciiTopic starter

  • Contributor
  • Posts: 14
  • Country: tr
Re: PIC16F877A Program Memory Write
« Reply #10 on: November 02, 2016, 12:41:45 am »
I write this style
Code: [Select]
        EECON1=EECON1|0x2; //WR bit set         0000 0010 =0x2
        asm("NOP");
        asm("NOP");
        EECON1=EECON1&0xFB;//WREN bit clear     1111 1011 =0xFB
debug code look like this
Code: [Select]
        EECON1=EECON1|0x2; //WR bit set         0000 0010 =0x2
0x7D7: MOVF PIR1, W
0x7D8: IORLW 0x2
0x7D9: MOVWF PIR1
!        asm("NOP");
0x7DA: NOP
!        asm("NOP");
0x7DB: NOP
!        EECON1=EECON1&0xFB;//WREN bit clear     1111 1011 =0xFB
0x7DC: BSF STATUS, 0x5
0x7DD: BSF STATUS, 0x6
0x7DE: MOVF PIR1, W
0x7DF: ANDLW 0xFB
0x7E0: MOVWF PIR1

Not worked.

I tried this style

Code: [Select]
//EECON1=EECON1|0x2; //WR bit set         0000 0010 =0x2
asm("BSF EECON1,1"); //not define WR
asm("NOP");
asm("NOP");
asm("BCF EECON1,2");
//EECON1=EECON1&0xFB;//WREN bit clear     1111 1011 =0xFB

I tried in main this.
Code: [Select]
int main(int argc, char** argv) {
    WritePM(0xBB,0xBB,0x00,0x00);
    return (EXIT_SUCCESS);
}

I dont know maybe this wrong side.
 

Offline JPortici

  • Super Contributor
  • ***
  • Posts: 3921
  • Country: it
Re: PIC16F877A Program Memory Write
« Reply #11 on: November 02, 2016, 07:06:50 am »
what compiler are you using again?

and it seems to me you are not following the procedure written in the datasheet on page 44, where you even have a ready-to-use procedure.

first of all, the status of the  WRT configuration bit? if it's set you can't write on program memory.
then the cose trasnlated from assembly would look like this
Code: [Select]
unsigned char dataL,dataH;
unsigned char addrL,addrH;

EEADR = addrL;    //the compiler here perform bank switching if necessary
EEADRH = addrH;
EEDATA = dataL;
EEDATH = dataH;
EECON1bits.EEPGD = 1;  //point to program memory
EECON1bits.WREN = 1;   //enable writes
INTCONbits.GIE = 0;       //disable interrupts if needed
EECON2 = 0x55;
EECON2 = 0xAA;
EECON1bits.WR = 1;       //start program memory write
NOP();
NOP();
INTCON1bits.GIE = 1;
EECON1bits.WREN = 0;   //disable write

if this up here doesn't work toss away your compiler because it's a shitty one. free version of XC8 will do better.
 
The following users thanked this post: meliharicii

Offline melihariciiTopic starter

  • Contributor
  • Posts: 14
  • Country: tr
Re: PIC16F877A Program Memory Write
« Reply #12 on: November 05, 2016, 07:54:59 pm »
Code: [Select]
#include <htc.h>


#define _XTAL_FREQ 4000000
/*
 *
 */
void WritePM(unsigned char datl,unsigned char dath,unsigned char addrl,unsigned char addrh){
    unsigned char addr;
    unsigned char datal=datl;
    unsigned char datah=dath;
 
    addr=&datal;
   
    EEADR=addrl;
    EEADRH=addrh; 
    EEDATA=datal;
    EEDATH=datah;
    EECON1bits.EEPGD=1; // EEPGD bits set   1000 0000 =0x80
    EECON1bits.WREN=1;  //  WREN bit set    0000 0100 =0x4
    INTCONbits.GIE=0; //  GIE clear       0111 1111 =0x7F
    EECON2=0x55;
    EECON2=0xAA;
    EECON1bits.WR=1; //WR bit set         0000 0010 =0x2
    //asm("BSF EECON1,1"); //not define WR
    asm("NOP");
    asm("NOP");
    __delay_ms(2);
    //asm("BCF EECON1,2");
    INTCONbits.GIE=1;//GIE set            1000 0000 =0x80
    EECON1bits.WREN=0;//WREN bit clear     1111 1011 =0xFB
    return;
}


void main(void) {
    unsigned char Hello1=0x00;
    unsigned char Hello2=0x00;
    while(1){

        WritePM(0x00,0x10,Hello1,Hello2);
        Hello1++;
        if(Hello1==0xFE){
            if(Hello2==0xFE){
            Hello2=0x00;               
            }
            Hello2++;
            Hello1=0x00;
                    }
            }
}

It's working .Now another question :) I can't write all memory when I run this code in simulation. Last writen adress is 0x03FE . Picture in attachment.
 

Offline JPortici

  • Super Contributor
  • ***
  • Posts: 3921
  • Country: it
Re: PIC16F877A Program Memory Write
« Reply #13 on: November 05, 2016, 08:03:35 pm »
maybe with the last write you are actually overwriting your application code?
 
The following users thanked this post: meliharicii

Offline Bruce Abbott

  • Frequent Contributor
  • **
  • Posts: 628
  • Country: nz
    • Bruce Abbott's R/C Models and Electronics
Re: PIC16F877A Program Memory Write
« Reply #14 on: November 06, 2016, 01:54:38 am »
Kind of hard for the program to keep working after it wipes out its own memory!

And this:-
Code: [Select]
        Hello1++;
        if(Hello1==0xFE){
            if(Hello2==0xFE){
            Hello2=0x00;               
            }
            Hello2++;
            Hello1=0x00;
skips 0xFE and 0xFF (which I am guessing is not what you wanted).

'unsigned char' automatically wraps around from 0xFF to 0x00. So you can just do this:-
Code: [Select]
        Hello1++;
        if(Hello1==0x00){
            Hello2++;
        }


Two more things:-

1. Did you disable the watchdog?

2. You don't need the __delay_ms(2) because the CPU is automatically halted while program memory is being written to  (since it can't fetch instructions during this time!).
 
The following users thanked this post: meliharicii

Offline melihariciiTopic starter

  • Contributor
  • Posts: 14
  • Country: tr
Re: PIC16F877A Program Memory Write
« Reply #15 on: November 20, 2016, 05:02:59 am »
1 WDT disable
2 its true

New thing "bootloader"

Code: [Select]
#include <htc.h>


#define _XTAL_FREQ  4000000

#define BASEADRESS 0x0009
#define BASEADRESSL 0x09
#define BASEADRESSH 0x00
#define SET         0x01

unsigned char ProgramData[]={0x16,0x83,0x13,0x03,0x01,0x86,0x30,0xFF,0x12,0x83,0x13,0x03,0x00,0x86,0x30,0x03\
                            ,0x00,0xF2,0x30,0x8A,0x00,0xF1,0x30,0x56,0x00,0xF0,0x0B,0xF0,0x2F,0xE4,0x0B,0xF1\
                            ,0x2F,0xE4,0x0B,0xF2,0x2F,0xE4,0x2F,0xEB,0x12,0x83,0x13,0x03,0x01,0x86,0x30,0x03\
                            ,0x00,0xF2,0x30,0x8A,0x00,0xF1,0x30,0x56,0x00,0xF0,0x0B,0xF0,0x2F,0xF4,0x0B,0xF1\
                            ,0x2F,0xF4,0x0B,0xF2,0x2F,0xF4,0x2F,0xFB,0x2F,0xDA,0x01,0x83,0x12,0x0A,0x11,0x8A\
                            ,0x2F,0xD7};

void led(){
    TRISB=0x00;
    while(1){
        PORTB=0xFF;
        __delay_ms(500);
        PORTB=0x00;
        __delay_ms(500);
    }

}
void WritePM(unsigned char dath,unsigned char datl,unsigned char addrh,unsigned char addrl){
    //unsigned char addr;
    unsigned char datal=datl;
    unsigned char datah=dath;
 
    //addr=&datal;
   
    EEADR=addrl;
    EEADRH=addrh; 
    EEDATA=datal;
    EEDATH=datah;
    EECON1bits.EEPGD=1; // EEPGD bits set   1000 0000 =0x80
    EECON1bits.WREN=1;  //  WREN bit set    0000 0100 =0x4
    INTCONbits.GIE=0; //  GIE clear       0111 1111 =0x7F
    EECON2=0x55;
    EECON2=0xAA;
    EECON1bits.WR=1; //WR bit set         0000 0010 =0x2
    //asm("BSF EECON1,1"); //not define WR
    asm("NOP");
    asm("NOP");
    //asm("BCF EECON1,2");
    INTCONbits.GIE=1;//GIE set            1000 0000 =0x80
    EECON1bits.WREN=0;//WREN bit clear     1111 1011 =0xFB
    return;
}
void FillPrgMem(unsigned char *ptr,unsigned int sizeofprogram){
    unsigned char addrrh=BASEADRESSH;
    unsigned char addrrl=BASEADRESSL-1;
    unsigned char flag1=0;
    unsigned char flag2=0;
    unsigned int loopcalculate=sizeofprogram;
    while(loopcalculate){
    addrrl++;
    if(addrrl==0xFF){
        flag1=SET;
        addrrh++;
    }
    if(addrrh==0xFF){
        flag2=SET;
    }
   
    WritePM(*ptr,*(ptr+1),addrrh,addrrl);
    if(flag1==SET){
        addrrl=0x00;
    }
    if(flag2==SET){
        addrrh=0x00;
    }
    ptr=ptr+0x02;
   
    loopcalculate--;
    }
}
void main(void) {
/**/
    void (*start)(void);
    FillPrgMem(ProgramData,88);
    start=BASEADRESS;
    start();
   
           
}

I am trying write bootloader and again I have some problem.

I need your proposal

I am still working on this code.
« Last Edit: November 20, 2016, 05:04:52 am by meliharicii »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf

 

- - -
-->