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);
  }
}

 
 
 
コメント
コメントを投稿