0
\$\begingroup\$

Disclaimer, i am more or a hardware designer and not so much a coder, i can code but i'm not the most proficient at it.

I have a project I'm working on that has a portion of the code that appears to be preventing the Auto-generated runtime startup from MPlab's XC8 compiler from ever executing.

The debugger enters the startup code and freezes there.

The only way I can get the debugger to actually run the code on the chip is for me to comment out either low limit while loop or the high limit while loop in the attached code.

This is not the complete code for the project but it is the only code that seems to be effecting the debugger from running.

The code appears to run fine directly from the PIC but just not while debugging from the laptop.

Any suggestions as to why that would be?

As well the last 2 equations will not allow the debugger to run from the PIC either.

I am trying to debug from a PICkit3 using MPlab.

the Calibrate function is where the issue is.

the purpose of the calibrate function is to take the input of the A/D and have the PIC learn what the MAX and MIN inputs will be, the device feeding the PIC has a big variance from part to part and the units will not display proper readings without it.

the overall program is supposed to display a value of 0-99 depending on the reading of the ADC and the values saved for the high and low reading in the EEPROM (derived from the Calibration function)

if i hard code in the values for 1 unit without using the calibration function everything works but i need the calibration function to work to make this item producible.

Edit: Please note the variables are declared in a separate file but I included them below for clarity on they type of variables I am using. Edit2: Added full code

// PIC16F88 Configuration Bit Settings

// 'C' source line config statements

// CONFIG1
#pragma config FOSC = INTOSCIO  // Oscillator Selection bits (INTRC oscillator; port I/O function on both RA6/OSC2/CLKO pin and RA7/OSC1/CLKI pin)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF       // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR)
#pragma config BOREN = OFF      // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP = OFF         // Low-Voltage Programming Enable bit (RB3/PGM pin has PGM function, Low-Voltage Programming enabled)
#pragma config CPD = OFF        // Data EE Memory Code Protection bit (Code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off)
#pragma config CCPMX = RB0      // CCP1 Pin Selection bit (CCP1 function on RB0)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

// CONFIG2
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF       // Internal External Switchover bit (Internal External Switchover mode disabled)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <htc.h>
#include <xc.h>
#include <math.h>
#include "HW.h"
#include "Int.h"
#include "Port.h"


#define CAL     PORTBbits.RB4//calibration bit that would be set at startup
#define CAL2    PORTBbits.RB5//calibration to initatiate calibration when unit is ready
#define SIGNAL  PORTAbits.RA7//external signal showing that there is a signal that we want to look at on the ADC

#ifndef TRUE
#define TRUE            1
#endif

#ifndef FALSE
#define FALSE           0
#endif

void main (void);
//void ad(void);
extern unsigned int signal;
unsigned int ADC_Read(void);
void ADC_Init();
void DISPLAY(void);
void UART_send_string();
void UART_send_char();
void write(void);
void Calibrate (void);
void MemReadConfig(void);

int ROMRead =0;

unsigned int TIMER = 0x00;
int MEM;
int FINALSAMPLE =0;
int SAMPLE_DIFF = 40;
unsigned int HIGH_SAMPLE    = 285;//initial value but calibration is needed for accurate results
unsigned int LOW_SAMPLE     = 245;//initial value but calibration is needed for accurate results
float SIG_DIVISOR           = 4;//initial value but calibration is needed for accurate results

unsigned int SIGNALIN= 0;
unsigned int NEW_SIGNALIN  = 0x00;
int PERCENT = 0x00;
int RESET = 0x00;
int RESET2 = 0x00;
int SAMPLE1 = 0x00; 
int SAMPLE2 = 0x00;
int POWERUP =0;
int UPPER = 0x00;
int LOWER = 0x00;
int SAMPLEDIV = 100;
unsigned int GETSIGNAL;
#define _XTAL_FREQ 8000000

