Variable changing mid-code in 16F883?


+ Reply to Thread
Results 1 to 4 of 4
  1. #1
    Join Date
    Jan 2009
    Location
    Huntsville, AL
    Posts
    36

    Default Variable changing mid-code in 16F883?

    I've been trying to figure out what's going on with this code, but for the life of me I can not. I've posted the whole code, but I believe the issue is in the loop titled "pulse_test". The variable "address" should increment by 16 every second time it goes through the loop, immediately after an EEPROM write. However it appears to be changing randomly during the program. I've added some debug statements and slowed down timer1 which is polled to space out measurements. After pressing STRT_BUT, some variables are set and it goes into "pulse_test". The output of the debug statements are shown below. As shown, address initially increments to 16 correctly but then is 13344 at the start of the next loop. I was sure there was a typo, but now wondering if it's something in the hardware I have set incorrectly? The loop is supposed to measure A, measure B every 8th loop, measure C, write to EEPROM every other loop, repeat. Any suggestions or thoughts are much appreciated!

    "THERMAL START
    A0-0-0
    B0-0-0
    C0-1-0
    A0-2-0
    C0-3-0
    D0-3-16
    A0-4-13344
    C0-5-13344
    A0-6-13344
    C0-7-13344
    D0-7-13360
    A0-8-13360
    C0-9-13360
    A0-10-13360
    C0-11-13360
    D0-11-13376
    A0-12-13376
    C0-13-13376
    A0-14-13376
    C0-15-13376
    D0-15-13392
    A0-1-13392
    C0-2-13392
    A0-3-13392
    C0-4-257
    A0-5-257
    C0-6-257
    A0-7-257
    C0-8-257"

    Code:
    #CONFIG
    __config _CONFIG1, _HS_OSC & _WDT_OFF & _MCLRE_OFF & _LVP_OFF & _CP_OFF
    __CONFIG _CONFIG2, _WRT_OFF & _BOR21V
    #ENDCONFIG
    
    'INTERRUPT VARS
    'wsave   var byte $70 system 'needed for interrupt
    'wsave   var byte    $70 SYSTEM
    'wsave1  VAR BYTE    $A0     SYSTEM      ' location for W if in bank1
    'wsave2  VAR BYTE    $120    SYSTEM      ' location for W if in bank2
    ibit    var bit
    icount  var byte
    'GENERAL VARS
    tempbit var bit
    wrbit   var bit
    tempvar var word
    tempvar2 var word
    tempbyt var byte
    n       var byte
    current var word
    voltage var word
    EDATA   var word[4]
    hbyte   var byte
    lbyte   var byte
    TIME1   var word
    TIME2   var word
    'HX711 specific
    HX711A  var Word
    'MAX6675 specific
    MXTemp  var word
    'ADS1115 specific
    adrs_w  var byte
    adrs_r  var byte
    config1 var byte
    config2 var byte
    CNFGREG VAR BYTE
    CNVRREG var byte
    'EEPROM specific
    wconfig	var byte
    rconfig	var byte
    address var word
    
    ABRT_BUT var PORTA.1
    STRT_BUT VAR PORTA.0
    DIAG_BUT VAR PORTE.3
    LED      var portA.2
    Hdta     var PORTA.3  'HX711 pins
    Hclk     var PORTA.4  'HX711 pins
    PIN_OUT  var PORTC.3  'serial out pin
    PIN_IN   var PORTC.2  'serial in pin
    ADC_CLK  var PORTC.1  'ADC clock pin
    ADC_DAT  var PORTC.0  'ADC data pin
    ADC_RDY  var PORTA.5  'ADC alert/ready pin
    EE_CLK   var PORTC.5  'I2C EEPROM clock pin
    EE_DAT   var PORTC.4  'I2C EEPROM data pin
    MXDATA   var PORTB.5  'MAX6675 DATA pin (was HX711 pin)
    MXCLK    var PORTB.7  'MAX6675 CLOCK pin (was HX711 pin)
    MXCS     var PORTB.6  'MAX6675 Chip Select
    MOT_PWM  var PORTB.4  'MOTOR PWM OUTPUT
    
    'INCLUDE "DT_INTS-14.bas" ' Base Interrupt System
    'INCLUDE "ReEnterPBP.bas" ' Include if using PBP interrupts
    
    T1CON = %00110000 ' Prescaler = 1:1,  Timer off
    
    ANSEL=%00000000      'all analogue ports to digital
    ANSELH=%00000000     'all analogue ports to digital
    ADCON0.0=0           'disable ADC
    CM1CON0=%00000000    'disable COMPARATOR 1
    CM2CON0=%00000000    'disable COMPARATOR 2
    SSPCON=%00000000     'disable SERIAL PORT
    RCSTA=%00000000      'disable SERIAL PORT
    PCON=%00000000       'disable BOR and ULPW
    
    TRISA=%00101011      '(0=output, 1=input)
    TRISB=%00100001      '(0=output, 1=input)
    TRISC=%00000000      '(0=output, 1=input) 
    TRISE=%00001000      '(0=output, 1=input) 
    
    OPTION_REG=%11000101
    
    define OSC 20
    
    low MOT_PWM
    low Hclk
    HIGH MXCS
    HIGH EE_CLK
    
    for n = 0 to 9
    high LED
    pause 100
    low LED
    pause 100
    next n
    
    'setup EEPROM
    wconfig=%10100000
    rconfig=%10100001
    
    'setup ADC configuration
    adrs_w=$48
    adrs_w=adrs_w<<1 ' Add read/write bit at end (0=write)
    adrs_r=adrs_w+1  ' Add read/write bit at end (1=read)
    CNFGREG=$01      ' Address of the configuration register
    CNVRREG=$00      ' Address of the conversion register
    
    waitforstart:
    if STRT_BUT=0 then waitforstart
    
    config1=%11010001  ' A+ = A1, A- = GND
    config2=%11100011
    I2CWRITE ADC_DAT,ADC_CLK,adrs_w,CNFGREG,[config1,config2] 'set config register
    ibit=0
    address=0
    icount=0
    pause 2
    TMR1H=0
    TMR1L=0
    
    tempbyt=0
    
    serout2 PIN_OUT,32,["THERMAL START",13,10] '19200bps
    high LED
    
    @ bsf     T1CON, TMR1ON   ' Start timer
    '@ INT_ENABLE TMR1_INT ; enable TMR1 interrupts
    pulse_test:
    TIME2.highbyte=tempbyt
    I2CWRITE ADC_DAT,ADC_CLK,adrs_w,[CNVRREG] 'point to conversion register
    I2CREAD ADC_DAT,ADC_CLK,adrs_r,[hbyte,lbyte] 'read voltage from ACS712 (current sensor) via ADC
    current.highbyte=hbyte
    current.lowbyte=lbyte 
    EDATA[icount]=current   
    'switch ADC to channel A2 (batt voltage)
    config1=%11100001 'A+ = A2, A- = GND
    I2CWRITE ADC_DAT,ADC_CLK,adrs_w,CNFGREG,[config1,config2] 'write config register channel
    serout2 PIN_OUT,32,["A",dec ibit,"-",dec icount,"-",dec address,13,10]   
    if icount=0 then
    LOW MXCS
    shiftin MXDATA,MXCLK,0,[MXTemp\16]   'read the data to MXTemp
    HIGH MXCS
    serout2 PIN_OUT,32,["B",dec ibit,"-",dec icount,"-",dec address,13,10]  
    endif
    
    hold1:
    tempbyt=TMR1H
    if tempbyt<>128 then hold1
    TIME2.LOWbyte=tempbyt
    icount=icount+1
    I2CWRITE ADC_DAT,ADC_CLK,adrs_w,[CNVRREG] 'point to conversion register
    I2CREAD ADC_DAT,ADC_CLK,adrs_r,[hbyte,lbyte] 'read batt voltage through 1/2 voltage divider via ADC
    voltage.highbyte=hbyte
    voltage.lowbyte=lbyte
    EDATA[icount]=voltage 
    'switch ADC to channel A1 (current)
    config1=%11010001  ' A+ = A1, A- = GND
    I2CWRITE ADC_DAT,ADC_CLK,adrs_w,CNFGREG,[config1,config2] 'write config register channel
    tempbyt=icount & %00000011
    serout2 PIN_OUT,32,["C",dec ibit,"-",dec icount,"-",dec address,13,10] 
    if tempbyt=3 THEN
    I2CWRITE EE_DAT,EE_CLK,wconfig,address,[EDATA[0],EDATA[1],MXTemp,TIME1,EDATA[2],EDATA[3],MXTemp,TIME2]
    address=address+16
    serout2 PIN_OUT,32,["D",dec ibit,"-",dec icount,"-",dec address,13,10] 
    toggle LED
    endIF
    icount.bit4=0 'rollover from 15 to 0
    if address=1600 then goto readout
    TIME1=TIME2
    hold2:
    tempbyt=TMR1H
    if tempbyt<>128 then hold2
    icount=icount+1
    goto pulse_test
    
    readout:
    '@ INT_DISABLE TMR1_INT ; enable TMR1 interrupts
    low MOT_PWM
    serout2 PIN_OUT,32,["READOUT",13,10] 
    low LED
    for tempvar=0 to 105
    address=tempvar<<3
    I2CREAD EE_DAT,EE_CLK,rconfig,address,[current,voltage,MXTemp,TIME1]
    serout2 PIN_OUT,32,[dec tempvar," ",dec current," ",dec voltage," ",MXTemp," ",TIME1.highbyte," ",TIME1.lowbyte,13,10]              
    next tempvar
    goto waitforstart
    
    END

  2. #2
    Join Date
    May 2013
    Location
    australia
    Posts
    2,445


    Did you find this post helpful? Yes | No

    Default Re: Variable changing mid-code in 16F883?

    for tempvar=0 to 105
    address=tempvar<<3
    that looked wrong at first if address started a 1600 but it doesn't.
    perhaps address gets corrupted every time readout is run,
    spaghetti code like that is hard to unravel
    Last edited by richard; - 4th September 2024 at 05:59.
    Warning I'm not a teacher

  3. #3
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,554


    Did you find this post helpful? Yes | No

    Default Re: Variable changing mid-code in 16F883?

    I'm not saying this is related to your problem but here:
    Code:
    hold1:
      tempbyt=TMR1H
      if tempbyt<>128 then hold1
    This will "hold" until TMR1H is 128 and then countinue.
    But for how long is TMR1H 128? Are you sure it's not (still) 128 the next time you check?

    I would rewrite this.
    * For pacing the loop, poll the TMR1 interrupt flag.
    * Create a short subroutine for each "task". MeasureA, MeasureB, MeasureC, WriteEEPROM and so on.
    * Have a LoopCount variable that counts from 0 to whatever.
    * Use a Select Case block to execute whatever tasks are needed at each increment of the loop.

    Crude example:
    Code:
    TMR1IF VAR PIR1.0
    LoopCount VAR BYTE
    
    TMR1IF = 0
    T1CON = %00110001 ' Prescaler = 1:8,  Timer ON
    
    Main:
      IF TMR1IF=0 THEN Main    ' Wait for TMR1 roll over
    
      TMR1IF=0		   ' Reset interrupt flag.
    
      Select Case LoopCount
        Case 0
          GOSUB MeasureA
          GOSUB MeasureB
    
        Case 1
         GOSUB MeasureA
         GOSUB MeasureC
    
        Case 2
          GOSUB MeasureA
          GOSUB MeasureB
          GOSUB MeasureC
    
        Case 3
          GOSUB MeasureB
          GOSUB MeasureC
          GOSUB WriteEEPROM
      END SELECT
    
      LoopCount = LoopCount + 1
      IF LoopCount = 4 THEN LoopCount = 0
    
    Goto Main
    
    
    MeasureA:
      ' Do stuff
    RETURN
    
    MeasureB:
      ' Do Stuff
    RETURN
    
    MeasureC:
      ' Do Stuff
    RETURN
    
    WriteEEPROM:
      ' Do Stuff
    RETURN

  4. #4
    Join Date
    May 2013
    Location
    australia
    Posts
    2,445


    Did you find this post helpful? Yes | No

    Default Re: Variable changing mid-code in 16F883?

    i had a slightly different take but am amazed at the similarity

    Code:
    #CONFIG
        __config _CONFIG1, _HS_OSC & _WDT_OFF & _MCLRE_OFF & _LVP_OFF & _CP_OFF
        __CONFIG _CONFIG2, _WRT_OFF & _BOR21V
    #ENDCONFIG
    
    
    DEFINE INTHAND   ticker  
    
    
    
    
    
    
    ANSEL=0      'all analogue ports to digital
    ANSELH=0     'all analogue ports to digital
    
    
    
    
    TRISA=%00101011      '(0=output, 1=input)
    TRISB=%00100001      '(0=output, 1=input)
    TRISC=%00000000      '(0=output, 1=input) 
    TRISE=%00001000      '(0=output, 1=input) 
    
    
    OPTION_REG=%11000101
    PIN_OUT       var PORTC.3  'serial out pin
    LED           var portA.2
    wsave         var byte    $70 SYSTEM
    ssave         var byte    SYSTEM
    psave         var byte    SYSTEM
    taskflag      var byte
    taskswitch    var byte
    ro_counter    var byte
    ibit          var byte
    address       var word
    icount        var word
    
    
    define OSC 20
    
    
    intcon =$c0
    pir1.0=0
    pie1.0=1
    
    
    serout2 PIN_OUT,32,["THERMAL START",13,10] '19200bps
    T1CON=$31
    
    
    
    
    main:
        if taskflag then
              taskflag = 0
              taskswitch = taskswitch + 1
              if taskswitch == 4 then  taskswitch = 0
              select case taskswitch 
                  CASE 0
                    gosub task0
                    serout2 PIN_OUT,32,["A",dec ibit,"-",dec icount,"-",dec address,13,10] 
                    serout2 PIN_OUT,32,["B",dec ibit,"-",dec icount,"-",dec address,13,10]  
                  case  1
                    gosub task1
                    icount=icount+1
                    serout2 PIN_OUT,32,["C",dec ibit,"-",dec icount,"-",dec address,13,10] 
                    address=address+16
                    serout2 PIN_OUT,32,["D",dec ibit,"-",dec icount,"-",dec address,13,10] 
                  case  2 
                    gosub task2
                    ro_counter =ro_counter +1
                    if ro_counter == 16 then
                        serout2 PIN_OUT,32,["READOUT",13,10] 
                        ro_counter =0
                    endif
                  case  3
                    gosub task3 
                    
              end select    
        endif
    goto main
    
    
    task0:
    'do voltage stuff
    return
    
    
    task1:
    'do current stuff
    return
    
    
    task2:
    'do other stuff
    return
    
    
    task3:
         LED = ! led 
    return
    
    
    
    
    END
    
    
    asm    
    ticker      ;tmr1 isr
        banksel  _taskflag
        bsf _taskflag,0
        banksel PIR1
        bcf PIR1,0
        movf psave,W ; restore PCLATH
        movwf PCLATH
        swapf ssave,W ; restore STATUS
        movwf STATUS
        swapf wsave,F ; restore W (swap avoids changing STATUS)
        swapf wsave,W 
        RETFIE    
    endasm
    Warning I'm not a teacher

Similar Threads

  1. Change variable increment/decrement into mid-loop?
    By CuriousOne in forum mel PIC BASIC Pro
    Replies: 4
    Last Post: - 30th January 2021, 08:38
  2. 16F883 Code Verify Problem
    By munromh in forum mel PIC BASIC Pro
    Replies: 4
    Last Post: - 19th February 2009, 11:47
  3. changing code from 16F to 18F microprocessor
    By SCC_699 in forum mel PIC BASIC Pro
    Replies: 13
    Last Post: - 14th May 2008, 13:27
  4. Changing Swordfish code to PBP
    By Ron Marcus in forum mel PIC BASIC Pro
    Replies: 3
    Last Post: - 29th April 2008, 01:28
  5. Changing position of program code
    By aerostar in forum mel PIC BASIC Pro
    Replies: 17
    Last Post: - 15th December 2006, 07:34

Members who have read this thread : 9

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts