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] PIC18F2550. LED blinking problem

Status
Not open for further replies.

Jiadong Yao

Member level 1
Joined
Mar 19, 2014
Messages
40
Helped
0
Reputation
0
Reaction score
0
Trophy points
6
Activity points
278
hi, I am working to make the led blink. you first press the button, it will blink once. The second time you press the button, it will blink twice and the third time blink 3 times and so on.
I am using the PIC18F2550, the compiler is C18.

below is the code.
and the problem is that, the led will always blink at a certain rate.

one more question: can i use for loop or while loop inside the while(1)?? because my coach told me that it is not allowed to use these loops and i could only use if statement. Is it this case?

thank you !

Code:
#include <p18cxxx.h>
#include "adc_process.h"
#include "pwm_process.h"
#include "stepper_process.h"
#include <stdio.h>
#include <stdlib.h>

long counter;
long buttonPress = 0;
long i=0;

void Init(void);

void main(void) {
	Init();			//initialise the system
 

	while(1) {
	
	if(PORTCbits.RC0 == 0)   //C0 equals 1,it connects to the 5V. button is not pressed
{
	buttonPress++;
	counter = 0;
	i=0;
}


if (counter == 0 )
{
	if(i == buttonPress*2 )
	{
	
	}
	else
	{
		LATCbits.LATC1 = !LATCbits.LATC1;
		
		i++;
	}
	
}
if(counter == 2000)
{
		counter=0;
}else
{
	counter++;
}

		Wait();				//wait until one 1m has elapesed
	}

}

void Init(void) {
	//configure I/O
	TRISCbits.TRISC0 = 1;

	TRISCbits.TRISC1 = 0;
	LATCbits.LATC1 = 0;

	counter = 0;
	
	Init_Timer_Loop();			

}

- - - Updated - - -

and how to make the layout clearer?
 

Attachments

  • main.zip
    1.4 KB · Views: 48
Last edited:

after the button is pressed it should flash, then do nothing except wait for next button press?

counter = 0
while (1)
{
if (button_pressed())
{ ++counter;
blink_led(counter); // a subroutine to make the LED blink n times
}
}
 
Last edited:

hi,kam,
Yes, your program is clearer than mine. but how to program the blink_led(counter) method? if counter=1, it should blink once, counter=2, blink twice and so on. The problem is that i cannot stop blinking after it has blinked the certain times.
 

hi, kam, i have another question. can i use for loop when i program subroutine?
 

yes you can

but my coach told me that we cannot use for loop, only if statement can be used. Because the program is for pic, not for PC. It's different. what do you think about it?
 

Try this:
Code:
unsigned int button_counter;

void main(void) {

	Init();
	
	button_counter = 0;

	while (1) {
		if (PORTCbits.RC0 == 0)
			blink_led(++button_counter);
	}
}

void blink_led(unsigned int blink_count) {
	unsigned int i = 0;

	while (i < blink_count) {
		LATCbits.LATC1 = !LATCbits.LATC1;
		Wait();
		LATCbits.LATC1 = !LATCbits.LATC1;
		Wait();
		++i;
	}
}

- - - Updated - - -

but my coach told me that we cannot use for loop, only if statement can be used. Because the program is for pic, not for PC. It's different. what do you think about it?

Your coach may be right and wrong.

Whether or not you can use a for loop is not limited by the PIC in terms of hardware, but rather the compiler. A for loop is a while loop just doing variable declaration, variable assignment, loop test condition and variable incrementation all on one line. This is high level programming language specific (such as C) and how the compiler reads it. There is no special assembly command required for a for loop.

All code is converted to assembly by the compiler. The compiler picks the best instructions available for the target processor. If your processor does not have a multiply instructions is uses a ton of additions to complete the operation. Which is why some processors are faster than others, they have a better instruction set which allows them to accomplish more in fewer cycles/time.

So your coach is wrong that you cannot run a for loop on a PIC, but may be right that the compiler does not allow it. I don't remember of the top of my head. I remember there being something funny about it when I first started using PIC18s. Then again Microchip just changed compilers so they may have fixed it. I have just always done the old while loop.

One thought is that you have to declare your variables at the top of the function because of C. So maybe it wants this:

int i;
void main (void) {

for (i= 0; i < 12; ++i) {
// code
}
}

Instead of this:

void main (void) {

for (int i= 0; i < 12; ++i) {
// code
}
}

Hope this helped.

- - - Updated - - -

Change this:
Code:
if(i == buttonPress*2 )

To:
Code:
if(i > buttonPress*2 )

That will fix your code but I would use my code from earlier or something like it. The reason for this is buttonPress*2 will get to big.
 

Did your instructor said this? "Because the program is for pic, not for PC"

Maybe your coach want you to blink the LED without using any loops. "You cannot" and "You should not" use loops give same maaning.
And so you can use Interrupts.


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
#define method1
 
#ifndef method1
    #define method2
#endif
 
unsigned int count = 0, x = 4;
unsigned char run = 0;
unsigned int button_counter = 0;
 
void ISR() {
 
    if(INTCON.TMR1IF) {
        //clrwdt
        if(++count >= x) {      //x = 500 ms * 4 = 2 sec
                        //if time after a button press is 2 sec or more then start blinking
            INTCON.TMR1IE = 0;  //disable TMR1 if 2 sec elapsed after a button press
            INTCON.INT0IE = 0;  //stop detecting button press until led blink process ends
            run = 1;            
        }
 
        INTCON.TMR1IF = 0;
    }
 
    
    if(INTCON.INT0IF) {
        //clrwdt
        if(INTCON.TMR1IE == 0)      //if TMR1 not enabled then enable it
            INTCON.TMR1IE = 1;
 
            #ifdef method1
                ++button_counter;   //increment button counter on each button press
            #endif
 
            #ifdef method2
                button_counter = button_counter + 2;
            #endif
 
            TMRH  = y;      //relaod TMR1
            TMRL = z;
            INTCON.TMR1IF = 0;  //clear TMR1 IF
            INTCON.INT0IF = 0;  //make INT0 ready to detect another button press    
    }
 
}
 
void main(void) {
 
    Init();
 
    //Configure TMR1 for 500 ms but don't start timer1
    //configure INT0 (button)
    //Enable global interrupts      
    
    //configure WDT for 2.3sec
    //clrwdt
 
    while (1) { //I am the only loop :)
 
        #ifdef method1
        if ((run) && (button_counter != 0)) {
            LATCbits.LATC1 = 1;
            //Delay 500 ms
            //clrwdt
            LATCbits.LATC1 = 0;
            //Delay 500 ms
            //clrwdt
 
            --button_counter;
            if(button_counter == 0) {
                run = 0;
                INTCON.INT0IE = 1;
            }
        }
        #endif
 
        #ifdef method2
        if ((run) && (button_counter != 0)) {
            LATCbits.LATC1 = ~LATCbits.LATC1;
            //Delay 500 ms
            //clrwdt
             
            --button_counter;
            if(button_counter == 0) {
                run = 0;
                INTCON.INT0IE = 1;
            }
        }
        #endif
 
        //clrwdt
        
    }
}

 
Last edited:

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top