Interrupt routine not acting as expected

Go To Last Post
21 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello everybody!

 

I have been working on a small project for the last weeks. I came to a point where I decided to add some functionality to it.

I have decided to include two pressure buttons that will trigger the interrupt flags that will execute a function in the main program.

 

I'm using AtMega328p and an USB-toSerial converter to upload code to the uC. I use avr-gcc and avrdude for the tasks. A makefile does the compilation task and I issue the avrdude command manually.

 

My project is supposed to read some values on the ADC pins and after some basic math it presents some values on an LCD module!

The functionality I'm now adding is supposed to increase/decrease frequency values sent tothe configuration of one other device I'm using, a DDS device. All the rest should be the same.

 

I have set up the interrupts to be activated on falling edges.

The problem is that when I press any of the 2 buttons, the checking procedure of the INT0 and INT1 pins never happens to be true. So I added some code to print on the LCD module the flag that each ISR changes! And I can see it changing, so, I need help to figure out why the checking procedure is not working properly.

 

As my small project as several files (.c and .h files) I'll split the code of interest and I'll state the file where each piece of code is.

 

The interrupts setup is as follows:

freq_sweep.c:

void interrupt_setup(void){
      // Set interrupts to trigger on falling edges, according to the datasshet, page 71, section 13.2.1
      EICRA |= (1 << ISC11) | (1 << ISC01); // for INT1 and INT0

      // Activate INT1 and INT0, according to the datasshet, page 72, section 13.2.2
      EIMSK |= (1 << INT1) | (1 << INT0);

      // Activate global interrupt flag
      sei();
}

 

My ISR are in file freq_sweep.c:

/*
 * ISR routines
 */
ISR(INT0_vect){
   sweep_dir = 0;
}

ISR(INT1_vect){
   sweep_dir = 1;
}

 

The following code is the code which is checking if the interrupt flags are triggered and that never happens to be true and it's inside the main() function infinite loop

project.c

int main(void){
    //some code here

   for( ; ;){
      if( (EIFR & (1 << INT1)) || (EIFR & (1 << INT0)) ){
         freq_sweep(&current_freq_value);
         lcd_gotoxy(0, 3); // For debug
         lcd_puts("Test!");// For debug
      }

       //some more code here

      // This prints the sweep_dir value that is changed by the ISR in the previous code, and it actually changes when I press the buttons. 0 or 1 is printend on the LCD
      lcd_gotoxy(6, 3);
      dtostrf(sweep_dir, 1, 0, tmp);
      lcd_puts(tmp);
      _delay_ms(2000);
   }
}

 

 

So, summarising it all:

The ISR is working, they are being triggered, but for some reason the below condition 

if( (EIFR & (1 << INT1)) || (EIFR & (1 << INT0)) )

is not happening to be true ever, therefore the freq_sweep() function is never being called!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Testing the INT1 and INT0 flags in main() will not work. The ISRhas already run, and according to the data sheet (p 91, section 17.2.3) "The flag is cleared when the interrupt routine is executed".

Happy 75th anniversary to one of the best movies ever made! Rick Blane [Bogart]: "Of all the gin joints, in all the towns, in all the world, she walks into mine."

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So, my only alternative is to execute code inside the ISR?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Set a flag in the ISR

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:
So, my only alternative is to execute code inside the ISR?

??? "Only"?

 

Of course not.  But what is it that you intend to accomplish?

 

1)  Buttons bounce.  So in any real application, one would not rely on an external interrupt to act on them.  [It might be the case that an external interrupt is used to wake from sleep, but then the debouncing sequence continues.  But surely you know that from reading similar posts/threads on this forum.]

 

2)  Given the above, the only ISR I'd use for that purpose is ~10ms "tick" to serve as time base for debouncing.

 

3) "Execute code"?  You already "execute code" in the ISR.

 

As I said, chances are that you will run into problems without debouncing.  But if you insist, then "volatile" [it >>is<< volatile, isn't it?] sweep_dir can be set to a flag value indication the ISR has been processed and that can be tested in the mainline.

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Set a flag in the ISR

OP sets the variable sweep_dir in the ISRs, but ignores it in main().  The declaration of sweep_dir is not shown, but something tells the keyword volatile is not used... 

Greg Muth

Portland, OR, US

Atmel Studio 7.0 on Windows 10

Xplained/Pro/Mini Boards mostly

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:

PsySc0rpi0n wrote:
So, my only alternative is to execute code inside the ISR?

??? "Only"?

 

Of course not.  But what is it that you intend to accomplish?

 

1)  Buttons bounce.  So in any real application, one would not rely on an external interrupt to act on them.  [It might be the case that an external interrupt is used to wake from sleep, but then the debouncing sequence continues.  But surely you know that from reading similar posts/threads on this forum.]

 

