2012年8月23日木曜日

Raspberry Pi で I2C その1 秋月RTCモジュール

 Raspberry Pi 用GPIOアダプタ(Raspduino)ArduinoGR-SAKURA のように秋月のI2C接続RTCが使えるかどうかを試してみました。


 下準備として ここ の記述を参考に以下を行いました。ただし、自分の環境は色々なものをインストールしているので、何がどう影響(良くも悪くも)しているかが正直わからないんですが・・・
 まず、/etc/modules に
     i2c-dev
の一行を追加して、/etc/modprobe.d/raspi-blacklist.conf の
     blacklist i2c-bcm2708
の先頭に#をつけてコメントアウト。一旦、再起動後に
     sudo apt-get install i2c-tools
で i2c-tools をインストールしました。
動作確認に使ったソースはこんな感じ。ただし、delay関数を使うために wiringPiのライブラリを使用しています。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>

#include <linux/i2c-dev.h>
#include <fcntl.h>
#include <sys/ioctl.h>

#include <wiringPi.h>



int main(int argc, char **argv)
{
 int rtc;       // ファイルディスクリプタ。
 char *i2cFileName = "/dev/i2c-0"; // I2Cドライバファイル名。
 int rtcAddress = 0xa2 >> 1;   // I2C LCD のアドレス。右1bitシフト。
 unsigned char buf[16];    // バッファ。
 
 printf("***** start i2c test program *****\n");
 printf("Initializing RTC unit... Please wait\n");
 delay(1000);
 
 // I2CポートをRead/Write属性でオープン。
 if ((rtc = open(i2cFileName, O_RDWR)) < 0)
 {
  printf("Faild to open i2c port\n");
  exit(1);
 }
 
 // 通信先アドレスの設定。
 if (ioctl(rtc, I2C_SLAVE, rtcAddress) < 0)
 {
  printf("Unable to get bus access to talk to slave\n");
  exit(1);
 }
 
 // RTC初期化。
 delay(15);
 // はじめにアドレス0x00を指定。次からはオートインクリメント。
 buf[0] = 0x00;
 // コントロールレジスタ1。
 buf[1] = 0x00;
 // コントロールレジスタ2。
 buf[2] = 0x00;
 // 秒レジスタ。とりあえず、58秒。
 buf[3] = 0x58;
 // 分レジスタ。とりあえず、59分。
 buf[4] = 0x59;
 // 時レジスタ。とりあえず、23時。
 buf[5] = 0x23;
 // 日レジスタ。とりあえず、23日。
 buf[6] = 0x23;
 // 曜日レジスタ。とりあえず、木曜日。
 buf[7] = 0x04;
 // 月レジスタ。とりあえず、8月。
 buf[8] = 0x08;
 // 年レジスタ。取りあえず、12年。
 buf[9] = 0x12;
 // アラーム設定。なし。
 buf[11] = 0x00;
 buf[12] = 0x00;
 buf[13] = 0x00;
 // Clock出力設定。1Hz。
 buf[14] = 0x83;
 if (write(rtc, buf, 15) != 15)
 {
  printf("Error writeing to i2c slave\n");
  exit(1);
 }
 delay(20);
 printf("RTC Initialized.\n");
 
 int i;
 for (i = 0; i < 20; i++)
 {
  // データ要求ダミーコマンド送信。
  buf[0] = 0;
  if ((write(rtc, buf, 1)) != 1) {
   printf("Error writing to i2c slave\n");
   exit(1);
  }
  // データ読み込み。
  if (read(rtc, buf, 16) != 16)
  {
   printf("Uneble to read\n");
   exit(1);
  }
  
  // 西暦年。以下数値はBCD。
  printf("20");
  printf("%x", buf[8]);
  printf("/");
  // 月。下位9bit。
  printf("%x", buf[7] & 0x1f);
  printf("/");
  // 日。下位10bit。
  printf("%x", buf[5] & 0x3f);
  printf(" ");
  // 曜日。
  switch (buf[6] & 0x07) {
  case 0:
   printf("Sun");
   break;
  case 1:
   printf("Mon");
   break;
  case 2:
   printf("Tue");
   break;
  case 3:
   printf("Wed");
   break;
  case 4:
   printf("Thr");
   break;
  case 5:
   printf("Fri");
   break;
  case 6:
   printf("Sat");
   break;
  default:
   printf("   ");
   break;
  }
  printf("   ");
  // 時。
  printf("%x", buf[4] & 0x3f);
  printf(":");
  // 分。
  printf("%x", buf[3] & 0x7f);
  printf(":");
  // 秒。
  printf("%x", buf[2] & 0x7f);
  printf("\n");
  
  delay(500);
 }
 
 return 0;
}



  どうやら、RTCから情報を取得できているようです。