Raspberry Pi のGPIOでLEDを点灯させてみた
久しぶりにRaspberryPiを触ってみました。
Broadcom社のBCM2835というPeripheralチップが搭載されており、その一部の端子がヘッダピンに結線されています。ADC端子が無いのは非常に残念ですが、GPIO、UART、I2Cでハードウェア拡張が可能になっています。
手始めとして、GPIOにLEDを接続してC言語で点滅させてみました。
●回路(僅かこれだけです・・・)
●プログラム概要
gpio_open()
BCM2835のレジスタへアクセスする準備を行います。
システムコールopen
システムコールmmap …BCM2835のGPIOレジスタ群のアドレスは0x20200000番地~です。
main()
gpio_open()
LEDを接続したヘッダP1の26番ピン(GPIO7)を出力モードに設定します。
while(1){
GPIO7にHighレベルを出力します。
sleep() 時間待ち
GPIO7にLowレベルを出力します。
sleep() 時間待ち
}
●コンパイル
$gcc gpio1.c
コンパイルが通ると a.out が生成されます。
●実行
$./a.out
と実行すると、システムコールopenでエラーが発生し、「can't open. Permisson denied」と返ってきます。
$sudo ./a.out
と管理者権限で実行させます。
実行停止はキーボードからCtrl-cです。
=================================================================================
ソースコード gpio1.c
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <stdint.h>
// BCM2835 on Raspberry pi
#define GPIO_REGS 0x20200000
static volatile uint32_t *gpio_regs;
int gpio_open()
{
int fd;
void *map;
if ((fd = open ("/dev/mem", O_RDWR | O_SYNC) ) < 0) {
printf("can't open. %s\n",strerror(errno));
return -1;
}
map = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_REGS);
if (map == MAP_FAILED) {
printf("can't mapping. %s\n",strerror(errno));
return -1;
}
close(fd);
gpio_regs = (volatile uint32_t *)map;
return 0;
}
int main(int argc, char **argv)
{
uint i;
// LED connected port number
// available port 2,3,4,7,8,9,10,11,14,15,17,18,22,23,24,25,27 (rev2.0 PCB)
//
// see http://elinux.org/RPI_LOW_level_peripherals/
uint portnum = 7;
if( gpio_open() != 0 ){
printf("error:stopped \n");
return -1;
}
// Port mode settting
// GPFSELn: Function Select Registers
// GPFSEL0: port0 - port9
// GPFSEL1: port10 - port19
// GPFSEL2: port20 - port29
// FSELn
// 000B input mode
// 001B output mode
// others function mode
//
// see http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
//
i = portnum/10;
*(gpio_regs + i) = (*(gpio_regs + i) & ~(0x7 << ((portnum%10) * 3) )) | (0x1 << ((portnum%10) * 3));
//LED toggle test loop
while(1){
// Output High
// GPSETn: GPIO Pin Output Set Registers
// GPSET0: port0 - port31
// SETn
// 0B : no effect
// 1B : set // GPSETn: GPIO Pin Output Set Registers
//
*(gpio_regs + 0x7) = (0x1 << portnum);
sleep(1);
// Output Low
// GPCLRn: GPIO Pin Output Clear Registers
// GPCLR0: port0 - port31
// CLRn
// 0B : no effect
// 1B : clear GPIO output
//
*(gpio_regs + 0x0A) = (0x1 << portnum);
sleep(1);
}
}
コメント
コメントを投稿