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] Falling edge detection code for PIC - MikroC Compiler

Status
Not open for further replies.

Nuwan Tharaka

Newbie level 4
Joined
Nov 23, 2013
Messages
7
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Location
Sri Lanka
Activity points
57
I was following a tutorial in mikroc and there I experimented a code for getting a output (light a led) when a button is pressed;
there the author had used falling edge detection for the button and I have problem with understanding that part;I asked several persons and didnt get a satisfactory answer;
so I expect a simple and illustrated explanation as I am still getting to microcontrollers and C
Code:
void main()
{
trisb.fo=0; // 0 bit is output led
trisb.f7=1; //7th bit is input button
option_reg.f7=0; // enable internal pullups
for(;;){
if(portb.f7==0){
[COLOR="#FF0000"]while(portb.f7==0){
delaly_ms(20);
}
portb.f0^=1;[/COLOR]
}
} 
}
the mcu is 16f877
the coloured code is very confusing to me
 

FenTrac

Full Member level 4
Joined
Jul 6, 2014
Messages
204
Helped
37
Reputation
74
Reaction score
39
Trophy points
28
Location
West Coast
Activity points
1,761
Below is your code with some comments added for each line. The code really does'nt illustrate falling edge detection. It is toggling pin b.f0 when pin b.f7 is no longer sampled as zero, Falling edge detection would be at the "if(portb.f7 == 0)" point in the code.

View attachment 119532

Code:
void main()
{
trisb.fo=0;       // 0 bit is output led
trisb.f7=1;       // 7th bit is input button
option_reg.f7=0;  // enable internal pullups
for(;;)         // continous for loop
  {
  if(portb.f7==0)       // if b.f7 == 0
     {
     while(portb.f7==0) // keep checking to see if b.f7 == 0
        {
        delaly_ms(20);  // pause before checking again
        }
      portb.f0^=1;      // toggle b.f0 when b/f7 is no longer 0
      }  // end if b.f7 == 0;
   }  // end for-ever
}  // end main
 

Attachments

  • example.jpg
    example.jpg
    12.5 KB · Views: 11

betwixt

Super Moderator
Staff member
Joined
Jul 4, 2009
Messages
14,941
Helped
4,876
Reputation
9,770
Reaction score
4,664
Trophy points
1,393
Location
Aberdyfi, West Wales, UK
Activity points
127,092
A more general way is to read the port bit in the main loop of your program, or in a timed ISR. Store the value read from the port in a variable. Then use the logic:
"if the variable says it was == 1 but is reading it now == 0" you know the falling edge has been detected. Reverse 1/0 to find a rising edge instead.

Brian.
 
  • Like
Reactions: Garyl

    Garyl

    Points: 2
    Helpful Answer Positive Rating

KlausST

Super Moderator
Staff member
Joined
Apr 17, 2014
Messages
19,771
Helped
4,350
Reputation
8,709
Reaction score
4,312
Trophy points
1,393
Activity points
130,845
Hi,

Like brain says.
Just to clarify, with a signal like this: "------\_______"

if(portb.f7 == 0)"
Is level triggered, because when you run the code (for example n times) it will be true (many times) as long as the port pin is low.

As opposed to this
if the variable says it was == 1 but is reading it now == 0"
Will be exactly one time be true, just after the first time when the port is read as low

Klaus
 

Nuwan Tharaka

Newbie level 4
Joined
Nov 23, 2013
Messages
7
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Location
Sri Lanka
Activity points
57
thanks all you guys for the answers!
But still little bit confused!
@betwixt
if the variable says it was == 1 but is reading it now == 0
how to write that? please give me a code example
actually I want the most simplest explanation as I am a newbie,so think you are telling all these to a person who does not know anything about it! thanks guys
I really appreciate you guys!
 

betwixt

Super Moderator
Staff member
Joined
Jul 4, 2009
Messages
14,941
Helped
4,876
Reputation
9,770
Reaction score
4,664
Trophy points
1,393
Location
Aberdyfi, West Wales, UK
Activity points
127,092
I don't use MikroC so I can't verify it works but you should see the method from this code. Depending on what f7 does you may need to change the function and it's prototype to return a different variable type.

Code:
void F7_Went_Low();
char OldState = 0;

main()
{
	if((OldState == 1) & (Portb.f7 == 0)) F7_Went_Low();
	OldState = Portb.f7 ? 1 : 0;
	
	<remainder of your code>
}


void F7_Went_Low()
{
	<code to run when f7 goes low>
}
Brian.
 
  • Like
Reactions: Garyl

    Garyl

    Points: 2
    Helpful Answer Positive Rating

KlausST

