【ソフト】
raspberry piのGPIO17を入力にして
1s周期でセンス
ターミナルの標準出力へ結果を出力
【ハード】
SW押下時に GPIO17にLが入力されるように
3.3VにPullUpしておき、SW押下時にGNDとつながるように構成
【結果】
test.c
------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include "BCM2835-ARM-SFR.h"
/* pin番号の定義 */
#define SW_PORT_NO 17
// gpio[n]: GPIO 関連レジスタ (volatile=最適化によって消滅させない→必ず実メモリにアクセスさせる)
static volatile unsigned int *gpio;
// gpio_init: GPIO 初期化(最初に1度だけ呼び出すこと)
void gpio_init ()
{
int fd;
void *gpio_map;
// /dev/mem(物理メモリデバイス)を開く(sudo が必要)
fd = open("/dev/mem", O_RDWR | O_SYNC);
if (fd == -1) {
printf("error: cannot open /dev/mem (gpio_setup)\n");
exit(-1);
}
// mmap で GPIO(物理メモリ)を gpio_map(仮想メモリ)に対応づける
gpio_map = mmap(NULL, BLOCK_SIZE,
PROT_READ | PROT_WRITE, MAP_SHARED,
fd, GPIO_BASE );
if ((int) gpio_map == -1) {
printf("error: cannot map /dev/mem on the memory (gpio_setup)\n");
exit(-1);
}
// mmap 後は不要な fd をクローズ
close(fd);
// gpio[index]: 整数 uint32 の配列としてレジスタへのアクセスを確立
gpio = (unsigned int *) gpio_map;
}
// gpio_configure: ピン機能を設定する(ピンを使用する前に必ず設定)
// pin : (P1) 2,3,4,7,8,9,10,11,14,15,17,18,22,23,24,25,27
// (P5) 28,29,30,31
// mode: GPIO_INPUT, _OUTPUT, _ALT0, _ALT1, _ALT2, _ALT3, _ALT4, _ALT5
void gpio_configure (int pin, int mode)
{
int index;
unsigned int mask;
// ピン番号チェック
if ((0 <= pin) && ( pin <= 31 )) {
// レジスタ番号(index)と3ビットマスクを生成
index = pin / 10;
mask = ~(0x7 << ((pin % 10) * 3));
// GPFSEL0/1 の該当する FSEL (3bit) のみを書き換え
gpio[index] = (gpio[index] & mask) | ((mode & 0x7) << ((pin % 10) * 3));
}
else{
printf("error: pin number out of range (gpio_configure)\n");
exit(-1);
}
}
int gpio_get (int pin)
{
int tmp;
int result;
// ピン番号チェック(スピードを追求するなら省略してもよい)
if ((0 <= pin) && ( pin <= 31 )) {
result = ( gpio[SFR_INDEX_GPLEV0] >> pin)& 0x00000001;
}
else{
result = GPIO_LEVEL_L;
printf("error: pin number out of range (gpio_set)\n");
exit(-1);
}
return result;
}
int main ()
{
unsigned long int level;
gpio_init(); /* アドレス空間を周辺ペリフェラルのアドレスにマッピング */
gpio_configure(SW_PORT_NO, GPIO_INPUT); /* ポート動作モードを設定 */
while (1) {
level = gpio_get(SW_PORT_NO);
printf("Level:%1d\n",level);
usleep(1000*1000);
}
return 0;
}
------------------------------------------------------------------------------
0 件のコメント:
コメントを投稿