Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[PIC] i cant stop my while loop

Status
Not open for further replies.

xinhui

Junior Member level 1
Joined
Jun 2, 2015
Messages
17
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Location
MALAYSIA
Activity points
143
i had met some problem in my coding. hope someone can help me solve the problem.
here is how my system work:
1. when button is pressed, the 2nd "if" will function.
2. when button is not pressed, the 1st "if" will function and stop after PORTC=0.

now the problem is when the system's button in "not pressed" condition, the circuit will run and work as what i want, but when i pressed the button after that, the circuit will not function as what i want, and it will function properly as i pressed the reset button in PIC16F877A. is that got some mistake in my coding? here is my code:
Code:
#define button PORTA.F4
#define LEDs PORTA.F0
#define Buzzer PORTA.F0
#define STEP1 0b00010010
#define STEP2 0b00000010
#define STEP3 0b00000110
#define STEP4 0b00000100
#define STEP5 0b00001100
#define STEP6 0b00001000
#define STEP7 0b00011000
#define STEP8 0b00010000

void Delay(unsigned int ms)
  {
   switch(ms)
  {
  case 500:
  Delay_ms(500);
  break;
  case 200:
  Delay_ms(200);
  break;
  default:
  Delay_ms(1000);
  }
  }
void main(void)
{   unsigned int i;
    TRISA =0b00110000;
    TRISB = 0;   //Port B as output (LCD is OUTPUT)
    TRISC=0*00;
    PORTC=0;
    Lcd_Init(&PORTB);
    Lcd_Config(&PORTB,3,1,2,7,6,5,4);
    Lcd_Cmd(LCD_CURSOR_OFF);

      while(1){

      if(button==1)
      {               //Button is not pressed
      Lcd_Cmd(LCD_CLEAR);        //Clear LCD display (Blank the LCD screen)
      Lcd_Out(1, 4, "HAVE A SAFE"); //Print text on LCD at line 1, column 4
      Lcd_Out(2, 6, "JOURNEY");     //Print text on LCD at line 2, column 5
      Delay_ms(1000);
      LEDs=0;
      PORTC=STEP8;
      Delay(200);
      PORTC=STEP7;
      Delay(200);
      PORTC=STEP6;
      Delay(200);
      PORTD=STEP5;
      Delay(200);
      PORTC=STEP4;
      Delay(200);
      PORTC=STEP3;
      Delay(200);
      PORTC=STEP2;
      Delay(200);
      PORTC=STEP1;
      Delay(200);
      break;
      }

      if(button==0)//Button is pressed
      {
      Lcd_Cmd(LCD_CLEAR);        //Clear LCD display (Blank the LCD screen)
      Lcd_Out(1,5,"CAUTION!!!");
      Lcd_Out(2,5,"CAUTION!!!");
      Delay_ms(500);
      PORTC=STEP1;
      Delay(500);
      PORTC=STEP2;
      Delay(500);
      PORTC=STEP3;
      Delay(500);
      PORTC=STEP4;
      Delay(500);
      PORTC=STEP5;
      Delay(500);
      PORTC=STEP6;
      Delay(500);
      PORTC=STEP7;
      Delay(500);
      PORTC=STEP8;
      Delay(500);
      while(1){
      Buzzer=1;
      Delay_ms(2000);
      LEDs=1;
      Delay_ms(2000);
      LEDs=0;
      Delay_ms(500);   }
      break;
      }
      }
    }

hope someone can help me solve this problem...:grin:
 

You are obviously not reaching the 'break' instruction in either check.
Most likely problem is electrical rather than software although burying a 'while(1)' loop inside another has got to be bad practice. At the end of the code you continuously loop with LEDs flashing with no way of escaping. The first thing to check is the 'button' signal is actually activating and clearing, do you have/need pull up or pull down resistors on the button inputs?

Brian.
 

Zip and post the complete mikroC project files. I will fix it.
 
  • Like
Reactions: FvM

    FvM

    Points: 2
    Helpful Answer Positive Rating
this is my code... hope you can help me solve this problem....:)
 

Attachments

  • PIC CODE.zip
    29.7 KB · Views: 83
Last edited by a moderator:

What do you expect to happen if the while (1) loop is left via break statement?

There's no defined behaviour when "returning" form main. Some compilers have an endless while (1); after main(), without a activated watchodg, code execution would stay there forever.

Normallly you have a while(1) loop around the periodical main action, and it's not left by a break statement.
 

if i delete the "break;" part, so my code will be okay??
 

This is the code I made using interrupts. There is no blocking code. Maybe there are bugs. I have not tested it in Proteus or hardware.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#define SW PORTA.F4
#define LED PORTA.F0
#define BUZZER PORTA.F1
 
char steps[] = {0b00010010, 0b00000010, 0b00000110, 0b00000100, 0b00001100, 0b00001000, 0b00011000, 0b00010000};
char doOnce1 = 0, doOnce2 = 0, mode = 0, i = 0, count = 0, state = 0, lock = 0;
 
//Timer1
//Prescaler 1:4; TMR1 Preload = 15536; Actual Interrupt Time : 200 ms
 
//Place/Copy this part in declaration section
void InitTimer1_200ms() {
    T1CON   = 0x21;
    INTCON.TMR1IF = 0;
    TMR1H   = 0x3C;
    TMR1L   = 0xB0;
    INTCON.TMR1IE = 1;
    INTCON = 0xC0;
}
 
//Timer1
//Prescaler 1:8; TMR1 Preload = 3036; Actual Interrupt Time : 500 ms
 
//Place/Copy this part in declaration section
void InitTimer1_500ms() {
    T1CON   = 0x31;
    INTCON.TMR1IF = 0;
    TMR1H   = 0x0B;
    TMR1L   = 0xDC;
    INTCON.TMR1IE = 1;
    INTCON = 0xC0;
}
 
 
void Interrupt() {
    if(INTCON.TMR1IF) {
    
        INTCON.TMR1IF = 0;
        
        if(state == 0) {
            if(mode == 0) {
                 PORTC = steps[7 - i];
                 TMR1H = 0x3C;
                 TMR1L = 0xB0;
            }
            else if(mode == 1) {
                 PORTC = steps[i];
                 TMR1H = 0x0B;
                 TMR1L = 0xDC;
            }
 
            i++;
        }
        
        if(i == 8) {
            i = 0;
            if(mode == 1)state = 1;
            else {
               T1CON.TMR1ON = 0;
               lock = 0;
            }
        }
 
        if(state) {
             if(state == 1) {
                  BUZZER = 1;
                  count = 0;
             }
             
             if(count == 4) {
                  LED = 1;
             }
             else if(count == 8) {
                  LED = 0;
             }
             else if(count == 9) {
                    state = 0;
                    count = 0;
                    T1CON.TMR1ON = 0;
 
                    doOnce1 = 0;
                    doOnce2 = 0;
                    lock = 0;
             }
             
             state++;
             count++;
        }
    }
}
 
 
void main(void) {
 
    CMCON = 0x07;
    ADCON1 = 0x87;
    
    TRISA = 0x30;
    TRISB = 0x00;
    TRISC = 0x00;
 
    PORTA = 0x00;
    PORTB = 0x00;
    PORTC = 0x00;
    
    Lcd_Init(&PORTB);
    Lcd_Config(&PORTB,3,1,2,7,6,5,4);
    Lcd_Cmd(LCD_CURSOR_OFF);
    Lcd_Cmd(LCD_CLEAR);
    
    while(1){
 
        if(lock == 0) {
        
            if(SW) {
                Delay_ms(50);
                if(SW) {
                    if(!doOnce1) {
                         Lcd_Cmd(LCD_CLEAR);
                         Lcd_Out(1,4,"Have a safe");
                         Lcd_Out(2,6,"Journey");
 
                         Delay_ms(800);
                         LED = 0;
 
                         InitTimer1_200ms();
 
                         mode = 0;
                         i = 0;
                         doOnce1 = 1;
                         lock = 1;
                    }
                }
            }
            else if(!SW) {
                Delay_ms(50);
                if(!SW) {
                    if(!doOnce2) {
                         Lcd_Cmd(LCD_CLEAR);
                         Lcd_Out(1,5,"Caution!!!");
                         Lcd_Out(2,5,"Caution!!!");
 
                         Delay_ms(500);
                         LED = 0;
 
                         InitTimer1_500ms();
 
                         mode = 1;
                         i = 0;
                         doOnce2 = 1;
                         lock = 1;
                    }
                }
            }
        }
    }
}





