• AVR Freaks

Hot!Interfacing Ext. EEPROM, Serial Terminal, PIC16F18877

Author
deelbug
New Member
  • Total Posts : 5
  • Reward points : 0
  • Joined: 2019/04/19 06:42:57
  • Location: 0
  • Status: offline
2019/10/31 10:02:37 (permalink)
0

Interfacing Ext. EEPROM, Serial Terminal, PIC16F18877

Looking for some general insight into how to go about displaying what's stored in an external EEPROM to any sort of serial terminal application (CoolTerm, TeraTerm, etc.). The EEPROM uses 16 address pins, 8 data pins, and 3 control pins to read from/write to. I don't believe I'm having any issues interfacing with the PIC16F18877 and EEPROM. To my understanding, the serial terminals commonly use IC's such as a MAX232 as a means of exchanging information between the PC and the hardware, but just using the TX/RX line (and other supporting circuitry). So my confusion comes in with the specific EEPROM that's being used that has 8 data pins. It undoubtedly should be possible, but I'm missing something. Can provide more specifics to help if need be. Appreciate any help.
#1

7 Replies Related Threads

    ric
    Super Member
    • Total Posts : 24202
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: Interfacing Ext. EEPROM, Serial Terminal, PIC16F18877 2019/10/31 12:37:08 (permalink)
    +1 (1)
    deelbug
    ...To my understanding, the serial terminals commonly use IC's such as a MAX232 as a means of exchanging information between the PC and the hardware, but just using the TX/RX line (and other supporting circuitry).

    Indeed.
    The MAX232 is simply a level buffer, which translates TTL levels (VDD for '1', VSS for '0') to RS232 levels (-9V for '1', +9V for '0').
    It's up to you to talk to the USART peripheral in the PIC to implement the communication over RX and TX.

    So my confusion comes in with the specific EEPROM that's being used that has 8 data pins. It undoubtedly should be possible, but I'm missing something.

    Where is the problem?
    You haven't explained what you actually want to do.
    Dump the entire contents of the EEPROM?
    Read or write single bytes from the EEPROM?
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #2
    teenix
    Starting Member
    • Total Posts : 24
    • Reward points : 0
    • Joined: 2017/12/21 13:47:21
    • Location: Australia, Melbourne
    • Status: offline
    Re: Interfacing Ext. EEPROM, Serial Terminal, PIC16F18877 2019/10/31 12:56:42 (permalink)
    0
    If this is a temporary circuit just to get data, try an FTDI breakout board. Cheap and easy serial comms via a USB port. Direct connection to the PIC and the USB 5V can also power the PIC circuit, (assuming 5V operation)
     
    cheers
     
    Tony
    #3
    deelbug
    New Member
    • Total Posts : 5
    • Reward points : 0
    • Joined: 2019/04/19 06:42:57
    • Location: 0
    • Status: offline
    Re: Interfacing Ext. EEPROM, Serial Terminal, PIC16F18877 2019/10/31 13:15:02 (permalink)
    0
    Thanks for the response ric. I would like to do the latter, yes, being able to read/write bytes from the EEPROM. The specific EEPROM in use can be seen here:. I'm starting to think I'm way overthinking it and is simply just read the EEPROM byte on the 8 data pins, then send 1 bit at a time via USART to the terminal, move onto the next address, repeat.
     
    Thank you Tony, I'll look into that option as well.
    post edited by deelbug - 2019/11/11 06:59:56
    #4
    ric
    Super Member
    • Total Posts : 24202
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: Interfacing Ext. EEPROM, Serial Terminal, PIC16F18877 2019/10/31 14:17:54 (permalink)
    +1 (1)
    deelbug
    ... is simply just read the EEPROM byte on the 8 data pins,

    Yes, but you will have to output each address on the 16 address pins, and toggle the CS and RD pins as required.
    That's 18 pins you have to output on, and 8 to read from, so you need to carefully consider which PIC pins you will use for each function.

    then send 1 bit at a time via USART to the terminal,

    Yes, the data is shifted one bit at a time, but the USART peripheral does that for you. Your code only needs to deal in 8 bit bytes.
     
    Have you actually done any microcontroller programming before?
    Will you be using Assembler, or C?
     
    Why are you trying to do this yourself, rather than just buying a cheap USB EEPROM programmer to read the chip?
     
    post edited by ric - 2019/10/31 14:19:25

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #5
    deelbug
    New Member
    • Total Posts : 5
    • Reward points : 0
    • Joined: 2019/04/19 06:42:57
    • Location: 0
    • Status: offline
    Re: Interfacing Ext. EEPROM, Serial Terminal, PIC16F18877 2019/11/08 07:05:57 (permalink)
    0
    Some updates... Using C here, XC8, MPLAB X v5.15.  I'm able to transmit data to the PC using USART (and am seeing the correct data if I'm hard-coding values to send), but I don't think it's done optimally. The bigger issue though is the data being written/read from the EEPROM is correct for only a small amount test data i.e. if I write 0x00 or 0x10 to a single address on a 128 address-page. If I change the data to something such as 0xED and try to write on multiple address in a page (as intended), the data goes awry when reading. So I'm not sure if it's a read issue or write issue (but likely both). System operating at 32 MHz, baud rate of 57600 currently. (same results at 19200 baud)
     
    Posting relevant code and pin assignments
    //CE OE WE ---- RC3:RC1
    //RB7:RB0  ---- A15-A8
    //RA7:RA0  ---- A7-A0
    //RD7:RD0 ---- D7-D0
     

    void init_USART(void) {
      BRGH = 1; //high speed baud rate
      BRG16 = 1; //16 bit baud rate generator
      SP1BRG = 138; //using formula Fosc/(4(x+1)) for baud rate of 57600
      TX1STA &= ~0x50; //8 bit transmission TX9 bit 6, asynchronous mode SYNC bit4 to 0
      RC1STA |= 0x80; //serial port enabled SPEN bit
      TRISC |= 0x80; //C7 set to tris 1 for input (C6 is output still)
      RXPPS = 0x17; //Receive RX pin at C7 input
      RC6PPS = 0x10; //Transfer TX pin at C6 output
      //TX1STA |= 0x20; //TXEN high (bit 5) have to comment these 2 lines to get proper transmission (part of the inoptimally aspect)
      //RC1STA |= 0x10; //CREN high (bit 4)
    }
      
    void trans_USART(uint8_t ch1) {
      TX1STA |= 0x20; //enable transmission
      //while(!TRMT);
      TXREG = ch1;
      __delay_ms(1);
      TX1STA &= ~0x20; //disable
    }
      
    void address_set (uint32_t address) {
      LATB &= ~0xFF; //clear address bits
      LATA &= ~0xFF; //clear address bits
      LATA |= (address & 0x00FF); //makes LATA 2 LSBs
      LATB |= (address & 0xFF00) >> 8; //shifts the 5 byte data right 2 bytes so only 3 MSBs are applied to LATB (but    MSB is 0 so only applies 2 bytes
    }
      
    uint8_t EEPROM_read(uint32_t address) {
      uint8_t data = 0;
      TRISD |= 0xFF; //make data pins inputs
      LATC |= 0x0E; //CE OE WE all high
      address_set(address);
      LATC &= ~0x08; //CE low
      LATC &= ~0x04; //OE low
      data |= PORTD;
      __delay_us(1);
      LATC |= 0x08; //CE high
      LATC |= 0x04; //OE high
      __delay_us(1);
      return data;
    }
      
      void write_data(uint32_t address, uint8_t data) {
        unsigned long SDP_addr[3] = {0x5555, 0x2AAA, 0x5555};
        unsigned char SDP_data[3] = {0xAA, 0x55, 0xA0};
        uint8_t byteaddr = 0;
        int i, j;

        for(i=0; i <= 2; i++) //SDP sequence
          write_byte(SDP_addr[i], SDP_data[i]);

      __delay_us(200); //min Tblco = 200 us
      __delay_ms(10); //max 10 ms Twc
     
      LATB &= ~0xFF; //clear address bits
      LATA &= ~0xFF; //clear address bits
      LATA |= (address & 0x00FF); //makes LATA 2 LSBs
      LATB |= (address & 0xFF00) >> 8; //shifts the 5 byte data right 2 bytes so only 3 MSBs are applied to LATB (but MSB is 0 so only applies 2 bytes)
      byteaddr |= (PORTA & 0x7F);
      TRISD &= ~0xFF; //make sure data are outputs
      LATC |= 0x0E; //CE OE WE all high
      __delay_us(1);
      while (byteaddr<128) {
        LATD &= ~0xFF; //set data to 0's
        LATA = (address & 0x000FF) + byteaddr;
        LATD |= data;
        LATC &= ~0x08; //CE low
        LATC &= ~0x02; //WE low
        __delay_us(1);
        LATC |= 0x02; //WE high
        __delay_us(1);
        byteaddr++;
      }
      __delay_us(200); //min Tblco = 200 us
      __delay_ms(10); //max 10 ms Twc
    }
     

    #6
    pcbbc
    Super Member
    • Total Posts : 1373
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: online
    Re: Interfacing Ext. EEPROM, Serial Terminal, PIC16F18877 2019/11/08 08:20:55 (permalink)
    +2 (2)
    What's with all the &= and |= on the LAT registers when setting values?  If you are writing the whole port...
      LATA = (address & 0x00FF);
      LATB = (address & 0xFF00) >> 8;

    Is a lot more efficient, easier to read and all that is necessary.
     
    Also:
    #define LATCbits.LATC3 CE
    #define LATCbits.LATC2 OE
    #define LATCbits.LATC1 WE

    And then more simply:
    uint8_t EEPROM_read(uint32_t address) {
      uint8_t data = 0;
      TRISD = 0xFF; //make data pins inputs
      CE = 1;
      OE = 1;
      WE = 1;
      address_set(address);
      CE = 0;
      OE = 0;
      data = PORTD;
      __delay_us(1);
      CE = 1;
      OE = 1;
      __delay_us(1);
      return data;
    }

    etc.
     
    Plus your addresses are 16 bits.  Why not use uint16_t?
    #7
    deelbug
    New Member
    • Total Posts : 5
    • Reward points : 0
    • Joined: 2019/04/19 06:42:57
    • Location: 0
    • Status: offline
    Re: Interfacing Ext. EEPROM, Serial Terminal, PIC16F18877 2019/11/08 11:40:19 (permalink)
    0
    Thanks for the response pcbbc. With your suggestions I've simplified both the write and read functions, and am now able to write any data value to a desired address. If I read the address I just wrote to, it shows the same value. Any subsequent read after alters the value stored, so I think I've narrowed it down to something about my read function causing inadvertent writes...
    Modified code: 
     
     
    uint8_t EEPROM_read(uint16_t address) {
      uint8_t data = 0;
      TRISD = 0xFF; //make data pins inputs
     
      //CE OE WE all high
      CE = 1;
      OE = 1;
      WE = 1;
      address_set(address);
      CE = 0; //CE low
      OE = 0; //OE low
      data = PORTD;
      __delay_us(1);
      CE = 1; //CE high
      OE = 1; //OE high
      __delay_us(1);
      return data;
    }
     
     
     
    void write_byte(uint16_t address, uint8_t data) {
      TRISD = 0x00; //make sure data are outputs
      //LATD = ~0xFF; //set data to 0's

      //CE OE WE all high
      CE = 1;
      OE = 1;
      WE = 1;

      __delay_us(1);
      address_set(address); //set to correct address
      LATD = data; //prepare data to be sent
      CE = 0; //CE low
      WE = 0; //WE low
      __delay_us(1);
      WE = 1; //WE high
      __delay_us(1);
      CE = 1;
    }
     
     
     
    void address_set (uint16_t address) {
      LATB = 0x00; //clear address bits
      LATA = 0x00; //clear address bits

      LATA = (address & 0x00FF); //makes LATA 2 LSBs
      LATB = (address & 0xFF00) >> 8; //shifts the 4 byte data right 2 bytes so only 2 MSBs are applied to LATB
    }
     

    test code in main to produce the following output

     
    for (x=0; x<15; x++) {
      write_byte(0x4305, 0xAB);  //write 0xAB to the address
      testdata = EEPROM_read(0x4305); //read what's at the address
      trans_UART(testdata);  //output to UART
      testdata = EEPROM_read(0x4305); //read the address again
      trans_UART(testdata);  //output to UART
    }
    for(x=0; x<20; x++) {
      testdata = EEPROM_read(0x4305); //recheck the address after
      trans_UART(testdata);  //output to UART
    }
     

     
    post edited by deelbug - 2019/11/08 11:42:18

    Attached Image(s)

    #8
    Jump to:
    © 2019 APG vNext Commercial Version 4.5