ATmega328P - PCINT0_vect is never called

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

Hey guys,

 

my goal is to have 4 push buttons (PB1-PB4) and wait for interrupts they will cause while being pushed. It's a very very easy thing to do, I'm aware of that but still, when I push any button, my ATmega328P (on Arduino UNO board) resets. I came up with a workaround (found it somewhere here, on avrfreaks of course :D ) - to use ISR(__vector_default). When is use it, my uC never resets but always goes to this routine when a button is pushed. My guess is that for some reason the compiler does not include the ISR routine for PCINT0_vect. Here is my code (if you leave ISR(__vector_default) all interrupts will go there and if you delete this routine, the atmega will reset on every button pin change).

 

/*
* Buttons.c
*
* Created: 22.11.2017 17:14:12
* Author : Daniel
*/

#define F_CPU 16000000UL

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

#define BUTTON_RED PB1
#define BUTTON_BLUE PB2
#define BUTTON_YELLOW PB3
#define BUTTON_GREEN PB4

#define BUTTON_RED_INDEX 0
#define BUTTON_BLUE_INDEX 1
#define BUTTON_YELLOW_INDEX 2
#define BUTTON_GREEN_INDEX 3

#define BUTTON_REG DDRB
#define BUTTON_PORT PORTB

void initButtons()
{
	BUTTON_REG &= ~((1 << BUTTON_RED) | (1 << BUTTON_BLUE) | (1 << BUTTON_YELLOW) | (1 << BUTTON_GREEN));
	BUTTON_PORT |= (1 << BUTTON_RED) | (1 << BUTTON_BLUE) | (1 << BUTTON_YELLOW) | (1 << BUTTON_GREEN);

	USART_SendLine("buttons initialized");
}

void initInterrupts()
{
	PCMSK0 |= (1 << PCINT1) | (1 << PCINT2) | (1 << PCINT3) | (1 << PCINT4);
	PCICR|= (1 << PCIE0);
	sei();

	USART_SendLine("interrupts initialized");
}

ISR(__vector_default)
{
	cli();
	USART_SendLine("default isr");
	sei();
}

ISR(PCINT0_vect)
{
	cli();
	USART_SendLine("pcint0 isr");
	sei();
}

int main(void)
{
	USART_Init();
	initButtons();
	initInterrupts();

	USART_SendLine("hello!");

	while (1)
	{
	}

	USART_SendLine("exiting main");

	return 0;
}

Here is my USART code:

/*
 * UART.h
 *
 * Created: 23.10.2017 20:11:58
 *  Author: Daniel
 */ 

#ifndef UART_H_
#define UART_H_

void USART_Init();
void USART_SendByte(unsigned char data);
void USART_SendString(char* data);
void USART_SendLine(char* data);
unsigned char USART_ReceiveByte();

#endif /* UART_H_ */
/*
 * USART.c
 *
 * Created: 23.10.2017 20:35:00
 *  Author: Daniel
 */ 

#define F_CPU 16000000UL
#define BAUD_RATE 9600
#define UBRR0_VALUE ((F_CPU / (16UL * BAUD_RATE)) - 1)

#include <avr/io.h>
#include "USART.h"

void USART_Init()
{
	UBRR0 = UBRR0_VALUE;
	UCSR0B |= (1 << RXEN0) | (1 << TXEN0);
	UCSR0C |= (1 << UCSZ00) | (1 << UCSZ01);

	USART_SendLine("usart initialized");
}

void USART_SendByte(unsigned char data)
{
	while(!(UCSR0A & (1 << UDRE0)));
	UDR0 = data;
}

void USART_SendString(char* data)
{
	while(*data != 0x00)
	{
		USART_SendByte(*data);
		data++;
	}
}

void USART_SendLine(char* data)
{
	USART_SendString(data);
	USART_SendByte('\r');
	USART_SendByte('\n');
}

unsigned char USART_ReceiveByte()
{
	while(!(UCSR0A & (1 << RXC0)));
	return UDR0;
}

Here is my build log, maybe it'll tell you something more than I get from it.