In your code

Code:
while(1){
      Buzzer=1;
      Delay_ms(2000);
      LEDs=1;
      Delay_ms(2000);
      LEDs=0;
      Delay_ms(500);   }
      break;

the break statement is outside the while(1) loop.

- - - Updated - - -

Edit: Your code modified a little.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#define button PORTA.F4
#define LED PORTA.F0
#define Buzzer PORTA.F1
 
#define STEP1 0b00010010
#define STEP2 0b00000010
#define STEP3 0b00000110
#define STEP4 0b00000100
#define STEP5 0b00001100
#define STEP6 0b00001000
#define STEP7 0b00011000
#define STEP8 0b00010000
 
char doOnce1 = 0, doOnce2 = 0;
 
void Delay(unsigned int ms)
{
    switch(ms)
    {
        case 500:
            Delay_ms(500);
            break;
        case 200:
            Delay_ms(200);
            break;
        default:
            Delay_ms(1000);
    }
}
 
void main(void)
{
    TRISA = 0b00110000;
    TRISB = 0;
    TRISC = 0;
    PORTC = 0;
    
    Lcd_Init(&PORTB);
    Lcd_Config(&PORTB,3,1,2,7,6,5,4);
    Lcd_Cmd(LCD_CURSOR_OFF);
    Lcd_Cmd(LCD_CLEAR);
    
    while(1){
 
        if(button == 1) //Button is not pressed
        {
            Delay_ms(50);
            if(button == 1) //Button is not pressed
            {
                if(doOnce1 == 0) {
                    Lcd_Cmd(LCD_CLEAR);
                    Lcd_Out(1,4,"HAVE A SAFE");
                    Lcd_Out(2,6,"JOURNEY");
                    
                    doOnce1 = 1;
                }
                
                Delay_ms(1000);
                LED = 0;
                PORTC = STEP8;
                Delay(200);
                PORTC = STEP7;
                Delay(200);
                PORTC = STEP6;
                Delay(200);
                PORTD = STEP5;
                Delay(200);
                PORTC = STEP4;
                Delay(200);
                PORTC = STEP3;
                Delay(200);
                PORTC = STEP2;
                Delay(200);
                PORTC = STEP1;
                Delay(200);
            }
        }
        else if(button == 0) //Button is pressed
        {
            Delay_ms(50);
            if(button == 0) {
            
                if(doOnce2 == 0) {
                    Lcd_Cmd(LCD_CLEAR);        //Clear LCD display (Blank the LCD screen)
                    Lcd_Out(1,5,"CAUTION!!!");
                    Lcd_Out(2,5,"CAUTION!!!");
 
                    doOnce2 = 1;
                }
 
                Delay_ms(500);
                PORTC = STEP1;
                Delay(500);
                PORTC = STEP2;
                Delay(500);
                PORTC = STEP3;
                Delay(500);
                PORTC = STEP4;
                Delay(500);
                PORTC = STEP5;
                Delay(500);
                PORTC = STEP6;
                Delay(500);
                PORTC = STEP7;
                Delay(500);
                PORTC = STEP8;
                Delay(500);
 
                while(1) {
                    Buzzer = 1;
                    Delay_ms(2000);
                    LEDs=1;
                    Delay_ms(2000);
                    LEDs=0;
                    Delay_ms(500);
                    doOnce1 = 0;
                    doOnce2 = 0;
                    break;
                }
            }
        }
    }
}

 

Attachments

  • LED Curtain.rar
    26.9 KB · Views: 82
Last edited:

my desired result is when i m not pressed the button, the LCD will display the text "have a safe journey", but when i pressed it after that, the LCD will straight display the text "caution!!!" instead of show this text after pressing the reset button which is connect to the pin 1 of PIC16F877A.
 

You have big delays in both if() conditions and hence the code related to button not pressed will be executing all the time and hence you have to press the button and hold it for a few seconds for it to be detected. This is not the right way of writing the code. Use the code which I have posted it uses timer interrupts.
 
  • Like
