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;
}



카테고리:

업데이트: