0

I am using MPLAB to perform an operation on PIC kit 14f458.

Now I want to create a code to pass the different amount of voltage supply LED through the Microcontroller using a button. When button pressed the first time I should get waveform with 10% DC, for second and third time, 50% and 95% respectively.

I have worked on this But still getting Values OF RE2 PORT as 0 rather than 1. And I also don't know how to stop timer while I release the button.

My code is as follow:

#include<stdio.h>                       //Standard I/O Library
#include<p18cxxx.h>                     //for TRISA,E and PORTA,E declaration
#pragma config WDT = OFF                //watchdog counter
#pragma config OSC = HS, OSCS = OFF
#pragma config PWRT = OFF, BOR = ON, BORV = 45
#pragma config DEBUG = OFF, LVP = OFF, STVR = OFF

void timer_10()
{
    CCP1CON = 0;
    PR2 = 249;
    CCPR1L = 24;
    TRISCbits.TRISC2 = 0;
    T2CON = 0x00;
    CCP1CON = 0x3c;
    TMR2 = 0;
    T2CONbits.TMR2ON = 1;
    while(1)
    {
        PIR1bits.TMR2IF = 0;
        while(PIR1bits.TMR2IF == 0);
    }
}

void timer_50()
{
    CCP1CON = 0;
    PR2 = 249;
    CCPR1L = 124;
    TRISCbits.TRISC2 = 0;
    T2CON = 0x00;
    CCP1CON = 0x2c;
    TMR2 = 0;
    T2CONbits.TMR2ON = 1;
    while(1)
    {
        PIR1bits.TMR2IF = 0;
        while(PIR1bits.TMR2IF == 0);
    }
}

void timer_95()
{
    CCP1CON = 0;
    PR2 = 249;
    CCPR1L = 236;
    TRISCbits.TRISC2 = 0;
    T2CON = 0x00;
    CCP1CON = 0x2c;
    TMR2 = 0;
    T2CONbits.TMR2ON = 1;
    while(1)
    {
        PIR1bits.TMR2IF = 0;
        while(PIR1bits.TMR2IF == 0);
    }
}

void main()
{
    int i = 1;
    ADCON1 = 0x06;                      //Sets RA0 to digital mode
    CMCON = 0x07;
    TRISEbits.TRISE2 = 1;               //set E2 PORTE pins as input
    PORTEbits.RE2 = 1;                  //Here I am not able to SET Value 1

    while(1)
    {
        while(PORTEbits.RE2 == 0)
        {
            switch(i)
            {
                case 1:
                    timer_10();
                    break;
                case 2:
                    timer_50();
                    break;
                case 3:
                    timer_95();
                    break;
            }
            if(i<4)
            {
                i++;
                if(i>=4)
                {
                    i=1;
                }
            }
        }
    }
}

And My compiler Get Stuck in function timer_10(). Please help me.

Sigve Kolbeinson
  • 1,133
  • 1
  • 7
  • 16

2 Answers2

0

This is a bit too long for a comment, and I think you're probably able to discover the answer yourself - however, I'll give you some pointers.

In main()

TRISEbits.TRISE2 = 1;               //set E2 PORTE pins as input
PORTEbits.RE2 = 1;                  //Here I am not able to SET Value 1

What behaviour do you expect when you write to port E2 after configuring E2 as an input? It is described in the PIC18F458 data sheet, specifically section 9.5

In timer_10()

void timer_10()
{
    CCP1CON = 0;
    PR2 = 249;
    CCPR1L = 24;
    TRISCbits.TRISC2 = 0;
    T2CON = 0x00;
    CCP1CON = 0x3c;
    TMR2 = 0;
    T2CONbits.TMR2ON = 1;
    while(1)
    {
        PIR1bits.TMR2IF = 0;
        while(PIR1bits.TMR2IF == 0);
    }
}

You said your compiler got stuck, but I assume you mean debugger, as you were able to run main() to observe PORTEbits.RE2 = 1; not doing what you expected. If you single-step this in function a debugger, where does it get stuck? can you see why?

Sigve Kolbeinson
  • 1,133
  • 1
  • 7
  • 16
  • Yes, you are right when I run my program in a debugger, I got stuck in **While loop** in function **timer_10()**. when timer2 completes it starts again and again. So when I change the value of **RE2** using Stimulus case 2 should be run and **timer_50()** should be called but it's not working. And I am using a logic analyzer to watch the value of **RE2** and when I start running, the value of **RE2** shows 0 rather than 1. And I know `PORTEbits.RE2 = 1;` sets the value 1 but It's not working, why I do not know. – Vishalkumar Monpara Mar 18 '18 at 19:01
  • Regarding `timer_10()`, what do you expect to happen after `while(PIR1bits.TMR2IF == 0 );` exits, ie. when `PIR1bits.TMR2IF` changes to `1`? Obviously, if that function doesn't exit, you won't get back to `main` to check `RE2` to proceed to `timer_50()` – Sigve Kolbeinson Mar 18 '18 at 19:45
  • Yes, I want it should exit after `while(PIR1bits.TMR2IF == 0)` but it starts again, I want to get exit from the function `timer_10` and plz help me to how to get exit from it. And in `main()` I have set `PORTEbits.RE2 = 1` but in a logic analyzer, it starts with 0 when I start running my code. If I have set `PORTEbits.RE2 = 1` why it starts with `PORTEbits.RE2 = 0`. – Vishalkumar Monpara Mar 18 '18 at 20:00
  • When `while(PIR1bits.TMR2IF == 0);` exits, the program is at the end of the loop body of `while(1)`, so it checks the loop condition of `while(1)`. `1` is always true, so that `while(1)` is an *infinite loop*. To make it exit the function, remove the outer loop, keeping its loop body `PIR1bits.TMR2IF = 0; while (PIR1bits.TMR2IF == 0);` – Sigve Kolbeinson Mar 18 '18 at 20:05
  • Yes, I got it but whenever I debug my program it starts with `RE2 = 0` why it happens while I have set it `PORTEbits.RE2 = 1`. And can I use `while(PORTEbits.RE2 == 0)` condition in function `timer_10()` without define PORTE in function? for exit from the loop while I release the button. – Vishalkumar Monpara Mar 18 '18 at 20:15
  • Because, in the line above, you do `TRISEbits.TRISE2 = 1;` From the data sheet linked in my answer: *Setting a TRISE bit (= 1) will make the corresponding PORTE pin an input (i.e., put the corresponding output driver in a high-impedance mode)* So writing to RE2 will have no effect, you'll need to change the voltage level on the pin to change the value of `PORTEbits.RE2` when it is configured as an input. – Sigve Kolbeinson Mar 18 '18 at 20:58
0

Ok, let's simplify this a bit. If you want the duty cycle to change on the negative edge of a push button, and you don't want to use interrupts, then you need to restructure what you have. Firstly, there are several issues with the timer_x routines: 1) you don't need the while loop in there, that is why you are getting stuck. 2) If you remove that loop, you will constantly call a timer routine which will reset the register values and you will not get what you expect. Also, since you are not using interrupts, who cares if the overflow flag is set or not, just leave it set. To fix this, first, remove all the timer_x routines. Next, you need a timer routine to read the switch input. Remember that all switches have switch bounce so reading one value isn't reliable. You either need to read the switch slowly, at a rate greater than the switch bounce (~50ms) and only run your routines if you have two readings in a row that are the same, or you can read it faster, but you will need more readings that are the same to know you have a stable value. From there, you can only increment "i" on the first negative edge, not all the time the switch is held down (unless you want it that way). your main routine should look something like (forgive the shortcut for the timer registers):

Main()
if (tmr2.overflow)     // 50ms switch read timer
{
  switchCurrent = PORTE2;
}
if (   (switchCurrent == swtichLast)    // Two readings of the same value
    && (!switchCurrent)                 // and switch is pressed
    && (!switchUpdated)  )              // and haven't updated the pwm yet
{
      switchUpdated = TRUE;             // Only allow one update per switch 
      i++;
      if (i > 4)
      {
          i = 0;
      }
      switch (i)
      {
         case 0:
             CCPR1L = 24;
             break;
         case 1:
             CCPR1L = 124;
             break;
        ... and so on.  Note, the only difference in each case is CCPR1L, so just rewrite that register instead of resetting everything.
}
switchLast = swtichCurrent;
if (swtichCurrent)
    switchUpdated = 0

This should give you a starting point, hope it helps

Joe Thomas
  • 325
  • 1
  • 7