void main(void)
{
    OSCCON  = 0b01111100;
    OSCTUNE = 0b00011111;
    TRISB   = 0b00110000; //was 0x10 //1 is input 0 is output
    TRISA   = 0b10001000; //SET PORTA BITS 0,1,& 5 AS OUTPUTS// WAS 0xDC
    PORTA   =0x00;  
    __delay_us(150);
    ADC_Init();                 //Initialize ADC
    MemReadConfig();// REad calibration b=values stored IN EEPROM if any exist
    if (CAL == 0)//Check to see if the calibration port is set at powerup
    {
        MEM = TRUE;
        Calibrate();
        write();//save values from the calibration procedure into EEPROM
        UPPER =0;
        LOWER =0;
        DISPLAY();
        __delay_ms(255);
        DISPLAY();
        __delay_ms(255);
        DISPLAY();
        __delay_ms(255);
        DISPLAY();      
    }
     while(1)                       //Infinite Loop
    {
        DISPLAY();
        SAMPLE1++;
        if (SAMPLE1 == 32)          // RETURN EVERY 32nd RESULT
        {   SAMPLE1=0;      
            SAMPLE2++;
            DISPLAY();
            __delay_ms(2);
            DISPLAY();
            GETSIGNAL = ADC_Read();
            if ((GETSIGNAL > (HIGH_SAMPLE*1.5))|| (GETSIGNAL < (LOW_SAMPLE/1.15)))//IF THE SIGNAL IS SHOWING VERY HIGH OR VERY LOW IGNORE THE READING AND DIVIDE THE AVERAGE BY 1 LESS
            {
                GETSIGNAL = 0;
                SAMPLEDIV--;                
            }
            SIGNALIN = GETSIGNAL + SIGNALIN;        //Read Analog Channel and add it to the running total before it gets averaged later
            DISPLAY();
            if (SAMPLE2 == 100)//once 100 samples have been collected average them together here
            {   SAMPLE2 =0;
                if (SAMPLEDIV !=0 ) //avoid divide by 0 errors
                {
                    SIGNALIN = SIGNALIN/SAMPLEDIV; //take the total of all the samples and average them by the number of valid results
                }
                else if ((SAMPLEDIV == 0))
                {
                    SIGNALIN =0;
                }
                SAMPLEDIV = 100;
                DISPLAY();
                if (((SIGNALIN >= (LOW_SAMPLE-10))&& (SIGNAL==TRUE)))// if we have an active signal coming in and the ADC value is high enough display the average of the samples taken
                {
                    DISPLAY();
                    PERCENT=((SIGNALIN-LOW_SAMPLE)/(SIG_DIVISOR))*10;//the current sample minus LOW_SAMPLE(which is our zero point) divided by our calculated divisor to get a value of 1-99
                    SIGNALIN =0;


                    if (PERCENT < 1)
                    {
                        UPPER = 0;
                        LOWER = 0;
                    }
                    else if (PERCENT >99)
                    {
                        UPPER = 9;
                        LOWER = 9;
                    }
                    else
                    {                   
                        UPPER = PERCENT/10;//get upper digit of 2 digit number to display on 7seg display
                        LOWER = PERCENT-(UPPER*10);//get lower digit of 2 digit number to display on 7seg display
                        DISPLAY();
                    }
                    DISPLAY();
                }
                else if (((SIGNALIN < (LOW_SAMPLE-10)) || (SIGNAL==FALSE)))//if there is not a valid signal to look at or the average is less than zero display 00
                {
                    PERCENT = 0;
                    UPPER = 0;
                    LOWER = 0;
                    DISPLAY();
                    SIGNALIN = 0;
                }
                DISPLAY();
                //SIGNALIN = 0x00;
            }//end of SAMPLE2 BRACKET
        }//end of SAMPLE1 BRACKET
    }//end of while loop
}//end of main
void DISPLAY(void)
{
    PORTB = UPPER;              //set UPPER DIGIT for BCD display
    PORTAbits.RA0 = 1;              //power on the UPPER DIGIT
    __delay_us(50);                 // display digit for 50us
    PORTAbits.RA0 = 0;              //turn display off
    PORTAbits.RA1 = 0;
    PORTB = LOWER;              //set UPPER DIGIT for BCD display
    PORTAbits.RA1 = 1;              //power on the UPPER DIGIT
    __delay_us(50);                 // display digit for 50us
    PORTAbits.RA0 = 0;              //turn display off
    PORTAbits.RA1 = 0;
}
void ADC_Init()
{
    ANSEL = 0b00001000;                     //SET AN3 AN ANALOG INPUT
    ADCON0 = 0b10011001;               //Turn ON ADC and Clock Selection
    ADCON1 = 0b11000000;               //Reference Voltages
}
//*****************************************************************************


