First, the set up: I’m using a PIC18F25K50 with HIDmaker for USB communications with a PC. I use Virtual Studio 2015, Visual Basic for the PC side programming. The PIC is part of a controller, while the PC software is a tuning “dashboard” of sorts. The idea is to have Programmable Parameters that can be tuned by the user with the PC. These Programmable Parameters are then stored in the EEPROM of the PIC (at least that’s the goal).


The USB part of things appears to be working just fine. In fact, the HIDmaker software has made that part of the design rather reliable. I pre-load values into the EEPROM addresses with PBP3 “DATA @add,val” commands. When I start the Dashboard for the first time after a “burn”, all of the data is as it should be, 25 times out of 25. As long as I don’t try to “Save Changes”, the values will come up the same every time.


However, if I change ANY value (there are over 200) and Save Changes, EVERYTHING goes wonky. After 5 days of frustration, I isolated a single variable to work with. It NEVER came back the same as I programmed it (from the PC side). Here is a brief of what I’ve tried:

  • When “Save Changes” command received by the PIC, GOSUB BurnToEeProm for all Programmable Parameters. This would be the most logical and simplistic approach. Values were corrupted.
  • Created a PC screen to monitor raw data before the VB software turns it into something meaningful to a tuner (human). This was to help spot when and where the variables got corrupted. Definitely on the PIC side.
  • Created a second set of variables; Var & OldVar. If Var <> OldVar Then : WRITE new value. It was hoped this would reduce latency.
  • Used “DEFINE WRITE_INT 1”, it dropped the USB every time I tried to Save Changes. This is a PBP3 command that disables Interrupts (GIE) while Writing to the EEPROM, then re-enables them when done.
  • Created a rotation variable Erot so that only one EEPROM WRITE was executed for each loop in the Main program. This was to prevent dropping the USB. USB still dropped out until I eliminated “DEFINE WRITE_INT 1”.
  • Increased the USB polling interval from every 10 ms to 50 ms.
  • Read through the PIC Data Sheet, created an ASM subroutine to burn to EEPROM using the exact syntax from the Data Sheet using the EECON1, EECON2, EEADD, and EEDATA Registers, got the same results.
  • Executed an EEPROM Save subroutine using PBP3 that mimicked the Data Sheet ASM sequence, same results.
  • Used both PBP3 & ASM subroutines with GOSUB and @ CALL, mostly the same results.
  • Placed the “long save” code (Data sheet style) in the regular subroutine (no GOSUB, no WRITE command).
  • Reviewed the software, both PIC & PC, numerous times to verify proper processing of the data. (I did find many bugs which I fixed, but haven’t been able to spot any lately.)
  • Reformatted parts of the software, both PIC & PC, to try to accomplish the same thing, but with a different approach (the PIC side is roughly outlined above and below).
  • Pulled my hair out & drank a screwdriver.
  • Lost sleep.


Here are a few things I have been able to confirm:
  • The EEPROMs are functional. Using “DATA @add,val” works every time.
  • The READ command is working, I get the same values every time.
  • The USB is working, I get the same values every time for fixed test values
  • The Save Changes command is sending the Program Counter (PC) to the proper subroutine (GOSUB SaveChanges works).
  • The value sent from the PC by USB is corrupted in the WRITE sequence on the PIC side.
  • The values written to the EEPROM are always wrong, usually have a pattern, but often the pattern is different from one time to the next.


Example 1:
Variable is CB, stored in EEPROM address 132. The value sent from the PC is 150d. Usually (but not always) the value returned is 148d.


Example 2:
A Byte array called Ramp[4]. Ramp starts at EEPROM address 128 (128 >> 131). Values sent from the PC are: 40,30,20,10. A few examples of the values returned are:


146,22,151,23
138,10,139,11
142,18,147,19


If there was consistency in the values returned, it might help me to isolate the issue & correct it. I’m at a total loss. I’ve been at this for several days (dozens of hours). Any help would be more appreciated than you could possibly know. Shown below are a couple renditions of the code used for saving to EEPROM:


Code:
   FOR b0 = 0 TO 63
        IF OldFX[b0] <> FX[b0] THEN		;Tried both “<>” and “!=“ variations
            WRITE b0, FX[b0]
            OldFX[b0] = FX[b0]
        ENDIF
    NEXT b0
; More variables in between
FOR b0 = 128 TO 131
       b1 = b0 - 128
       WRITE b0, Ramp[b1]
NEXT b0



Code:
IF Erot = 132 THEN			;Erot is my EEPROM Save Rotation variable
   IF OldCB != CB THEN
     WRITE 132, CB
     Erot = Erot + 1		;Move to the next variable on the next rotation
     OldCB = CB
  ENDIF
ENDIF



Code:
  EEADR = 132
  EEDATA = CB
  GOSUB Write_EE
  DO
      LOOP UNTIL EECON1.1 = 0	;EE_WR, Software Set, HardwareCleared Write Command
  EECON1.2 = 0              ;EE_WREN


Write_EE:
  ASM
    BANKSEL EECON1
    BCF     EECON1,EEPGD
    BCF     EECON1,CFGS
    BSF     EECON1,WREN
    BCF     INTCON,7
    MOVLW   0x55
    MOVWF   EECON2
    MOVLW   0xAA
    MOVWF   EECON2
    BSF     EECON1,WR
    BSF     INTCON,7
ENDASM    
RETURN