SAM4S Xplained Pro Buttons Demo2018-10-19T06:22:59+00:00

ASF version

Tested for ASF version 3.31.0

ASF Modules required 

  • Same as Parallel IO

Basic Demo

The Button Demo toggles LEDs when buttons are pressed. The drivers allow to set a “cut-off frequency for the de-bouncing filter” as the last parameter of pio_set_debounce_filter.

See Buttons Demo.

 

Code
#include <asf.h>

#define LED1  IOPORT_CREATE_PIN(PIOC, 20);
#define LED2  IOPORT_CREATE_PIN(PIOA, 16);
#define LED3  IOPORT_CREATE_PIN(PIOC, 22);

void Button_Handler(uint32_t id, uint32_t mask)
{
	uint32_t led;

	if ( ID_PIOA == id && PIO_PA0 == mask ){ led = LED1; }
	else if( ID_PIOC == id && PIO_PC29 == mask ){ led = LED2; }
	else if( ID_PIOC == id && PIO_PC30 == mask ){ led = LED3; }
	else { return; }
	
	ioport_set_pin_level( led, !ioport_get_pin_level(led) );
}

const uint32_t irq_priority = 5;
void configure_buttons(void)
{
	//Configure Pushbutton 1
	pmc_enable_periph_clk(ID_PIOA);
	pio_set_debounce_filter(PIOA, PIN_PUSHBUTTON_1_MASK, 10);
	pio_handler_set(PIOA, ID_PIOA,
	PIN_PUSHBUTTON_1_MASK, PIN_PUSHBUTTON_1_ATTR, Button_Handler);
	NVIC_EnableIRQ((IRQn_Type) ID_PIOA);
	pio_handler_set_priority(PIOA, (IRQn_Type) ID_PIOA, irq_priority);
	pio_enable_interrupt(PIOA, PIN_PUSHBUTTON_1_MASK);

	//Configure Pushbutton 2
	pmc_enable_periph_clk(ID_PIOC);
	pio_set_debounce_filter(PIOC, PIN_PUSHBUTTON_2_MASK, 10);
	pio_handler_set(PIOC, ID_PIOC,
	PIN_PUSHBUTTON_2_MASK, PIN_PUSHBUTTON_2_ATTR, Button_Handler);
	NVIC_EnableIRQ((IRQn_Type) ID_PIOC);
	pio_handler_set_priority(PIOC, (IRQn_Type) ID_PIOC, irq_priority);
	pio_enable_interrupt(PIOC, PIN_PUSHBUTTON_2_MASK);

	//Configure Pushbutton 3
	pmc_enable_periph_clk(ID_PIOC);
	pio_set_debounce_filter(PIOC, PIN_PUSHBUTTON_3_MASK, 10);
	pio_handler_set(PIOC, ID_PIOC,
	PIN_PUSHBUTTON_3_MASK, PIN_PUSHBUTTON_3_ATTR, Button_Handler);
	NVIC_EnableIRQ((IRQn_Type) ID_PIOC);
	pio_handler_set_priority(PIOC, (IRQn_Type) ID_PIOC, irq_priority);
	pio_enable_interrupt(PIOC, PIN_PUSHBUTTON_3_MASK);
}

int main(void){
	sysclk_init();
	board_init();
	configure_buttons();
	
	while(1);

}

 

Advanced Demo

[TO DO: Fix this explanation. Makes no sense.]

This demo uses an external button connected to PA24. When pressed a light bulb is toggled via a solid state relay (Sharp S108T02) sitting between PA25 and the light bulb. PA25 has its own interrupt configured to avoid busy-waiting. On every interrupt PA24 drives the Solid state relay’s internal LED on/off, when this happens the circuit is closed and the light turns on/off (a resistor is needed between PA25 and the S10802’s internal LED). The input taken from PA25 is similar, one side of the red button is wired to 5v while the other end is wired to PA25. When the button is pressed PA25 goes high and an interrupt is generated. When the button is not pressed PA25 is not connected to anything. It is not low and it is not high—it is open. This can be a problem as the value on the pin will be changing over and over thereby generating random interrupts. To always read a value we expect we add either pull up or pull down resistors to the circuit. The MCU can do it internally on command. The demo sets PA25 with a pull down resistor so that when the button is not pressed a digital 0 is read. More information here and here.

Also the de-bouncer filter cut off value has been set to 10ms (see page 565 of SAM4S datasheet). Despite of it too many false presses were occurring. Therefore a ceramic capacitor of 0.1 uF (104 value written in it) was added to minimize false pulses. The video demonstrates the results with the ceramic capacitor.

See Red Button Demo

Code
#include <asf.h>

#define RED_BUTTON  	IOPORT_CREATE_PIN(PIOA, 24) //EXT1 pin 5
#define LAMP	IOPORT_CREATE_PIN(PIOA, 25) //EXT1 pin 6

#define RED_BUTTON_ATTR ( PIO_DEBOUNCE | PIO_IT_RISE_EDGE)
#define RED_BUTTON_MASK PIO_PA24
#define DEBOUNCE_THRESHOLD 50 //50ms

static void RedButton_Handler(uint32_t id, uint32_t mask){
	if ( ID_PIOA == id && PIO_PA24 == mask ){
		//toggle lamp
		ioport_set_pin_level( LAMP, !ioport_get_pin_level(LAMP) );
	}	
}

const uint32_t irq_priority = 5;
void configure_button_int(void){
	
	pio_set_debounce_filter(PIOA, RED_BUTTON_MASK, DEBOUNCE_THRESHOLD);
	pio_handler_set(PIOA, ID_PIOA,
	RED_BUTTON_MASK, RED_BUTTON_ATTR, RedButton_Handler);
	NVIC_EnableIRQ((IRQn_Type) ID_PIOA);
	pio_handler_set_priority(PIOA, (IRQn_Type) ID_PIOA, irq_priority);
	pio_enable_interrupt(PIOA, RED_BUTTON_MASK);
}

int main(void){
	sysclk_init();
	board_init();
	
	//configure 
	pmc_enable_periph_clk(ID_PIOA);
	ioport_set_pin_dir( RED_BUTTON, IOPORT_DIR_INPUT );
	ioport_set_pin_dir( LAMP, IOPORT_DIR_OUTPUT );
	
	//the physical set up requires red button's pin as pull down
	ioport_set_pin_mode( RED_BUTTON, IOPORT_MODE_PULLDOWN );
	
	//configure red button's interrupt	
	configure_button_int();
	
	while(1);

}