void Calibrate(void)
{
    TIMER = 21480;
//COMMENT OUT HERE FOR DEBUGGING

    while (CAL2 == 1)
    {
        UPPER = 0x0C;
        LOWER = 0x0C;
        DISPLAY();
    }   

    while (TIMER>1)//High limit while loop
    {
        TIMER--;
        //NEW_SIGNALIN = ADC_Read();        //Read Analog Channel
        SAMPLE1++;
        if ((SAMPLE1 == 32) && (FINALSAMPLE == 0))          // RETURN EVERY 125TH RESULT
        {   SAMPLE1=0;      
            SAMPLE2++;
            __delay_ms(2);
            GETSIGNAL = ADC_Read(); //Read Analog Channel
            if ((GETSIGNAL > 330) || (GETSIGNAL < 200))//IF THE SIGNAL IS SHOWING VERY HIGH OR VERY LOW IGNORE THE READING AND DIVIDE THE AVERAGE BY 1 LESS
            {
                GETSIGNAL = 0;
                SAMPLEDIV--;    
            }
            SIGNALIN = GETSIGNAL + SIGNALIN; //ADD THE LAST READING TO THE SIGNAL SAMPLES
            DISPLAY();
            if (SAMPLE2 == 100)
            {   SAMPLE2 =0;
                SIGNALIN = SIGNALIN/SAMPLEDIV; //AVERAGE ALL THE READINGS TOGETHER
                SAMPLEDIV = 100;
                DISPLAY();
                FINALSAMPLE = 1;// DONT TAKE ANY MORE SAMPLES AND ALLOW THE TIMER TO EXPIRE WITHOUT ENTERING THE LOOP AGAIN
            }//end of SAMPLE2 BRACKET
        }//end of SAMPLE1 BRACKET
        UPPER = 0x0C;//print u to the Display digit
        LOWER = 0x0C;//print u to the Display digit
        DISPLAY();
    }
    HIGH_SAMPLE = SIGNALIN;// save the value found for the high ADC result (99 point)
    FINALSAMPLE = 0;
    SIGNALIN =0;
    TIMER = 21480;  
    SAMPLE1 = 0;
    SAMPLE2 = 0;    
//COMMENT OUT HERE FOR DEBUGGING

    while (CAL2 == 1)
    {
        UPPER = 0x01;
        LOWER = 0x00;
        DISPLAY();
    }
    while (TIMER>1)//low limit while loop
    {
        TIMER--;
        //NEW_SIGNALIN = ADC_Read();        //Read Analog Channel
        SAMPLE1++;
        DISPLAY();
        if ((SAMPLE1 == 32) && (FINALSAMPLE ==0))           // RETURN EVERY 125TH RESULT
        {   SAMPLE1=0;      
            SAMPLE2++;
            GETSIGNAL = ADC_Read(); //Read Analog Channel
            if ((GETSIGNAL > 330) || (GETSIGNAL < 200))//IF THE SIGNAL IS SHOWING VERY HIGH OR VERY LOW IGNORE THE READING AND DIVIDE THE AVERAGE BY 1 LESS 
            {
                GETSIGNAL = 0;
                SAMPLEDIV--;
            }
            SIGNALIN = GETSIGNAL + SIGNALIN; //ADD THE LAST READING TO THE SIGNAL SAMPLES
            DISPLAY();
            if (SAMPLE2 == 100)
            {   SAMPLE2 =0;
                SIGNALIN = SIGNALIN/SAMPLEDIV; //AVERAGE ALL THE READINGS TOGETHER
                SAMPLEDIV = 100;
                DISPLAY();
                FINALSAMPLE = 1;// DONT TAKE ANY MORE SAMPLES AND ALLOW THE TIMER TO EXPIRE WITHOUT ENTERING THE LOOP AGAIN
            }//end of SAMPLE2 BRACKET
        }//end of SAMPLE1 BRACKET
        UPPER = 0x01;//print 1 to the Display digit
        LOWER = 0x00;//print 0 to the Display digit
        DISPLAY();
    }
    LOW_SAMPLE = SIGNALIN;// save the value found for the low ADC result (zero point)
    SIGNALIN =0;
    SAMPLE1 = 0;
    SAMPLE2 = 0;
    SAMPLE_DIFF= HIGH_SAMPLE-LOW_SAMPLE;//comment out for debugging
    SIG_DIVISOR = SAMPLE_DIFF*.10;//comment out for debugging result doesnt seem to be calculating correctly and wont allow debugger to launch

}
//=============================================================================
unsigned int ADC_Read(void)
{
  GO_DONE = 1;                //Initializes A/D conversion
   __delay_us(40);               //Acquisition time to charge hold capacitor
  while(GO_DONE==1);   
    { return ((unsigned int)ADRESH << 8) + ADRESL; //Return result
    }
}
//=============================================================================
int read_eeprom(int adr)
{
    EEADR=adr;
    EEPGD= 0; 
    //CFGS = 0;
    RD=1; // set the read bit   
    return(EEDATA);
}
//=============================================================================
void write_eeprom(int adr, int data)
{   
    GIE=0;
    PIR2bits.EEIF=0;
    EEADR = adr;
    EEDATA = data;
    EECON1bits.EEPGD= 0;
//  EECON1bits.CFGS = 0;
    EECON1bits.WREN = 1;  // write enable
    EECON2 = 0x55; // protection sequence
    EECON2 = 0xaa;

    EECON1bits.WR = 1;  // begin programming sequnce
    while(PIR2bits.EEIF==0);    
    EECON1bits.WREN = 0;  // disable write enable
    PIR2bits.EEIF=0;    
    GIE=1;
}
//=============================================================================
void MemReadConfig(void)
{
    ROMRead=read_eeprom(0x01);
    if(ROMRead==0x0F)//see if EEPROM has been written previously, if not do nothing
    {
        LOW_SAMPLE      =read_eeprom(0x02);
        HIGH_SAMPLE     =read_eeprom(0x03);
        SIG_DIVISOR         =((read_eeprom(0x04))/10);  
    }
    else
    {
        NOP();
    }
}
//*****************************************************************************
void write(void)
{           write_eeprom(0x01,0x0F);    
            write_eeprom(0x02, LOW_SAMPLE);
            write_eeprom(0x03, HIGH_SAMPLE);
            write_eeprom(0x04, (SIG_DIVISOR*10));
            MEM = FALSE;
}
\$\endgroup\$
  • \$\begingroup\$ Have you stepped through the code line by line to see where exactly the hang up is located? \$\endgroup\$ – vini_i Feb 18 at 20:54
  • \$\begingroup\$ When you make an example, like the one you posted, it can help everyone if you create a complete program that actually builds. This helps in several ways. 1) It gets you to focus on where you think the problem is. 2) It helps others to check that you have not missed a small but important detail. 3) It can help you see how to take your design choices and implement them with clarity. \$\endgroup\$ – Dan1138 Feb 18 at 21:14
  • \$\begingroup\$ The code posted has no comments to suggest what you intend the void Calibrate(void) function to accomplish. A clear description of how this method is supposed to work would be good. There are many ways to calibrate ADC inputs. Perhaps someone could suggest something simpler. \$\endgroup\$ – Dan1138 Feb 18 at 21:18
  • \$\begingroup\$ @Dan1138 full code posted to clear up any ambiguity. as wall as a explanation of the function \$\endgroup\$ – Chris Feb 18 at 22:03
  • \$\begingroup\$ @vini_i yes but it freezes up right away in the startup script \$\endgroup\$ – Chris Feb 18 at 22:06