2)  Given the above, the only ISR I'd use for that purpose is ~10ms "tick" to serve as time base for debouncing.

 

3) "Execute code"?  You already "execute code" in the ISR.

 

As I said, chances are that you will run into problems without debouncing.  But if you insist, then "volatile" [it >>is<< volatile, isn't it?] sweep_dir can be set to a flag value indication the ISR has been processed and that can be tested in the mainline.

 

 

 

The buttons are supposed to do a frequency sweep... For each time button1 is pressed, the frequency is decreased by some FREQ_STEP that I have set in the code and when button2 is pressed, the same frequency is increased by that same FREQ_STEP.

That is the purpose of those 2 buttons I have in the circuit attached to INT0 and INT1 pins.

 

1) The only thread I read about interrupts is the [TUT] Newbie's Guide to AVR Interrupts thread. And that tutorial is a very basic one that do not cover many situations.

2) I do not understand what a ~10ms "tick" is to serve as base for debouncing because I don't understand what a debounce is. I'm sorry.

3) Yes, I execute a minimal attribution there! But that's all! What I meant was that I would have to execute the function freq_sweep() inside the ISR.

 

Greg_Muth wrote:

Set a flag in the ISR

OP sets the variable sweep_dir in the ISRs, but ignores it in main().  The declaration of sweep_dir is not shown, but something tells the keyword volatile is not used... 

 

That variable has another purpose in the code! And it's declared as an "extern volatile" data type in freq_sweep.h file which I have not pasted here!

 

So, the solution I see is to set another variable inside the ISR to indicate the interrupt was triggered and check that variable in main...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You're still ignoring bouncing.  You could easily get 5 to 50 interrupts on one button push.  Learn how to use timer-based polling to read buttons.  Furthermore, and as you note, any variable shared between ISRs and main (background) code must be declared 'volatile'.  In addition, all accesses to shared variables must be atomic.  This happens automatically for byte-sized variables on an 8-bit architecture, but for any larger variables (int, long, etc) you must protect all background code accesses to the variable from an interrupt that can modify it.  Usually something as simple as: 

// in background code
cli();
temp = shared_isr_variable;
sei();
// use temp now in place of shared_isr_variable

 

Last Edited: Sun. Sep 17, 2017 - 04:19 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Greg_Muth wrote:
OP sets the variable sweep_dir in the ISRs, but ignores it in main().

Not really. He is actually using it in a printf() call, and claims that the correct/expected value is shown on the display:

      // This prints the sweep_dir value that is changed by the ISR in the previous code, and it actually changes when I press the buttons. 0 or 1 is printend on the LCD
      lcd_gotoxy(6, 3);
      dtostrf(sweep_dir, 1, 0, tmp);
      lcd_puts(tmp);

 

This also hints at the variable actually being declared volatile. 

 

I still claim his problem (and this fits with his description) is with

 

      if( (EIFR & (1 << INT1)) || (EIFR & (1 << INT0)) ){
         freq_sweep(&current_freq_value);
         lcd_gotoxy(0, 3); // For debug
         lcd_puts("Test!");// For debug
      }

in main(). He claims that "Test!" is never printed. This then made him to think that something is wrong with the ISRs, but it is not. The ISRs are executing just fine. As I've quoted from the data sheet, those flags are "cleared when the interrupt routine is executed", so by the time execution returns to main() and the test above they are cleared.

 