Reactions: xinhui

    xinhui

    Points: 2
    Helpful Answer Positive Rating
actually this system is used at the LRT station as an emergency button. in this system, stepper motor is involved to stop the LRT and open the LRT door. so there are 2 stepper motor involved. in my code that i attach in my previous post is just a motor involved. now the problem is i just want the 1st motor do in 1 loop but not the continuous loop, but i had try many ways to modify my code but still can't get my desired result. so what should i do for the "if" part which the button is not pressed for get the result of one loop on the 1st motor and continuous loop for the second motor when the button is not pressed.
 

Please provide the code which includes the motor. I need complete code that you have written. Let it show the working using delays. I will modify it so that Timer interrupts are used and make it work as you want. So, Zip and post the complete mikroC project files which includes code for motor.

Are you saying that stepper motor is connectd to PORTC ? Please show the circuit, if possible in Proteus format.
 

this is the code and circuit... very thankful for your help:smile: i m very confuse while doing this coding... i have benn try many days already... hope u can help me solve this problem.
 

Attachments

  • circuit.zip
    43 KB · Views: 86
  • code.zip
    33.3 KB · Views: 78

1. The porta is analog port by default, if you want to use it as digital you have to configure ADCON1=0x07,
2. add de-bounce delay after key press
3. Break command will lead to exit from the while loop, after that the main function will be executed again, is that you needed?
 

@MUKESH.K.S

If button is not pressed and if thet if() condition has just started to execute and if he presses the button then he have to wait till that if() condition code executed before the button press is detected. He has to use Timer Interrupts to load stepper motor values to PORTC.
 

so where should i place the break command to let the stepper motor of door stop after completing one loop and let the stepper motor of LRT continuous rotating and just stop when i pressed the button?
 

You have to use the code that I have posted. But port it to mikroC PRO PIC. mikroC (Old) had a lot of bugs. Maybe it is generating buggy .hex file.
 

thanks for your help... it is useful for me... i m really appreciate it...:-D
 

Explain me how the motors have to work like which motor rotates when and what angle it rotates and also your motors step angle.
 

Hello!

Some comments about this program:
1. Button timer.
What you are doing is:
- Check the button status
- Wait 50 ms
- Check if the button is still in the same status.

What's the point? This is a continuous process. Why not just testing once?
Beside this, there can always be cases where you just pressed, and there are some
rebounds, or where you release the button in your 50 ms delay. Next, you cannot do
anything during the 50 ms. Why not using interrupts?

Usually what is done with interrupts:
- Configure button interrupt;
At interrupt:
- Call your button event process
- Forbid a button interrupt
- Fire a timer for a given period
At timer interrupt:
- Re enable button interrupt

2. You should not writ functions for the sake of writing functions.
The Delay function is useless as it calls Delay_ms with the same value.
Why not writing:

Code C - [expand]
1
2
3
4
uint16 delay.
// Somewhere in your code:
if((delay == 200) }} (delay == 500)) Delay_ms(delay);
else Delay_ms(1000);



And beside this, you always use Delay with a parameter of 200 or 500, so there is really
no point writing this function. Just use Delay_ms(200) and Delay_ms(500) directly.

3. Why not using a loop instead of writing sequentially all the states of your motor?
In pseudo code:

Code C - [expand]
1
2
3
4
for(i = 0 ; i < 8 ; ++i) {
    MOTOR_PORT = step[i];
    delay(200);
}



4. What would happen if you want to change the speed?
You are going to change all the delay instances? Why not defining delays like this:

#define SHORT_DELAY 200
#define LONG_DELAY 500

and then in your code, use Delay_ms(SHORT_DELAY) or Delay_ms(LONG_DELAY).
Then if you have to change the speed, just change the #define and your're done.

5. A better approach for driving motors :
You are driving your motors by sets of 8 steps. What's the purpose of using half-steps since
you will run 4 steps at once?
What you should do:

- Set up a timer with interrupt.
- Declare a static variable like step_pos.

At interrupt:

- Increment or decrement step_pos and roll it into [0..7]
- Set port C to step[step_pos]

This way, your half steps will be useful and you can stop the program any time, even at a halfstep.

Dora.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top