Electronic – Problem Controlling Digital Potentiometer with Micro

assemblydigital-logicmicrocontrollerpicpotentiometer

I am trying to control a digital potentiometer with a PIC18F14K50 and am having a random problem (potentiometer not remembering correct value) when I power off then back on. The X9313 datasheet states that to initiate a save of the digital pots wiper position into its own internal EEPROM the CS line must be taken from low to high while the INC line is pulled high. the INC line is on RC6 and the CS line is on RA5(CS is pulled to 5V thru a 10k to avoid unknown conditions on power up this was a late modification and is not shown on the schematic).

The problem is that when the volume is changed and the power is turned off and then back on the digital pot comes back on and has decremented one wiper position. This only happens when the volume is changed and then power is cycled the FIRST time. For example if I set the pot in the middle giving me an output of 1V at the wiper(using false numbers for simplicity) and each step is 50 mV when I cycle power the output at the wiper will be 950mV when I reapply power. If I leave the volume there and do not change it I can cycle power as many times as I want and it will always remember the 950 mV. But if I change it again to say 500 mV and cycle power, on the next power up I will have 450 mV at the wiper and that value will be remembered for as many power cycles as I have tested. It seems to be a walking wiper issue as discussed in this intersil app note but it seems strange that it only happens the first power cycle after the value has changed.
I added small portions of my code. the config bits and the portion where I am changing the value of the digital pot. If anyone wants to see the rest of the code let me know and I can get it to you. Can anyone see a problem with my code or the setup that would be causing this issue? I appreciate any input I can get.

Partial; Schematic

    CONFIG  CPUDIV = NOCLKDIV   ; No CPU System Clock divide
    CONFIG  USBDIV = OFF        ; USB Clock comes directly from the OSC1/OSC2 oscillator block; no divide
    CONFIG  FOSC = IRC          ; Internal RC oscillator, CLKOUT function on OSC2
    CONFIG  PLLEN = OFF         ; Oscillator multiplied by 4
    CONFIG  PCLKEN = ON         ; Primary clock enabled
    CONFIG  FCMEN = OFF         ; Fail-Safe Clock Monitor disabled
    CONFIG  IESO = OFF          ; Oscillator Switchover mode disabled
    CONFIG  PWRTEN = ON         ; PWRT enabled
    CONFIG  BOREN = ON          ; Brown-out Reset enabled in hardware only (SBOREN is disabled)
    CONFIG  BORV = 27           ; VBOR set to 2.7 V nominal
    CONFIG  WDTEN = OFF         ; WDT is controlled by SWDTEN bit of the WDTCON register
    CONFIG  WDTPS = 1           ; 1:1
    CONFIG  MCLRE = ON          ; MCLR pin enabled, RE3 input pin disabled
    CONFIG  HFOFST = OFF        ; The system clock is held off until the HFINTOSC is stable
    CONFIG  STVREN = OFF        ; Stack full/underflow will not cause Reset
    CONFIG  LVP = OFF           ; Single-Supply ICSP disabled
    CONFIG  BBSIZ = ON          ; 2kW boot block size
    CONFIG  XINST = OFF         ; Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
    CONFIG  CP0 = OFF           ; Block 0 not code-protected
    CONFIG  CP1 = OFF           ; Block 1 not code-protected
    CONFIG  CPB = OFF           ; Boot block not code-protected
    CONFIG  CPD = OFF           ; Data EEPROM not code-protected
    CONFIG  WRT0 = OFF          ; Block 0 not write-protected
    CONFIG  WRT1 = OFF          ; Block 1 not write-protected
    CONFIG  WRTB = OFF          ; Boot block not write-protected
    CONFIG  WRTC = OFF          ; Configuration registers not write-protected
    CONFIG  WRTD = OFF          ; Data EEPROM not write-protected
    CONFIG  EBTR0 = OFF         ; Block 0 not protected from table reads executed in other blocks
    CONFIG  EBTR1 = OFF         ; Block 1 not protected from table reads executed in other blocks
    CONFIG  EBTRB = OFF         ; Boot block not protected from table reads executed in other blocks


    DIR_CCW 
;
        BSF         UPDOWN          ;Set up / down bit
        BCF         CS             ;pulse CS line
        NOP
        BCF         INC
        NOP
        NOP
        BSF         INC
        NOP
;
        MOVLW       0x64            ;100ms delay
        MOVWF       LOOP_COUNT
DLOOP   CALL        DELAY_ONE_MS
        DECFSZ      LOOP_COUNT
        GOTO        DLOOP
;
        BSF         CS
        NOP
        BCF         ENCDR_FLG, 1
        RETURN
;*********************************************************
DIR_CW  
;
        BCF         UPDOWN         ;Clear up / down bit
        BCF         CS             ;pulse CS line
        NOP
        BCF         INC
        NOP
        NOP
        BSF         INC
        NOP
;
        MOVLW       0x64            ;100ms delay
        MOVWF       LOOP_COUNT
DLOOP1  CALL        DELAY_ONE_MS
        DECFSZ      LOOP_COUNT
        GOTO        DLOOP1
;
        BSF         CS
        NOP
        BCF         ENCDR_FLG, 0
        RETURN

Best Answer

I finally found the problem! While initializing the ports on the PIC the CS and INC lines on the digital pot were momentarily being cleared long enough to initiate a decrement command but not long enough for a store command. The correct value was being stored and the device would decrement that correct stored value each power cycle giving the illusion that a new value had been stored. By setting the CS and INC lines high before port initialization (didn't know I could do that even) I avoided the unwanted decrement.

        BSF     CS              ;   SET CS
        BSF     INC             ;   SET INC
;
        MOVLW   0X1F            ;
        MOVWF   TRISC           ;
        MOVLW   0x80
        MOVWF   TRISB           ;
        CLRF    TRISA           ;
        CLRF    ANSEL           ;   CONFIGURE AS DIGITAL IO
        CLRF    ANSELH          ;
        CLRF    PORTA           ;   INITIALIZE PORT A
        CLRF    PORTB           ;   INITIALIZE PORT B
        CLRF    PORTC           ;   INITIALIZE PORT C