PCINT - ask for help!

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

I want to toggle a led on ATmega328p by button through PCINT, my code:

// A program for LED Toggle by Push-button and PCINT on ATmega328p

 /*
 * LED toggle by button
 * LED - 1.5Kohm - D8(PB0)
 * BUTTON - D7(PD7/PCINT23) - 10Kohm - 5v(VCC)
 * BUTTON - GND
 */


#define F_CPU 16000000UL

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

volatile uint8_t pinb = 0;

int main(void){
  //DDRB &= ~(1<<DDB0);
  DDRB |= (1<<PINB0);
  //DDRD |= (1<<DDD7);
  DDRD &= ~(1<<PIND7);

  PCICR = (1<<PCIE2);
  //PCICR = 0x00000100; // Pin Change Interrupt Enable 2
  PCMSK2 = (1<<PCINT23);  //0x10000000; PCINT23 enabled
  //PCMSK2 = (1<<PIND7);

  while(true){
    ;
  }
}

ISR(PCINT2_vect)
{
  pinb = PINB;
  PORTB = PINB ^ pinb;
}

 

It didn't work, any suggestion?

This topic has a solution.
Last Edited: Wed. Aug 3, 2022 - 01:09 AM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
  pinb = PINB;
  PORTB = PINB ^ pinb;

What are you trying to achieve here ? Toggling (when using the PINB feature) should be as simple as:

PINB = (1 << PINB0);

You just write a 1 bit for any bit position that you want to toggle. Simple as that.

 

Also I know my eyesight is failing but I don't see any point in your code where you call sei() to switch on the interrupting system ?

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

clawson wrote:

  pinb = PINB;
  PORTB = PINB ^ pinb;

What are you trying to achieve here ?

 

 

I want the bit position I want to toggle XOR with itself, thus get a toggle - I push button LED on, I push button the 2nd time, LED off, the 3rd time, On....

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

Your code "looks" ok but there is no sei() and the ISR() is pointless.

 

You normally examine the "input" to check for rising edge or falling edge.   PCINT always fires on both.

You only need to toggle on one edge.   Otherwise two toggles puts you back where you started.

 

e.g.

ISR(PCINT2_vect)

{

    uint8_t rising = PIND & (1 << 7);

    if (rising) PORTB ^= (1 << 0);

}

 

Untested.  Easy to test in the Simulator.   But just as simple on your real hardware.

 

Note that the Simulator is "safer" because you avoid switch bouncing.

Otherwise you might get an even or odd number of bounces.

 

David.

 

Edit. You probably choose falling for an active-low push button.   Rising for an active-high switch.

 

Last Edited: Mon. Aug 1, 2022 - 10:33 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As a general rule, using interrupts for push buttons is a bad idea, due to the switch bounce...

However, it is common to use the PCINT to wake a sleeping AVR, and then poll the state of the switch....

 

The others gave you the solution your looking for.

 

Jim

 

 

FF = PI > S.E.T

 

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

I tested,

PINB = (1 << PINB0);

works, and:

ISR(PCINT2_vect)

{

    uint8_t rising = PIND & (1 << 7);

    if (rising) PORTB ^= (1 << 0);

}

would get the refection I wanted.

and "

As a general rule, using interrupts for push buttons is a bad idea, due to the switch bounce...

However, it is common to use the PCINT to wake a sleeping AVR, and then poll the state of the switch

" was also right, since the former 2 codes were all have some disorder detection.