------ Build started: Project: Buttons, Configuration: Debug AVR ------
Build started.
Project "Buttons.cproj" (default targets):
Target "PreBuildEvent" skipped, due to false condition; ('$(PreBuildEvent)'!='') was evaluated as (''!='').
Target "CoreBuild" in file "P:\Atmel Studio 7.0\7.0\Vs\Compiler.targets" from project "D:\Dokumenty\Praca\Exitus\repos\SafeWithButtons\Buttons\Buttons.cproj" (target "Build" depends on it):
    Task "RunCompilerTask"
        Shell Utils Path P:\Atmel Studio 7.0\7.0\shellUtils
        P:\Atmel Studio 7.0\7.0\shellUtils\make.exe all --jobs 8 --output-sync
        Building file: .././main.c
        Invoking: AVR/GNU C Compiler : 5.4.0
        "P:\Atmel Studio 7.0\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe"  -x c -funsigned-char -funsigned-bitfields -DDEBUG  -I"P:\Atmel Studio 7.0\7.0\Packs\atmel\ATmega_DFP\1.2.150\include"  -O1 -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -g2 -Wall -mmcu=atmega88pa -B "P:\Atmel Studio 7.0\7.0\Packs\atmel\ATmega_DFP\1.2.150\gcc\dev\atmega88pa" -c -std=gnu99 -MD -MP -MF "main.d" -MT"main.d" -MT"main.o"   -o "main.o" ".././main.c"
        Finished building: .././main.c
        Building file: .././USART.c
        Invoking: AVR/GNU C Compiler : 5.4.0
        "P:\Atmel Studio 7.0\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe"  -x c -funsigned-char -funsigned-bitfields -DDEBUG  -I"P:\Atmel Studio 7.0\7.0\Packs\atmel\ATmega_DFP\1.2.150\include"  -O1 -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -g2 -Wall -mmcu=atmega88pa -B "P:\Atmel Studio 7.0\7.0\Packs\atmel\ATmega_DFP\1.2.150\gcc\dev\atmega88pa" -c -std=gnu99 -MD -MP -MF "USART.d" -MT"USART.d" -MT"USART.o"   -o "USART.o" ".././USART.c"
        Finished building: .././USART.c
        Building target: Buttons.elf
        Invoking: AVR/GNU Linker : 5.4.0
        "P:\Atmel Studio 7.0\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe" -o Buttons.elf  main.o USART.o   -Wl,-Map="Buttons.map" -Wl,--start-group -Wl,-lm  -Wl,--end-group -Wl,--gc-sections -mmcu=atmega88pa -B "P:\Atmel Studio 7.0\7.0\Packs\atmel\ATmega_DFP\1.2.150\gcc\dev\atmega88pa"
        Finished building target: Buttons.elf
        "P:\Atmel Studio 7.0\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objcopy.exe" -O ihex -R .eeprom -R .fuse -R .lock -R .signature -R .user_signatures  "Buttons.elf" "Buttons.hex"
        "P:\Atmel Studio 7.0\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objcopy.exe" -j .eeprom  --set-section-flags=.eeprom=alloc,load --change-section-lma .eeprom=0  --no-change-warnings -O ihex "Buttons.elf" "Buttons.eep" || exit 0
        "P:\Atmel Studio 7.0\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objdump.exe" -h -S "Buttons.elf" > "Buttons.lss"
        "P:\Atmel Studio 7.0\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objcopy.exe" -O srec -R .eeprom -R .fuse -R .lock -R .signature -R .user_signatures "Buttons.elf" "Buttons.srec"
        "P:\Atmel Studio 7.0\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-size.exe" "Buttons.elf"
           text       data        bss        dec        hex    filename
            412         92          0        504        1f8    Buttons.elf
    Done executing task "RunCompilerTask".
    Task "RunOutputFileVerifyTask"
                Program Memory Usage     :    504 bytes   6,2 % Full
                Data Memory Usage         :    92 bytes   9,0 % Full
    Done executing task "RunOutputFileVerifyTask".
Done building target "CoreBuild" in project "Buttons.cproj".
Target "PostBuildEvent" skipped, due to false condition; ('$(PostBuildEvent)' != '') was evaluated as ('' != '').
Target "Build" in file "P:\Atmel Studio 7.0\7.0\Vs\Avr.common.targets" from project "D:\Dokumenty\Praca\Exitus\repos\SafeWithButtons\Buttons\Buttons.cproj" (entry point):
Done building target "Build" in project "Buttons.cproj".
Done building project "Buttons.cproj".

Build succeeded.

Any ideas? :(

 

Daniel

 

PS:
1. I do have a 100nF capacitor for every button.

2. I tried to run this code on ATmega88PA as well - worked the same as on ATmega328P.

Last Edited: Fri. Nov 24, 2017 - 05:48 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Aranha wrote:
PCMSK0 |= (1 << PCINT1) | (1 << PCINT2) | (1 << PCINT3) | (1 << PCINT4);

You enable PCINT1 - PCINT4, but buttons are on PCINT0 - PCINT3.

 

You (typically) should not disable (cli) and re-enable (sei) interrupts with the ISR.

 

Edit: added strikethru, I misread BUTTON_RED_INDEX as the pin location

 

 

David

Last Edited: Fri. Nov 24, 2017 - 06:01 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Do >>NOT<< put cli/sei in your ISR code.  The hardware does that for you.  The sei you have placed in your ISR code means that the ISR itself will get interrupted by additional interrupts when the button you press bounces.

 

And as a rule, don't call other functions from within an ISR, especially something extremely slow like a USART send function.

 

1. I do have a 100nF capacitor for every button.

Why?  More to the point, how is it connected?  If from input pin to GND (i.e. across the button), then this will lead to early button failure.

 

You're probably trying to minimise bounce in hardware.  That  can be done, but not with single capacitor.  And debouncing is usually done in software more effectively.

 

Your build output shows a build for the m88.  Are you certain that you built for the m328p, and that this is what you flashed to the m328p?  If you flashed code built for the m88 onto an m328, it will not work.  Your symptoms could be explained by this.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Fri. Nov 24, 2017 - 06:06 PM