Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Help with programming pic16f877a

Status
Not open for further replies.

si2030

Member
Hi there,

I am at the very early stages of programming in C in MPLAB X using the compiler XC8.

Whilst I have a breadboard setup hooked up to a PicKit3 its my intention to run the debug functionality in the IDE first so I can best see if the program is working as I want it to.

Initially a very simple program, each time you press a switch it scrolls through 3 LEDs - hopefully the beginnings of a bigger project.

My question is this. When running in debug mode I want to set portB RB5 to low and get the simulator to step into the interrupt routine. I have the window/pic memory view/SFR displayed and with the program looping endlessly I try and change the value of PORTB and it just keeps looping.

My program is included as a file:

Kind Regards
Simon
 

Attachments

  • Power_Supply_MAIN.c
    11.5 KB · Views: 215
Hi Simon.... Let me say first off... That's a VERY well documented source code..

The RBIF cannot be cleared that way.... You MUST physically read the port to clear the interrupt..

If you place this at the end of the interrupt.

dummy = PORTB;

This will do the job.

Then place a break point inside your interrupt to see if it's firing..

Say at this point "PORTE = 0; "
 
Hi there,

OK, so I created a dummy variable to clear the port but I cannot even get the simulator to trigger an interrupt. I tried modifying PORTB manually through the SFR window and changing the hex from 0x00 to 0x20 for portB,RB6 but instead of stepping into the interrupt routine it continues to loop in the main program. How can I trigger an interrupt? Get it to go to the interrupt routine?

Kind Regards

Simon

PS its easier to read in a couple of months time when you swing back to it if its well documented :)
 
Why am I getting no carriage returns in that code? Totally unreadable for me.

Mike.
 
hi M,
Confirmed that the 0x0D is missing before the 0x0A in the hex code view of that listing.
E
 

Attachments

  • AAesp02.gif
    AAesp02.gif
    14.9 KB · Views: 216
Hi there,

OK, so I created a dummy variable to clear the port but I cannot even get the simulator to trigger an interrupt. I tried modifying PORTB manually through the SFR window and changing the hex from 0x00 to 0x20 for portB,RB6 but instead of stepping into the interrupt routine it continues to loop in the main program. How can I trigger an interrupt? Get it to go to the interrupt routine?

Kind Regards

Simon

PS its easier to read in a couple of months time when you swing back to it if its well documented :)
I'll try and simulate it here to see what's going on..
 
Okay.... There is this line...
C:
INTCONbits.RBIF = 1;  // Enable PORTB interupts

Once you change it to
C:
INTCONbits.RBIE= 1;  // Enable PORTB interupts
And change "TRISB =1" to "TRISB = 255".

The interrupts run.... I am just wondering why the encoder outputs do not work.
 
Thanks Ian,