It is not entirely clear what the final code is actually to do, but if it is about changing the sweep direction, then button bouncing is not a problem since there are two separate buttons for the two directions. I.e. if "UP" is pressed then the sweep_dir is set to 1. Now the button bounces, but it has no malign effects - the sweep_dir will simply be set to 1 several times. (This is what I'd like to call "Bob debouncing" since Bob Gardner has, correctly IMO, pointed out several times that this is often sufficient where something has separate On and Off buttons.)

 

With my speculation on what the requirements/specification actually is I''d say that is is enough to simply set sweep_dir in the ISRs. My only speculative question is: Is a STOP button also needed? No problem as such, only curious. If the actual possible states are "decreasing", "stopped" and "increasing" - governed by three buttons then I would probably have sweep_dir being an int8_t and in the ISRs for the tree buttons set it to -1, 0 or 1 respectively.

 

The lessons for the OP is:

 

  • Always post a minimal but complete program  that builds and runs and demonstrates the problem. In this case we're more or less only missing the declaration of the variable sweep_dir! 
  • Possibly explain what the system is actually intended to do.

 

With that, a lot of the guess-work above could have been avoided and the matter already closed.

 

PsySc0rpi0n wrote:
So, my only alternative is to execute code inside the ISR?

As I see it, yes. And it would more or less be the code you've already put into them - as in your first post. Not more. Just a variable assignment.

 

In main() you test on that variable, rather than on the flags in the register.

Happy 75th anniversary to one of the best movies ever made! Rick Blane [Bogart]: "Of all the gin joints, in all the towns, in all the world, she walks into mine."

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Sun. Sep 17, 2017 - 04:28 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kk6gm wrote:

You're still ignoring bouncing.  You could easily get 5 to 50 interrupts on one button push.  Learn how to use timer-based polling to read buttons.  Furthermore, and as you note, any variable shared between ISRs and main (background) code must be declared 'volatile'.  In addition, all accesses to shared variables must be atomic.  This happens automatically for byte-sized variables on an 8-bit architecture, but for any larger variables (int, long, etc) you must protect all background code accesses to the variable from an interrupt that can modify it.  Usually something as simple as: 

// in background code
cli();
temp = shared_isr_variable;
sei();
// use temp now in place of shared_isr_variable

 

 

Here we go again... It's my 2nd post and I'm already being thrown at with criticism, not to use other words...

Have you read all my post? If so, how can you say I still ignore "buttons bounce"??? I have said in my previous post that I didn't understood what "buttons bounce" is!

Last Edited: Sun. Sep 17, 2017 - 04:34 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I repeat: In this case it is not certain that button bounce is a problem. Pushing the on-switch a second time wont make my microwave oven start more than it already is.

 

Someone here has in his footer (or has posted repeatedly) something like "engineering is about making things as simple ass possible, but not simpler than that". I still argue that "as simple as possible" here might to let the buttons bounce all they like. It depends on if my speculation of the system specifications are (i.e. separate buttons for "increase" and "decrease") and if the waste of CPU cycles is benign or not.

 

If the ISRs are long, and the application is "short on CPU cycles" then executing the ISR more than once for a press of a button, due to the button bouncing, might be a problem. But we don't know that since the OP has not told us anything about how the finished system is actually supposed to behave.

 

Again, at the OP: Set your variable in your ISRs. Test on the variable value (not the interrupt flags) in main(). Make the variable volatile and 8 bits wide, not wider.

 

When your requirements change and you need a toggling button then bouncing will definitively be a problem. Then come back here and ask.

 

EDIT: I stand corrected. In the hectic traffic in this thread I missed the statement from the OP that each time the button is pressed the frequency should be increased (or decreased). Button bounce will definitively be a problem.

 

So, to the OP, on the subject of button bounce and "debouncing":

 

When a switch-button is pressed it makes and breaks contact several time during a short period - on the order of a few microseconds or so. If you use interrupts for detecting buttons closing then you will see several consecutive interrupts. This means that while the user expects the frequency to decrease with, say, 1 Hz it might hop down 2 or 3 Hz because the ISR was activated several times.

 

Button bounce is such a common problem that a few techniques have been devised for handling it, and the process is often referred to as "debouncing". Most of the approaches does debouncing by simply polling the switches repeatedly, perhaps every 5 or 10 ms and require to see the switch in the new state perhaps 4 times in order to deem it having done it's bouncing. For a human user the 25 ms or so it takes (between the start of the button press and the actual reaction of the system) is not detectable. So instead of relying on edge interrupts you rely on a timer interrupt and polling.

 

Put this into Google: "button bounce debounce site:www.avrfreaks.net" and you will have some reading to do (-:

 

It is not likely that anyone will take on a detailed discussion on button bounce and debouncing. We've had it more times than we can count and everything that can be said has already been said. Do the search and read. Allocate an entire evening or so for this - there's a lot to read. Then come back with any questions.

 

(If you want my favorite deboucer then put this into Google: "danni debounce site:www.avrfreaks.net". Others might disagree on that being the favourite. YMMV.)

Happy 75th anniversary to one of the best movies ever made! Rick Blane [Bogart]: "Of all the gin joints, in all the towns, in all the world, she walks into mine."

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Sun. Sep 17, 2017 - 04:52 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, about the code, as it has several files, it's hard to past it all here. Therefore I'll past the Github link!

 

I've made some changes and the buttons are already working.

 

Now, I still have other bugs in the code that I will try to address next!

 

https://github.com/PsySc0rpi0n/P...

 

Mr. JohanEkdahl, about sweep_dir, yes, it has 3 states, UP, DOWN and UNDEF. I have only 2 buttons. One for up and another for down. The range of frequencies are like cyclic! When it reaches the max limit, it drops down to the minimum limit.

I have added a new flag, sweep_sta that will hold the interrupt triggering event and that I check in main().

 

You guys can now see the declarations and all the code!

Last Edited: Sun. Sep 17, 2017 - 04:51 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:
Ok, about the code, as it has several files, it's hard to past it all here.

No. It is your job to reduce the code to the minimal that demonstrates the problem.

 

PsySc0rpi0n wrote:
Therefore I'll past the Github link!

Generally, it is not appreciated to do that. If you reduce the code to the minimal then it will be small enough to post here.

 

This is just the ordinary way engineers solve problems. Remove everything that has nothing to do with the core problem so as to rule out un-necessary complexity and complications.

Happy 75th anniversary to one of the best movies ever made! Rick Blane [Bogart]: "Of all the gin joints, in all the towns, in all the world, she walks into mine."

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That is hard, but I'll try... The code is all interconnected, so it will be hard to break it into parts to paste here only the code that is problematic!

 

 

My project has the following files:

project.c -> main() is in this file

signal_gen.c

adc.c

sweep_freq.c

lcd.c

signal_gen.h

adc.h

sweep_freq.h

lcd.h

 

 

Ok, for project.c, the code of interest I think it's this:

 

int main(void){
   float vswr_val = 0;
   char tmp[BUFFER];
   uint64_t inital_freq_value = 10e5,
            current_freq_value  = inital_freq_value;

// yet some code here but not of interest

    interrupt_setup();

// yet some code here but not of interest

    for( ; ;){
      if(sweep_sta != SWEEP_STA_UNDEF){
         freq_sweep(current_freq_value);
         lcd_gotoxy(0, 3);              // For debug
         lcd_puts("Test!");             // For debug
         lcd_gotoxy(6, 3);              // For debug
         dtostrf(sweep_dir, 1, 0, tmp); // For debug
         lcd_puts(tmp);                 // For debug
         _delay_ms(2000);
         sweep_dir = SWEEP_DIR_UNDEF;
      }
      
      // yet some code here but not of interest
}

 

For freq_sweep.c, the code of interest is:

#include <avr/interrupt.h>
#include <avr/io.h>

#include "signal_gen.h"
#include "freq_sweep.h"
#include "lcd.h"

#define FREQ_MAX 39000000
#define FREQ_MIN     1000
#define FREQ_STEP  100000

volatile uint8_t sweep_dir = SWEEP_DIR_UNDEF;
volatile uint8_t sweep_sta = SWEEP_STA_UNDEF;

void interrupt_setup(void){
      // Set interrupts to trigger on falling edges, according to the datasshet, page 71, section 13.2.1
      EICRA |= (1 << ISC11) | (1 << ISC01); // for INT1 and INT0

      // Activate INT1 and INT0, ccording to the datasshet, page 72, section 13.2.2
      EIMSK |= (1 << INT1) | (1 << INT0);

      // Activate global interrupt flag
      //SREG |= (1 << SREGI);
      sei();
}

/*
 *Function that sweeps frequency by external interrupt source
 */
void freq_sweep(uint64_t current_freq_val){
   uint64_t updated_freq_val = current_freq_val;
   if(sweep_dir == SWEEP_DIR_UP){
      if( (updated_freq_val + FREQ_STEP) > FREQ_MAX)
         updated_freq_val = FREQ_MIN;
      else
         updated_freq_val += FREQ_STEP;
   }else{
      if( (updated_freq_val - FREQ_STEP) < FREQ_MIN)
         updated_freq_val = FREQ_MAX;
      else
         updated_freq_val -= FREQ_STEP;
   }

   freq_send(updated_freq_val);
   sweep_sta = SWEEP_STA_OFF;
}


/*
 * ISR routines
 */
ISR(INT0_vect){
   sweep_sta = SWEEP_STA_ON;
   sweep_dir = SWEEP_DIR_DOWN;
}

ISR(INT1_vect){
   sweep_sta = SWEEP_STA_ON;
   sweep_dir = SWEEP_DIR_UP;
}

 

For freq_sweep.h, the code is:

 

#define SWEEP_STA_OFF   0
#define SWEEP_STA_ON    1
#define SWEEP_STA_UNDEF 2

#define SWEEP_DIR_UP    1
#define SWEEP_DIR_DOWN  0
#define SWEEP_DIR_UNDEF 2

extern volatile uint8_t sweep_dir;
extern volatile uint8_t sweep_sta;

void interrupt_setup(void);
void freq_sweep(uint64_t current_freq_value);

 

I think this is all the code of interest...

Last Edited: Sun. Sep 17, 2017 - 05:25 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:
as it has several files, it's hard to past it all here.

Does that not already ring some kind of alarm bell?
.
In well designed, modular code you'd keep everything to do with button input in a single file/module that could easily be tested in isolation. The only "public bit" being the final interface presented to the rest of the code. Don't wire it up like spaghetti with bits of the operation all over the place or, as you just proved, it gets very tricky to develop, debug and test.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:
That is hard

Think of it like this: If it was easy, then anyone could do it.. ;-)

 

Don't fear challenges - enjoy them!

Happy 75th anniversary to one of the best movies ever made! Rick Blane [Bogart]: "Of all the gin joints, in all the towns, in all the world, she walks into mine."

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
PsySc0rpi0n wrote:
as it has several files, it's hard to past it all here.
Does that not already ring some kind of alarm bell? . In well designed, modular code you'd keep everything to do with button input in a single file/module that could easily be tested in isolation. The only "public bit" being the final interface presented to the rest of the code. Don't wire it up like spaghetti with bits of the operation all over the place or, as you just proved, it gets very tricky to develop, debug and test.

 

Indeed... I tried to split the code in different files exactly to try to make it modular. one file takes care of ADC stuff, other file takes care of DDS module in the circuit and the other file takes care of buttons pressing and their intended actions!

The catch is that in some files, are used functions from other files, like in sweep_freq.c I'm using functions from signal_gen.c file.

 

JohanEkdahl wrote:

PsySc0rpi0n wrote:
That is hard

Think of it like this: If it was easy, then anyone could do it.. ;-)

 

Don't fear challenges - enjoy them!

 

Thank you. I like your reasoning!

 

My code cannot work if I try to set part of the code aside! That's why I said it would be complicated to split the code to past here only the problematic code and yet make it work by compiling it and uploading it to the uC!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:

kk6gm wrote:

You're still ignoring bouncing.  You could easily get 5 to 50 interrupts on one button push.  Learn how to use timer-based polling to read buttons.  Furthermore, and as you note, any variable shared between ISRs and main (background) code must be declared 'volatile'.  In addition, all accesses to shared variables must be atomic.  This happens automatically for byte-sized variables on an 8-bit architecture, but for any larger variables (int, long, etc) you must protect all background code accesses to the variable from an interrupt that can modify it.  Usually something as simple as: 

// in background code
cli();
temp = shared_isr_variable;
sei();
// use temp now in place of shared_isr_variable

 

 

Here we go again... It's my 2nd post and I'm already being thrown at with criticism, not to use other words...

Have you read all my post? If so, how can you say I still ignore "buttons bounce"??? I have said in my previous post that I didn't understood what "buttons bounce" is!

 

We don't just post for the OP.  We post for anybody else who might be reading and face similar problems.  And it's not criticism, it's helpful advice, learned over many years.  You're welcome.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kk6gm wrote:

PsySc0rpi0n wrote:

kk6gm wrote:

You're still ignoring bouncing.  You could easily get 5 to 50 interrupts on one button push.  Learn how to use timer-based polling to read buttons.  Furthermore, and as you note, any variable shared between ISRs and main (background) code must be declared 'volatile'.  In addition, all accesses to shared variables must be atomic.  This happens automatically for byte-sized variables on an 8-bit architecture, but for any larger variables (int, long, etc) you must protect all background code accesses to the variable from an interrupt that can modify it.  Usually something as simple as: 

// in background code
cli();
temp = shared_isr_variable;
sei();
// use temp now in place of shared_isr_variable

 

 

Here we go again... It's my 2nd post and I'm already being thrown at with criticism, not to use other words...

Have you read all my post? If so, how can you say I still ignore "buttons bounce"??? I have said in my previous post that I didn't understood what "buttons bounce" is!

 

We don't just post for the OP.  We post for anybody else who might be reading and face similar problems.  And it's not criticism, it's helpful advice, learned over many years.  You're welcome.

 

When you said I was "still ignoring" button bounce, you clearly demonstrated you didn't read my whole post. Otherwise you would have seen that I did not ignored it. I replied to that matter!

 

Appreciate advises but that was not an advice!

 

Anyway, I'm now trying to fix the code using everything that was said here about button bounce and debouncing! I'm reading about it and I'm also trying to figure out a new problem I have just detected. My DDS module is not outputting a sine wave!

 

Thanks

Psy

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here's a tutorial  on debouncing, part of a larger set of tutorials I wrote some time back.

https://www.embeddedrelated.com/...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kk6gm wrote:

Here's a tutorial  on debouncing, part of a larger set of tutorials I wrote some time back.

https://www.embeddedrelated.com/...

 

Thanks.

I appreciate|

 

Psy