지금까지 LED제어, 푸쉬버튼 감지 그리고 DS18B20과 통신하기 위하여 거의 모든 코드에서 delay함수를 사용하여 일정 시간동안 프로그램의 진행을 잠시 멈추는 기능을 수행하였다. 임베디드 시스템에서는 이와 같이 상당히 많은 부분에서 시간과 관련된 코드가 들어가게 된다. _delay_ms()나 _delay_us() 함수는 거의 정확한 시간동안 시간지연 기능을 수행해 준다. 그러나 이 함수들은 치명적인 단점이 있다. 특정 시간동안 delay를 주기 위하여 함수 인자로 시간지연값을 넣어 주는데 이 값들은 반드시 상수이어야만 한다는 것이다. LED 제어 1에서 만든 코드를 가지고 이 말이 무슨뜻인지 설명해 보도록 하겠다. int main(void) { DDRB = 0x03; PORTB= 0x03; whil..
DS18B20은 섭씨 -55 ~ +125도까지의 온도를 측정할 수 있다. 이 범위는 8비트 데이터로 충분히 처리할 수 있는 값이다. 즉, 8개의 LED로 표현이 가능하다는 뜻이다. 그러나 LED로 표시되는 온도값은 2진수이므로 사람이 직관적으로 현재 온도값을 알기가 쉽지 않다. 그래서 이번 글에서는 DS18B20에서 읽어 온 온도값을 좀 더 쉽게 알아볼 수 있는 방법에 대해서 설명하도록 하겠다. 아무래도 사람이 현재 온도를 한눈에 인식하려면 수은주처럼 막대그래프 모양이 좋을것 같다. 따라서 이번 프로젝트는 현재 온도값을 막대그래프 형태로 표시하는 방법에 대해서 알아볼 것이다. LED의 개수가 많으면 현재 온도값만큼 LED를 켜면 좋겠지만, 가지고 있는 보드에는 단지 8개의 LED밖에 없으므로 최대한 8개..
이번 글에서는 실제로 DS18B20에서 온도 데이터를 읽어 오는 기능을 구현해 보도록 하겠다. 프로그램을 작성하기 이전에 한가지 생각해 봐야 하는 점이 있다. 블로그의 첫번째 글인 "hello, world"에서 언급한 바와 같이 프로그래머가 예상했던대로 보드에서 결과가 나오는 경우는 모든 것이 문제가 없는 단 한가지의 경우에 해당되고, 제대로 동작되지 않을 경우는 무수히 많다. 특히 클럭 신호도 없는 단 하나의 신호선을 통해서 데이터 송수신이 이루어 진다면 더더욱 그 결과를 신뢰하기가 어렵게 된다. 이미 앞의 글에서 설명했듯이 신호가 유지되는 길이를 이용하여 데이터값이 '0'인지 '1'인지 판단해야 되는 DS18B20의 경우 내장된 크리스탈도 없으므로 정확한 시간에 맞춰 동작된다는 보장도 없다. 이러한 ..
지금까지 AVR의 PORT 레지스터를 제어하여 LED에 불이 들어오게 하거나, 푸쉬버튼 스위치의 ON/OFF 상태를 모니터링 하는 기능을 만들어 보았다. LED를 제어하기 위한 PORT I/O핀은 출력으로만 동작될 수 있도록 설정을 하였고, 푸쉬버튼을 감지하기 위하여 버튼과 연결된 I/O 핀을 입력으로만 동작되도록 설정해 두었다. 이번 프로젝트는 DS18B20이라는 디지털 온도 센서를 이용하여 현재 온도를 측정한 후 LED를 제어하여 측정된 온도값을 출력하는 프로젝트를 진행해 볼 것이다. DS18B20은 하나의 신호선(1-Wire)을 이용하여 온도값을 읽어와야 하는 구조를 가지고 있으므로 AVR의 PORT I/O 핀을 입력과 출력을 번갈아 가며 사용하여야 한다. 따라서 이번 프로젝트는 I/O핀을 입,출력..
앞의 글 푸쉬 버튼과 LED제어 연동 1에서는 PB0에 연결되어 있는 푸쉬버튼을 누르면 다음 LED 패턴을 출력하는 방법에 대해서 설명하였다. 그러나 조금 아쉬운 느낌이 든다. 하나의 패턴을 출력한 후 푸쉬버튼을 누를때까지 아무런 동작을 하지 않고 프로그램이 멈추어 있는것처럼 보이기 때문이다. 그래서 이번글에서는 하나의 LED패턴을 무한히 반복 수행하다가 푸쉬버튼이 눌러지는 시점에 그 다음 LED패턴으로 넘어가는 기능을 구현해 보겠다. 하드웨어 구성은 앞의 글과 동일하므로 회로 수정없이 프로그램만 수정하면 된다. 이번 프로젝트의 핵심은 어느 한 LED 패턴안에서 한동작을 수행한 후 푸쉬버튼이 눌리워 졌는지 항상 모니터링을 하여야 한다. 그래야 버튼이 눌러졌을 때 즉시 다음 LED 패턴으로 넘어갈 수 있기..
푸쉬 버튼을 한 번 누를때마다 앞의 글 LED 제어 - 부록에서 만들었던 LED 패턴을 변경 시키는 프로젝트를 구현하여 보도록 하겠다. 필요한 회로는 앞의 글과 같고 단지 PB0에 푸쉬버튼을 연결하면 된다. 아래 회로도를 참고하여 보드에 회로를 구성한다. 역시 회로가 잘 구성되어 있는지 확인하기 위하여 다음과 같은 코드를 작성한다. 스위치 S1을 누를때 모든 LED에 불이 켜지고, 스위치를 누르지 않을 때는 모든 LED의 불이 꺼지는 코드이다. #include #define F_CPU 1000000 #include #define PORTB_REG 0x23 #define PORTD_REG 0x29 struct port { uint8_t pin; uint8_t ddr; uint8_t port; }; vola..
아래 그림은 AVR에서 SPI 통신을 수행하는데 필요한 SPCR이라는 레지스터이다. SPI통신은 주로 AVR에 연결되어 있는 다른 부품과의 통신을 위해 주로 사용된다. 이때 사용되는 부품들은 SPI 통신이 안정적으로 동작될 수 있는 최대 통신 속도에 대한 규격을 명확히 알려준다. 때로는 그 속도가 AVR CPU의 동작 속도에 비해 많이 낮은 속도가 될 수 있다. 따라서 AVR은 부품 규격에서 제안하는 통신 속도를 맞추기 위하여 여러가지 통신 속도를 설정할 수 있어야 한다. 통신 속도 조절을 위하여 SPCR 레지스터에는 SPR이라는 필드가 있다. SPR은 두개의 비트로 이루어져 있다. SPCR레지스터는 8비트 레지스터이므로 2비트를 SPR로 할당하면 6비트가 남게 된다. SPI통신을 위해서는 SPR과 같은..
푸쉬 버튼 감지 1에서 사용한 예제는 역시 AVR에서만 사용할 수 있는 코드이다. 이를 일반적인 임베디드 프로그램으로 표현해 보도록 하겠다. #include #define PORTB_REG 0x23 #define PUSH_BTN 0x01 #define RED_LED 0x02 struct port { uint8_t pin; uint8_t ddr; uint8_t port; }; volatile struct port *const portb = (void*)PORTB_REG; void setup(void) { portb->ddr = RED_LED; portb->port= (RED_LED | PUSH_BTN); } void loop(void) { if (portb->pin & PUSH_BTN) portb->por..
AVR의 포트핀 출력을 제어하여 두개의 LED를 점멸시키는 방법을 여러가지 예제를 통하여 알아 보았다. 이번 글에서는 포트로 입력되는 신호를 읽어내는 방법에 대해서 알아본다. 이전글에서 사용하였던 회로에서 초록색 LED회로를 들어내고 푸쉬버튼을 넣어보도록 하겠다. 회로도로 표현하면 아래 그림과 같이 된다. 위의 회로를 브레드보드에 꾸미면 아래 그림처럼 된다. 회로도 그림에서 보이는 푸쉬버튼 스위치 'S1'의 한쪽은 PB0에 연결되어 있고, 나머지 한쪽은 GND에 연결되어 있다. 버튼을 누르지 않은 상태에서 PB0에 입력되는 값을 high로 만들고 버튼을 눌렀을때 PB0의 값이 low로 되면 AVR CPU입장에서 1혹은 0의 입력으로 판단할 수 있다. 그렇게 하기 위해서는 PB0에 pull-up 저항을 연..
데이터쉬트의 Regitster Summary에 나와있는 표에서 다음과 같은 내용을 볼 수 있다. 위의 표를 보면 PORT 레지스터가 PIN, DDR, PORT순으로 놓여져 있음을 알 수 있다. 이런 경우 구조체를 이용하면 훨씬 코드를 짜임새 있게 구현할 수 있게 된다. struct port { unsigned char pin; unsigned char ddr; unsigned char port; }; PORT B블럭안에 있는 레지스터는 PINB, DDRB, PORTB이다. 이 세개의 레지스터를 제어하기 위해서 다음과 같이 하면 된다. struct port *portb = (void*)0x23; portb변수에는 0x23이라는 주소가 들어간다. portb는 struct port라고 생긴 구조체 모양을 하고..