0
\$\begingroup\$

This can be for a few reasons, the first one that came to my mind was that delays are often behaving differently then they would on a PIC, further it could be something with the tool you use to debug, could you please tell us what you are using? And I think there is some essential code missing in this question, i.e. as far as I know there is no DISPLAY() function built in in any compiler.

\$\endgroup\$
  • \$\begingroup\$ i am debugging with the PICkit3 and MPlab. the DISPLAY() function is written elsewhere in my code to display 2 digits on 7 segment displays \$\endgroup\$ – Chris Feb 18 at 20:57
  • \$\begingroup\$ Could you show it please, as for the PICkit3, I don't have any experience with it, I'm used to use the PICkit2. Also expect a much longer delay if you use the debug mode, sometimes 1 s becomes 1-2 min, try reducing that delay for the debugging. Further could it be that you use a pin that is connected to the PICkit? \$\endgroup\$ – Tim Jager Feb 18 at 21:03
  • \$\begingroup\$ i dont think that it is the delay because it works as long as one of the while loops is commented out and it cannot go from one while loop to the other until a button is pressed. the PICkit 3 is very similar to the 2 but i do not know the specific differences \$\endgroup\$ – Chris Feb 18 at 21:18
  • \$\begingroup\$ also i do not have any of the pins that are used for programming setup as IO, i always do everything i can to not use them for IO this way i can do the in circuit debugging \$\endgroup\$ – Chris Feb 18 at 21:20
  • \$\begingroup\$ If there is no good answer I might be able to do some debugging in the electronics lab at school, were I think we have a PICkit3, but no guarantees. \$\endgroup\$ – Tim Jager Feb 18 at 21:28
