티스토리 뷰

입문

푸쉬 버튼과 LED제어 연동 1

Just4Fun 2016. 3. 12. 22:49

푸쉬 버튼을 한 번 누를때마다 앞의 글 LED 제어 - 부록에서 만들었던 LED 패턴을 변경 시키는 프로젝트를 구현하여 보도록 하겠다.

필요한 회로는 앞의 글과 같고 단지 PB0에 푸쉬버튼을 연결하면 된다.  아래 회로도를 참고하여 보드에 회로를 구성한다.

역시 회로가 잘 구성되어 있는지 확인하기 위하여 다음과 같은 코드를 작성한다.  스위치 S1을 누를때 모든 LED에 불이 켜지고, 스위치를 누르지 않을 때는 모든 LED의 불이 꺼지는 코드이다.

#include <stdint.h>
#define F_CPU   1000000
#include <util/delay.h>
 
#define PORTB_REG   0x23
#define PORTD_REG   0x29
struct port
{
    uint8_t   pin;
    uint8_t   ddr;
    uint8_t   port;
};
 
volatile struct port *const portb = (void*)PORTB_REG;
volatile struct port *const portd = (void*)PORTD_REG;
 
#define PUSH_BTN    0x01
 
void setup(void)
{
    portb->ddr  = 0x00;
    portb->port = PUSH_BTN;
    portd->ddr  = 0xFF;
    portd->port = 0x00;
}
 
void loop(void)
{
    if (portb->pin & PUSH_BTN)
        portd->port = 0x00;
    else
        portd->port = 0xFF;
}
 
int main(void)
{
    setup();
 
    while (1) 
    {
        loop();
    }
}

위의 코드를 이용하여 회로와 부품의 정상성을 검증한다.

푸쉬버튼을 누를때마다 모든 LED에 불이 들어오는것을 확인하였으면, 앞의 글에서 만들어 보았던 세가지의 LED 패턴을 하나씩 코드에 추가해 본다.

void led_pattern1(void)
{
    int     i;
 
    for (i=0; i<8; i++)
    {
        _delay_ms(200);
        portd->port = 1 << i;
    }
 
    for (i=0; i<8; i++)
    {
        _delay_ms(200);
        portd->port = 1 << (7-i);
    }
}
 
void loop(void)
{
    led_pattern1();
}

먼저 첫번째 패턴으로 LED하나씩 왼쪽, 오른쪽으로 쉬프트하는 코드를 추가하고 정상 동작하는지 확인한다.

첫번째 패턴이 잘 동작되는지 확인한 후 두번째 패턴을 추가한다.

void led_pattern2(void)
{
    int     i;
 
    for (i=0; i<8; i++)
    {
        _delay_ms(200);
        portd->port = (1 << i) | (1 << (7-i));
    }
}
 
void loop(void)
{
    led_pattern1();
    led_pattern2();
}

첫번째 패턴과 새로 추가한 두번째 패턴이 교대로 반복해서 동작되는지 확인한다.

확인이 되었으면 마지막으로 세번째 패턴을 추가한다.

void led_pattern3(void)
{
    int     i,j,val;
 
    val = 0;
    for (i=0; i<4; i++)
    {
        val = (1 << (1<<(3-i)))-1;
        for (j=0; j<i; j++)
        {
            val |= val << (1 << (4-i));
        }
        portd->port = val & 0xFF;
        _delay_ms(PATTERN_DELAY);
        portd->port = (~val) & 0xFF;
        _delay_ms(PATTERN_DELAY);
    }
}
 
void loop(void)
{
    led_pattern1();
    led_pattern2();
    led_pattern3();
}

세가지 LED 패턴이 반복해서 수행될 것이다.

이제 패턴과 패턴사이에 푸쉬버튼 상태를 읽어서 버튼이 눌러 지는 순간에 다음 패턴으로 진행하는 코드를 만들어 보겠다.  즉, 하나의 LED 패턴을 수행하면 바로 다음 패턴으로 진행 하는것이 아니라, 버튼이 눌러 질때까지 현재 상태를 유지 하다가 버튼이 눌러지게 되는 상태에 다음 LED 패턴으로 넘어가게 되는 것이다.

버튼이 눌러지는지 감시하는 함수를 하나 만든다.  버튼이 눌러지게 되면 PINB의 0번 비트 값이 1에서 0으로 변경된다.  따라서 PB0 값이 0이 될때 빠져나오는 while문을 사용하면 될 것 같다.

void wait_until_button_press(void)
{
    while (portb->pin & PUSH_BTN);
}

while() 문은 () 안의 값이 거짓이 될때까지 계속 반복문을 수행한다.  이미 앞에서 설명했듯이 C언어에서 참과 거짓의 조건은 0이 아니면 참, 0이면 거짓이라고 판단한다.  위의 코드는 PB0의 값이 1이면 계속 참이 되어 while문을 계속 수행하게 된다.  만약 버튼을 누르면 PB0값이 0이 되어 while()에서 빠져나오게 된다.  

임베디드 시스템은 이와 반대로 어떤 특정한 비트값이 1이 될때까지 기다려야 되는 경우가 있다.  그럴때는 어떻게 코딩하여야 할까?  예를 들어 PB0의 값이 평소에는 0으로 유지 되는데, 어떤 조건이 되면 그 값이 1이 된다.  PB0핀의 값이 1이 될때까지 기다리다가 1이 되는 순간 while()문에서 빠져 나오는 코드는 다음과 같이 하면 된다.

while (!(portb->pin & PUSH_BTN));

버튼 감시 함수를 완성하였으면 loo() 함수의 각 led 패턴을 부르는 함수 사이 마다 버틈 감시 함수를 부르는 코드를 삽입하여 버튼 감시가 제대로 되는지 확인해 본다.

void loop(void)
{
    led_pattern1();
    wait_until_button_press();
    led_pattern2();
    wait_until_button_press();
    led_pattern3();
    wait_until_button_press();
}

 

이번글에서 구현한 전체 코드는 파일로 첨부한다.

main.c
다운로드

 

입문 과정 목차

'입문' 카테고리의 다른 글

LED 온도계 1  (6) 2016.03.20
푸쉬 버튼과 LED제어 연동 2  (1) 2016.03.15
LED 제어 - 부록  (3) 2016.03.07
푸쉬 버튼 감지 2  (3) 2016.03.06
푸쉬 버튼 감지 1  (7) 2016.03.06
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함