반응형
안녕하세요. 소나무 기운입니다.
스위를 입력받는 동작은 기본이고 꼭 필요하지요.
제일 많이 사용하는 스위치는 TACT스위치입니다.
이러한 기계적인 움직임이 있는 곳에는 채터링이라는 것이 발생해요.
접점이 붙는 순간에 붙었다가 떨어졌다 하는 일들이 순간적으로 반복돼요.
채터링 현상으로 검색하시면 설명이 많이 있습니다.
chattering noise, switch bounce
스위치 입력을 받을 때 이 채터링 현상을 처리해 주지 않으면 문제가 생기게 됩니다.
한 번만 스위치를 눌렀는데 여러 번 눌린 것과 같은 증상이 있지요.
이러한 현상을 해결하기 위한 하드웨어적인 방법도 있지만 소프트웨어적인 방법이 있어요.
주기적으로 스위치를 읽어 보다가 같은 값이 유지가 되면 그것을 현재의 상태로 인식하는 겁니다.
예를 들어 10mS마다 핀 값을 읽어서 여러 번 High가 읽어지고 나면 High라고 인식합니다.
또 반대로 여러번 Low라고 읽어지면 Low라고 인식합니다.
저는 주로 10mS마다 스위치를 읽어요. 그리고 두 번 반복해서 같은 값이 읽어지면 그 값을 사용하지요.
#define MAX_KEY 4
struct keystruct
{
unsigned char Status;
unsigned char Value;
unsigned short Data;
unsigned short OldData;
unsigned char AutoKey;
};
void ChkKey(void)
{ // 10mS마다 한번씩 호출됨.
uint8_t cnt = 0;
uint16_t tmp = 0;
KeyFlags.Data = ReadKey(); // 현재의 스위치 비트를 읽어옴
if (KeyFlags.Status == 1) // 키가 눌렸고 처리되지 않았으면 추가 작업 없음.
goto CHK_END;
if (KeyFlags.Data == KeyFlags.OldData)
{ // 같은 값이 연속해서 두번 들어왔음. 채터링 노이즈를 제거한 상태
if (bit_test(KeyFlags.Data, KeyFlags.AutoKey))
{ // 키가 눌린 상태로 계속 유지됨.
AutoKeyCnt++;
if (AutoKeyCnt == 50)
{ // 첫번째 길게 눌림 키를 처리
KeyFlags.Value += 50;
KeyFlags.Status = 1;
}
else if (AutoKeyCnt > 100)
{ // 2번째 이후 길게 눌림 키를 처리
KeyFlags.Status = 1;
AutoKeyCnt = 100 - 5; // 0.5sec
}
}
else
{ // 모든 키가 떨어진 상태
KeyFlags.AutoKey = MAX_KEY; // no key
}
}
else
{ // 키가 눌리거나 떨어지면서 변화가 생김.
AutoKeyCnt = 0;
tmp = KeyFlags.OldData ^ KeyFlags.Data;
for (cnt = 0; cnt < 16; cnt++)
{
if (!bit_test(KeyFlags.OldData, cnt))
{ // 변화가 생긴 핀이 떨어졌다가 눌린것인지 판단
if (bit_test(tmp, cnt))
break;
}
}
KeyFlags.Value = cnt;
if (cnt < MAX_KEY)
{ // 정상적으로 키가 눌려짐.
KeyFlags.Status = 1; // 눌림 상태로 전환
KeyFlags.AutoKey = cnt;
AutoKeyCnt = 0;
// Key Story 눌린 키를 누적하여 비교
// SaveKeyBuffer(KeyFlags.Value);
// bit_set(KeyFirstFlags, cnt);
// bit_set(KeyFirstFlags2, cnt);
}
}
CHK_END:
KeyFlags.OldData = KeyFlags.Data;
}
//=============================================================================
uint16_t ReadKey(void)
{
uint16_t nRet = 0;
static bool AdjKeyReleaseFlag = false;
static int AdjKeyPushCnt = 0;
if (digitalRead(KEY_HOUR) == LOW)
{
nRet |= 0x0001;
}
if (digitalRead(KEY_MIN) == LOW)
{
nRet |= 0x0002;
}
if (digitalRead(KEY_ALARM) == LOW)
{
nRet |= 0x0004;
}
if (digitalRead(KEY_LAMP) == LOW)
{
nRet |= 0x0008;
}
return nRet & 0x000F;
}
잘 쓰고 있는 소스네요.
- 눌림시 키 처리
- 누르고 있으면 롱키 처리
- 계속 누르고 있으면 빠르게 롱키 반응
- 채터링 적용
- 10mS마다 키 스캔
즐거운 코딩 하세요~
반응형
'Arduino' 카테고리의 다른 글
[TB-I2C] IR 온도센서 (적외선) 사용하기 (0) | 2020.12.18 |
---|---|
[시계용 FND] Adafruit 제품 소개 (0) | 2020.12.12 |
[부저] 아두이노에서 부저 사용하기 (0) | 2020.12.12 |
아두이노 나노 소개 (0) | 2020.12.12 |
SW-420 진동 센서 (0) | 2020.10.16 |
댓글