button.c
#define F_CPU 5000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdbool.h>
#include "button.h"
extern buttonFlag_t buttonFlag = {false,false,false};
void GPIO_Init(void)
{
PORTF.DIRSET = PIN5_bm;
PORTF.DIRCLR = PIN6_bm;
PORTF.OUTSET = PIN5_bm;
PORTF.PIN6CTRL |= PORT_PULLUPEN_bm;
}
void buttonISR(void)
{
static buttonState_t buttonState = BUTTON_IDLE;
static uint16_t buttonPressTimeCount = 0;
static uint16_t LastPress, CurrentPress = 0;
static uint16_t clock = 0;
clock++;
if(LastPress && LastPress != CurrentPress && (CurrentPress - LastPress) < 80) { buttonFlag.DoublePress = true; }
if(buttonPressTimeCount && buttonPressTimeCount % 200 == 0) buttonFlag.Hold = true;
switch (buttonState)
{
case BUTTON_IDLE :
if(USER_BUTTON_ON) buttonState++;
break;
case BUTTON_PRESSING :
if(USER_BUTTON_ON) { buttonFlag.OnPress = true; buttonState++; CurrentPress = clock; }
else buttonState--;
break;
case BUTTON_PRESSED :
if(!USER_BUTTON_ON) buttonState++;
else { buttonPressTimeCount++; LastPress = CurrentPress; }
break;
case BUTTON_RELEASE :
if(!USER_BUTTON_ON) { buttonFlag.OnPress = false; buttonState = BUTTON_IDLE; buttonPressTimeCount = 0; }
else buttonState--;
break;
}
}
button.h
#ifndef BUTTON_H_
#define BUTTON_H_
#define USER_BUTTON_ON !(PORTF.IN & PIN6_bm)
typedef enum { BUTTON_IDLE, BUTTON_PRESSING, BUTTON_PRESSED, BUTTON_RELEASE }buttonState_t;
typedef struct {
volatile bool OnPress;
volatile bool DoublePress;
volatile bool Hold;
}buttonFlag_t;
void GPIO_Init(void);
void buttonISR(void);
#endif /* BUTTON_H_ */
main.c
#define F_CPU 5000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdbool.h>
#include "button.h"
void CLK_Init(void);
void TCB0_Init(void);
#define USER_LED_ON (PORTF.OUTCLR = PIN5_bm)
#define USER_LED_OFF (PORTF.OUTSET = PIN5_bm)
buttonFlag_t buttonFlag;
int main(void)
{
CLK_Init();
TCB0_Init();
GPIO_Init();
sei();
while (1)
{
if(buttonFlag.OnPress) USER_LED_ON;
else USER_LED_OFF;
if(buttonFlag.Hold) { buttonFlag.Hold = false; }
if(buttonFlag.DoublePress) { buttonFlag.DoublePress = false; }
}
}
void CLK_Init(void)
{
CCP = CCP_IOREG_gc;
CLKCTRL.MCLKCTRLB = CLKCTRL_PDIV_4X_gc | CLKCTRL_PEN_bm;
}
void TCB0_Init(void)
{
TCB0.CCMP = 5000;
TCB0.CTRLA |= TCB_ENABLE_bm;
TCB0.INTCTRL |= TCB_CAPT_bm;
}
ISR(TCB0_INT_vect)
{
static uint16_t Cnt1000Hz = 0;
uint8_t Cnt200Hz = (uint8_t)(Cnt1000Hz % 5);
Cnt1000Hz++;
if(Cnt200Hz == 0) buttonISR();
TCB0.INTFLAGS |= TCB_CAPT_bm;
}