0
\$\begingroup\$

I think that I may have an answer to your posted problem of In-Circuit-Debug not working.

The ICD tool needs to connect to the PIC16F88 target through the PGC/PGD pins. If the user application sets PORTB pins RB6 & RB7 as outputs too soon after a Power-On-Reset the ICD can fail to establish a debug connection.

Try changing your TRISB = 0b00110000; //was 0x10 //1 is input 0 is output statement to TRISB = 0b11110000; //was 0x10 //1 is input 0 is output and try a debug session.

\$\endgroup\$
  • \$\begingroup\$ If that was the case it would never work, the commented part does not seem to change the initialization. \$\endgroup\$ – Damien Feb 22 at 10:16
  • \$\begingroup\$ @Damien, I am not sure I understand your comment. In my experience the early PIC controllers had several issues with getting the debug session to start. The PIC16F88 is kind of old and may have a few quirks. My answer is just a request for Chris to give this a try and report back if it helped at all. \$\endgroup\$ – Dan1138 Feb 23 at 7:00
  • \$\begingroup\$ OP states the pic debug fine if he comment out the part described.if your answer was the reason, the debug will never work as this part of the code works fine from what the op says,it only stops when going on the calibrate function \$\endgroup\$ – Damien Feb 24 at 7:07
  • 1
    \$\begingroup\$ What you say is the likely case. So I must be confused when the Original Poster said: ... will not allow the debugger to run ... If the OP would describe the failing case for debug with more details I could perhaps understand what the issues could be. So the ICD debug may be working and the OP does not realize this is all bugs in the code. \$\endgroup\$ – Dan1138 Feb 25 at 8:14
0
\$\begingroup\$

My Guess is that you have a code error on the section that you have to comment. In debug a error would cause to stop the debug, in normal mode the chip might just continue or reset and you wouldn't see it.

On your code you have:

        {
            GETSIGNAL = 0;
            SAMPLEDIV--;    
        }
        SIGNALIN = GETSIGNAL + SIGNALIN; //ADD THE LAST READING TO THE SIGNAL SAMPLES
        DISPLAY();
        if (SAMPLE2 == 100)
        {   SAMPLE2 =0;
            SIGNALIN = SIGNALIN/SAMPLEDIV; //AVERAGE ALL THE READINGS TOGETHER
            SAMPLEDIV = 100;

Typically, you can have a divide by 0 error here which would cause a crash:

SIGNALIN = SIGNALIN/SAMPLEDIV;

Make sure SAMPLEDIV is never 0 and check if that fixes your issue.

Interestingly, you did check on your first loop but not on the calibrate function.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.