That was a rookie mistake.. doh :(

I can make it go to interrupt routine but it now just goes straight there. I realise that it will go on the falling edge of RB6 however RB6 is already low and inputs. I dont know how to set RB6 hight while its an input (so it goes straight to the infinite loop) and then set RB6 low using MPLAB XC8 to make it go to the interrupt address...

Its late here in Aus... off to bed.. Thanks again for the help.

Simon
 
Your statements to "toggle" are also wrong..

Hers the correct method "~" is bitwise on a word... The code will not be included as the compiler omits it

You need to shift XOR to swap bits... ALSO you need a break after the first two switch statements and NOT the third.
C:
void interrupt isr(void)
{
    //*** Service external interrupt
    //
    //  Triggered on high -> low transition on RB5 pin
    //  caused by externally debounced pushbutton press

    if(PORTB);            // Clear interrupt flag

    // toggle current adjustment LEDs
    PORTE = 0;                     // Set all current LEDs off

    switch(CUR_ADJ_COUNT)
    {
            case 0:                // Fine adjustment selected
              sPORTE.port ^= 1 << 0;  // Turn fine cur fine adj LED on
              CUR_ADJ_COUNT = 1;  // Set count for medium for next time
              break;
             case 1:                // Medium adjustment selected
              sPORTE.port ^= 1 << 1;  // Turn fine cur med adj LED on
              CUR_ADJ_COUNT = 2;  // Set count for course for next time
                break;
             case 2:                // Course adjustment selected
              sPORTE.port ^= 1 << 2;  // Turn fine cur course adj LED on
              CUR_ADJ_COUNT = 0;  // Set count for fine for next time

    }
    RBIF = 0;
}
 
Hi there

I am still working on interrupts after a break from this for a couple of weeks. I have MPLAB XC setup to run the on board simulator. I can set breakpoints and step through the code. After stepping through some initialising it runs into an indefinite loop as required.

I have set INTCON RBIE and GIE both to 1 so if RB4-7 change it should go to an interrupt. You can step through this initialisation straight down into indefinite loop. Once I am stepping in the loop I have no way of triggering an external interrupt.

Is there a way to manually set RBIF=1 or change the value of RB4-7 to simulate a change of state and thus force the program to the interrupt routine? I tried to set RB4 in the variables window, in the SFR window and also the watches window. I cannot seem to change the value of any of the PORTB pins via any one of these windows.

I want to be able to force the program manually to go into an interrupt.. is this possible?

Kind Regards

Simon

I have included a copy of the program.
 

Attachments

  • Power_Supply_MAIN.c
    11.5 KB · Views: 158
Look into the "Stimulus" topics... You can fire events from this window... Are you using MPLABX or MPLAB 8.xx

In MPLABX.... After a successful build set a breakpoint inside your interrupt, From the Top menu Select the following "Window\Simulator\Stimulus"

In the Stimulus tab that appears below the code window... Select the pin you wish to simulate... Run the debugger, and the code should stop in the interrupt at your breakpoint when you fire the event!!
 
Hi there,

I decided to use a function call. The function is a void function with no parameters. Yet when I try and call the function its underlined red and I get "Unidentified identifier". How do I call a simple function? In this case its called "checkButtonDown" and I called it like this:

checkButtonDown();

Kind Regards

Simon
 

Attachments

  • Power_Supply_MAIN.c
    13 KB · Views: 141
You can't write functions inside a function.

C:
#include <xc.h>
#include <stdint.h>

/* Function prototype */
void checkButtonDown();
extern void __delay_ms(unsigned int );

#define _XTAL_FREQ  4000000         // oscillator frequency for _delay()

// CONFIGURATION
#pragma config CP = OFF             // Flash Program Memory Code Protection bit
                                    //  (Code protection off)
#pragma config WRT = OFF            // Flash Program Memory Write Enable bits
                                    //  (Write protection off; all program memory
                                    //   may be written to by EECON control)
#pragma config BOREN = OFF          // Brown-out Reset Enable bit (BOR enabled)
#pragma config PWRTE = OFF          // Power-up Timer Enable bit (PWRT disabled)
#pragma config FOSC = HS            // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF           // Watchdog Timer Enable bit (WDT disabled)
#pragma config LVP = OFF            // Low-Voltage (Single-Supply) In-Circuit
                                    //  Serial Programming Enable bit
                                    //  (RB3/PGM pin has PGM function;
                                    //  low-voltage programming disabled)
#pragma config CPD = OFF            // Data EEPROM Memory Code Protection bit
                                    //  (Data EEPROM code protection off)

// PIN ASSIGNEMENTS
#define sCUR_LED_FINE sPORTE.RE0    // Shadow copy of RE0
#define sCUR_LED_MED sPORTE.RE1     // Shadow copy of RE1
#define sCUR_LED_COURSE sPORTE.RE2  // Shadow copy of RE2

#define VOLT_SWITCH PORTBbits.RB1   // This pin reads the VOLT switch
#define CURR_SWITCH PORTBbits.RB2   // This pin reads the CURRENT switch
#define DOWN        0               // DOWN
#define UP          1               // UP

/***** GLOBAL VARIABLES *****/

int     CUR_FALLING_EDGE_FLAG = 0;  // Change triggers off falling edge
char    sRB1_VOLT = 0;              // Shadow copy of RB1

char    PORTB_READ;

volatile union {                    // shadow copy of PORTE
    char         port;
    struct {
        unsigned    RE0     : 0;
        unsigned    RE1     : 0;
        unsigned    RE2     : 0;
    };
} sPORTE;

/**********MAIN PROGRAM***********/
void main()
{
    //***INITIALISATION****/
    ADCON1 = 0x0F;                  // SetPORTE to IO

    TRISB = 255;                    // Configure PORTB to all inputs
    TRISE = 0;                      // Configure PORTE to all outputs

    RE0 = 1;
    sPORTE.RE0 = ~sPORTE.RE0;       // Initalise fine tune LED on

    INTCONbits.RBIE   = 1;          // Enable PORTB interupts
    INTCONbits.GIE    = 1;          // Enable global interupts

    int    db_cnt;                  // debounce counter
    int    VOLT_ADJ_COUNT  = 0;     // Voltage tunning ratio
    int    CUR_ADJ_COUNT   = 0;     // Current tunning ratio
    //*** Main loop

   for (;;)
    {
      
       if (VOLT_SWITCH == UP)           // if button up RB1 high)
       {
            checkButtonDown();
       }
    }
  }

/* Function implementation */
// wait for button press, debounce by counting:
        void checkButtonDown()
        {
            for (db_cnt = 0; db_cnt <= 10; db_cnt++)
            {
                __delay_ms(1);          // sample every 1 ms
                if (VOLT_SWITCH == UP)  // if button up RB1 high)
                    db_cnt = 0;         //   restart count
            }                           // until button down for 10 successive
                                        // reads.
             PORTE = 0;                 // Set all current LEDs off

            switch(CUR_ADJ_COUNT)
            {
                case 0:                 // Fine adjustment selected
                  sPORTE.port ^= 1 << 0;// Turn "Fine" adj LED on
                  VOLT_ADJ_COUNT = 1;   // Set count for medium for next time
                  break;
                 case 1:                // Medium adjustment selected
                  sPORTE.port ^= 1 << 1;// Turn "Med" adj LED on
                  VOLT_ADJ_COUNT = 2;   // Set count for course for next time
                  break;
                 case 2:                // Course adjustment selected
                  sPORTE.port ^= 1 << 2;// Turn "Course" adj LED on
                  VOLT_ADJ_COUNT = 0;   // Set count for fine for next time

            }
            // wait for button release, debounce by counting:
            for (db_cnt = 0; db_cnt <= 10; db_cnt++)
            {
                __delay_ms(1);          // sample every 1 ms
                if (VOLT_SWITCH == DOWN)  // if button down (GP2 low)
                    db_cnt = 0;         //   restart count
            }                           // until button up for 10 successive reads
        }

/***** INTERRUPT SERVICE ROUTINE *****/
void interrupt isr(void)
{
    //*** Service external interrupt
    //
    //  Triggered on high -> low transition on RB5 pin
    //  caused by externally debounced pushbutton press


}
 
Button Circuit.jpg
Hi There,

I have been using the Gooligum tutorials as a basis for using a button press (circuit included). I have also included an updated program. I have loaded the program into the micro controller and it runs however it immediately detects that RB1 is low and goes into the function where it never leaves as RB1 never registers a high (i.e release of the button). the button is never pressed as RB1 appears to be sinking the current. I have used a multi meter and with it not connected to RB1 it registers just under 5v on the jumper (not connected) and when the button is pressed it duly goes to 0 volts. So I believe that the circuit is correct but that my program is some how making RB1 sink current all the time...

Is there something I am missing?

Kind Regards

Simon
 

Attachments

  • Power_Supply_MAIN.c
    15.2 KB · Views: 158
Hi There,

With coding in C I am a newbie as you can see from my previous posts.

I have been working on this for a couple of nights now and am getting no where. I have, in the end paired down the program to just turning on the weak pull ups on the PIC16F877a. I find now that when I use this program to program the controller and just turning on the weak pull ups I get weird results. To remove the possibility of the breadboard being faulty I tried another bread board. I also used a second chip. I get the same problem. I am using a PICkit 3 and MPLAB xc8. With just the weak pullups enabled using OPTION_REG = 0b01111111 I get RB0, RB2, RB4, RB6 all sitting on 5 volts. The other pins are sitting on zero.... nothing is connected to any of the PORTB pins so all the pins in PORTB should sit at 5 volts I would have thought.

Could someone have a look at my code, because it is my code thats a problem here, and see if I have screwed up with the settings. I think they are correct and there is simply nothing else that I can see that should set alternate PORTB pins to deck.

Hope someone might have a look.

Kind Regards

Simon
 

Attachments

  • Power_Supply_MAIN.c
    11.8 KB · Views: 143
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top