이번 글에서는 실제로 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라고 생긴 구조체 모양을 하고..
이번에는 조금 고급 테크닉을 사용하여 LED를 제어해 보도록 하겠다. 앞에서 매크로를 사용해서 코드를 보기 좋게 만들었다. 앞의 코드는 Data memory 공간을 이용했다면, 이번에는 C코드에서 직접 I/O 메모리 공간을 바로 접근하는 방법에 대해서 설명하겠다. 이미 LED 제어 4에서 I/O 메모리 공간에 접근하기 위해서 "in", "out"명령을 사용해야 한다고 설명했었다. 그러나 I/O 주소를 직접 사용할 수 없고 0x20만큼 offset값을 더해서 사용해야된다고 했다. C프로그램을 하다보면 C코드로는 도저히 사용할 수 없는 명령어를 사용해야 되는 경우와 어셈블러로 구현하는게 훨씬 효율적인 경우가 생긴다. 이런 요구사항을 해결하기 위해서 inline assembler기능을 사용하면 된다. #def..
이번에는 앞에서 작성했던 코드를 매크로를 이용하여 좀더 깔끔하게 수정해 보도록 하겠다. 앞에서 어떤 레지스터에 값을 쓰기 위하여 포인터를 사용했는데 다음과 같은 코드를 사용하였다. *(unsigned char*)DDRB = (GREEN_LED|RED_LED); 위의 코드를 매크로를 사용하면 다음과 같이 수정할 수 있다. #define write8(addr, val) (*(volatile unsigned char *)(addr) = (val)) 전체 코드를 위의 매크로를 이용하여 정리하면 다음과 같은 모양으로 나온다. 훨씬 깔끔하게 보일 것이다. #define F_CPU 1000000 //#include #include #define IO_REG_OFFSET 0x20 #define PINB (IO_REG_..