복잡하게 디바이스 드라이버까지 작성하지 않고 간단하게 mmap을 사용하여 레지스터에 접근하여 LED를 제어해보려고 합니다.
핀번호 6번 그라운드와 핀번호 12번 GPIO18에 LED를 연결해주었습니다.
BCM2835 데이터 시트에 따르면 LED를 켜고 끄는 데에는 다음 레지스터들을 사용하면 됩니다.
라즈베리파이3에선 BCM2837이지만 동일하게 동작했습니다.
- GPFSELx – GPIO핀을 Input 또는 Ouput으로 사용할지 결정.
- GPSETx – GPIO핀을 하이레벨로 만들어줌. Led가 켜진 상태.
- GPCLRx – GPIO핀을 로우 레벨로 만들어줌. Led가 꺼지는 상태.
GPIO Base Address가 아래처럼 0x 7E20 0000으로 나와 있지만 BCM2835 데이터시트의 1.2.3 ARM physical addresses에 따르면 실제로 접근 시에는 0x 2020 0000부터 시작하는 걸로 생각하면 됩니다.
하지만 이건 라즈베리파이 1 기준입니다. (http://www.raspberrypi.org/forums/viewtopic.php?f=6&t=5982 )
https://www.raspberrypi.org/forums/viewtopic.php?f=33&t=98740 에 따르면 라즈베리파이2에서는 0x3F20 0000으로 바꾸어서 적용시키면 된다고 합니다. 따라서 GPFSEL0의 시작 주소가 0x7E20 0000이 아니라 0x3F20 0000이 되는 것입니다.
라즈베리파이3에서도 테스트해보니 동일하게 동작합니다.
아래에 LED를 제어하는데 사용할 3가지 레지스터의 메모리 주소들을 보여주고 있습니다.
GPIO18번은 GPF_SEL1레지스터에 해당 항목이 있습니다.
24번째 비트부터 26번째 비트까지의 값을 001로 바꾸어주면 GPIO18번는 출력모드가 되게 됩니다.
//gpio[GPFSEL1/4] = 0b00000001000000000000000000000000; gpio[GPFSEL1/4] |= (1<<24); |
그리고 다음 레지스터들에서 GPIO18번의 위치에 해당되는 비트를 세팅 해주면 LED가 켜지고 꺼지게 할 수 있습니다.
//gpio[GPSET0/4] = 0b00000000000001000000000000000000; gpio[GPSET0/4] |= (1<<18); |
//gpio[GPCLR0/4] = 0b00000000000001000000000000000000; gpio[GPCLR0/4] |= (1<<18); |
실행시켜보면 LED가 5번 깜빡이게 됩니다.
pi@raspberrypi:~ $ g++ led.c -o led
pi@raspberrypi:~ $ sudo ./led
#include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/mman.h> #define GPIO_BASE 0x3F200000 #define GPFSEL1 0x04 #define GPSET0 0x1C #define GPCLR0 0x28 int main() { int fd = open( "/dev/mem", O_RDWR|O_SYNC ); if ( fd < 0 ){ printf( "can't open /dev/mem \n" ); exit(-1); } char *gpio_memory_map = (char *)mmap( 0, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_BASE ); if ( gpio_memory_map == MAP_FAILED ) { printf( " Error : mmap \n" ); exit(-1); } volatile unsigned int* gpio = (volatile unsigned int*)gpio_memory_map; //gpio[GPFSEL1/4] = 0b00000001000000000000000000000000; gpio[GPFSEL1/4] |= (1<<24); int i; for ( i=0; i<5; i++ ) { //gpio[GPSET0/4] = 0b00000000000001000000000000000000; gpio[GPSET0/4] |= (1<<18); sleep(1); //gpio[GPCLR0/4] = 0b00000000000001000000000000000000; gpio[GPCLR0/4] |= (1<<18); sleep(1); } munmap( gpio_memory_map, 4096); return 0; } |
마지막 업데이트 2019. 2. 18
'Raspberry Pi > Raspberry Pi 활용' 카테고리의 다른 글
Raspberry Pi 4 에서 무선랜(WiFi) 설정하는 방법 (0) | 2023.10.21 |
---|---|
C언어로 Raspberry Pi 3의 GPIO 레지스터 접근하여 버튼값 읽어오기 (0) | 2023.10.09 |
Raspberry Pi 4 - Python으로 7 Segment 제어하기 (0) | 2021.06.13 |
Raspberry Pi 4에서 캐릭터 LCD 사용하는 방법 ( wiringpi ) (6) | 2021.02.05 |
Node.js를 이용하여 Raspberry Pi 3에 연결된 LED 제어하기 (4) | 2019.08.13 |
시간날때마다 틈틈이 이것저것 해보며 블로그에 글을 남깁니다.
블로그의 문서는 종종 최신 버전으로 업데이트됩니다.
여유 시간이 날때 진행하는 거라 언제 진행될지는 알 수 없습니다.
영화,책, 생각등을 올리는 블로그도 운영하고 있습니다.
https://freewriting2024.tistory.com
제가 쓴 책도 한번 검토해보세요 ^^
그렇게 천천히 걸으면서도 그렇게 빨리 앞으로 나갈 수 있다는 건.
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!