Super Moderator
Staff member
Joined
Apr 17, 2014
Messages
19,771
Helped
4,350
Reputation
8,709
Reaction score
4,312
Trophy points
1,393
Activity points
130,845
Hi,

Brians solution is OK, but there is one very small issue.

For a high reliability solution i recommend to spend an extra variable for the current port state. Reading twice the port at different times during one loop gives the chance that the port status changes between those two readings.
Then you have the (little) change to miss one event. This is no problem for level triggered signals, but for edge triggered signals.

I hope Brian doesn´t mind if i change his code:


Code:
Code:
void F7_Went_Low();
char NewState = 0;
char OldState = 0;

main()
{
	NewState = Portb.f7
        if((OldState == 1) & (NewState == 0)) F7_Went_Low();
	OldState = NewState ? 1 : 0;
	
	<remainder of your code>
}


void F7_Went_Low()
{
	<code to run when f7 goes low>
}
I´m sorry in case there is an error with my code, but i´m not familiar with C. I just can copy and paste :-(

Klaus
 

betwixt

Super Moderator
Staff member
Joined
Jul 4, 2009
Messages
14,941
Helped
4,876
Reputation
9,770
Reaction score
4,664
Trophy points
1,393
Location
Aberdyfi, West Wales, UK
Activity points
127,092
I hope Brian doesn´t mind if i change his code:
not at all! - I haven't actually tried it anyway!

In real life, all situations where a port is polled will be prone to some delay. If the original code works at all, the logic still applies, it would just take one more loop of the program to respond.

Brian.
 
  • Like
Reactions: Garyl

    Garyl

    Points: 2
    Helpful Answer Positive Rating

KlausST

Super Moderator
Staff member
Joined
Apr 17, 2014
Messages
19,771
Helped
4,350
Reputation
8,709
Reaction score
4,312
Trophy points
1,393
Activity points
130,845
Hi,

In real life, all situations where a port is polled will be prone to some delay. If the original code works at all, the logic still applies, it would just take one more loop of the program to respond.
I don`t think so.

For sure because of the small difference in time it is not very likely, but with your code you probably miss a falling edge, and will never detect it.

Code:
void F7_Went_Low();
char OldState = 0;

main()
{
	if((OldState == 1) & (Portb.f7 == 0)) F7_Went_Low()[COLOR="#FF0000"]; if here Portb.f7 is high[/COLOR]
	OldState = Portb.f7 ? 1 : 0; [COLOR="#FF0000"]but here Portb.f7 is low, (= it just has changed) then you miss one falling edge[/COLOR]
	
	<remainder of your code>
}


void F7_Went_Low()
{
	<code to run when f7 goes low>
}

Don´t get me wrong. I know the chance is small. It may detect 100000 edges correctly, but then it may miss one.

Klaus
 

FenTrac

Full Member level 4
Joined
Jul 6, 2014
Messages
204
Helped
37
Reputation
74
Reaction score
39
Trophy points
28
Location
West Coast
Activity points
1,761
Nuwan,

In the origional code you posted, the "if(portb.f7==0)" serves as an falling edge detector because the while loop that follows it prevents the "if statement" from being executed again, until the portb.f7 has gone back high. Thus it will see a low on that pin only once, and then wait until it is high before it starts to check for a low again. The "while(portb.f7 == 0" loop is a positive edge detector, because it runs until portb.f7 goes back high. Then the program looks for a high to low transition again. So, the program is looking for low to high and high to low transitions. Portb.f0 is being toggled on the low to high edge, but not the high to low edge.
 
Last edited:

Aussie Susan

Advanced Member level 4
Joined
Jan 5, 2015
Messages
1,260
Helped
380
Reputation
760
Reaction score
376
Trophy points
83
Activity points
13,631
One aspect that has not been mentioned is that the OP says the input is a button. Therefore it will be subject to contact bounce.
If all you are doing is turning on a LED then this might not matter as you may not see the flicker, but in general I always recommend either a hardware or software debounce when monitoring buttons and switches.
Also, for completeness, while the OP does not say which MCU is begin used, many have edge triggered (and edge selectable) interrupts as some have port bit change interrupts (which are NOT edge selectable but that can be handled in the ISR).
However I do NOT recommend using interrupts connected to switches and buttons unless there is hardware debounce circuitry.
Susan
 

betwixt

Super Moderator
Staff member
Joined
Jul 4, 2009
Messages
14,941
Helped
4,876
Reputation
9,770
Reaction score
4,664
Trophy points
1,393
Location
Aberdyfi, West Wales, UK
Activity points
127,092
Good point Susan.

Debounce is always a good idea, especially with the expected faster response time if an interrupt is used. The original code used a "delaly" (?) although without knowing the full purpose of the program it's impossible to say whether that would be appropriate to solve this particular problem.

Brian.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Top