叶鋼は午前1時に計算をする

電子工作と計算の記録

【Felicaを使う】 Felica リード・ライターRC-S620Sを動かす

他人をうまく助けることができなければ、人間一人前とはいえません。

吉田茂

今回は、Felicaリーダー・ライターRC-S620Sの使ってFelica Plugと通信する方法について説明します。

しかし、特に説明しないといけないほどのことは何もありません。

 

プログラムはhttps://github.com/SWITCHSCIENCE/mbed-FeliCaをRX62N用に修正しました。

修正したと言っても、C++言語用の記述をC言語用に直すのと、mbedのUART通信関数をRX62Nのものと置き換えただけです。

 

Felicaリーダー・ライターRC-S620SはRX62Nで制御しています。RC-S620SとRX62N通信はごくありふれた普通のUART通信で行います。RX62Nはシリアル0を使用し、通信速度は 115200bbsにしています。

Felica Plugのような独自規格ではなく、詳しい説明は不要と思われるので、以下の解説は概要のみといたします。

 

まず、UARTの設定について、CUBESUITでプロジェクト作成時に自動生成されるレジスタ定義などを利用して、以下のように設定しています。

// =========================================================================
// システムクロック設定
// =========================================================================
SYSTEM.SCKCR.LONG = 0x00020100;  //ICLK=98MHz,PCLK=48MHz,BCLK=24MHz
        
// =========================================================================
// SCI0 UART通信 ボーレート設定
// 48MHz、115200bbs
// =========================================================================
#define SCI0_SCBRR_SET     25 

// =========================================================================
// SCI0 UART通信設定
// =========================================================================
// 割り込み設定
ICU.IPR[0x80].BIT.IPR = 7;    // SCI0 割り込みレベル
ICU.IER[0x1A].BIT.IEN7 = 1;   // SCI0 受信割り込み許可レジスタ

// ポート設定(RXD0(P21))入力方向 
PORT2.ICR.BIT.B1 = 1;

// SCI0スタンバイ解除 
SYSTEM.MSTPCRB.BIT.MSTPB31 = 0;

// SCIF設定 
SCI0.SCR.BYTE = 0x00;          // TE=0,RE=0,CKE1=0 
SCI0.SMR.BYTE = 0x00;          // CHR=0,PE=0,STOP=0,CKS=00(Pφ/1) 
SCI0.BRR = SCI0_SCBRR_SET;      // 分周設定 
SCI0.SEMR.BIT.ABCS = 1;            // ABCS=1 
for(i=0;i<1000;i++);             // 1bit時間ウェイト 
SCI0.SCR.BYTE = 0x70;          // TIE=0,RIE=1,TE=1,RE=1 

シリアル通信の送受信は、ルネサスが公開しているサンプルプログラムを元に作成した以下の関数を使用しています。

(正確な引用元は忘れてしまいました。)

// *******************************************************************************/
//   -Name(en)   :   CPU_UartPutch_NFC                                          */
//   -Name(jp)   :   <1バイト出力>                                               */
// *******************************************************************************/
void CPU_UartPutch_NFC(unsigned char data)
{
    while(1){
        if (SCI0.SSR.BYTE & 0x80) {  /* 送信バッファが空いているか */
            SCI0.TDR = data;
            SCI0.SSR.BYTE = SCI0.SSR.BYTE & 0x40;
            break;
        }
    }
}

// *******************************************************************************/
//   -Name(en)   :   CPU_UartPuts_NFC                                           */
//   -Name(jp)   :   <入力バッファチェック>                                      */
// *******************************************************************************/
int CPU_UartRecvCheck_NFC(void)
{
    if (SCI0.SSR.BYTE & 0x40) {  /* データを受信したか */
        return 1;    /* 受信データあり */
    } else {
        return 0;    /* 受信データなし */
    }
}

// *******************************************************************************/
//   -Name(en)   :   CPU_UartPuts_NFC                                           */
//   -Name(jp)   :   <1バイト受信(エコーバックなし)>                             */
// *******************************************************************************/
unsigned char CPU_UartGetch_NFC(void)
{
    unsigned char data;
    while(1){
        if (CPU_UartRecvCheck_NFC()) { /* データを受信したか */
            data = SCI0.RDR;
            SCI0.SSR.BYTE = SCI0.SSR.BYTE & 0x80;
            break;
        }
    }
    return data;
}

以上のようなUART通信関数を作成して、最初に紹介したサンプルプログラムの通信関数を以下のように置き換えていくだけでプログラムの8割は完成します。 他にタイマーを用いて受信タイムアウト関数を作成したり、細かい諸々の修正は必要です。

// *******************************************************************************/
//   -Name(en)   :   RCS620S_writeSerial                                      */
// *******************************************************************************/
void RCS620S_writeSerial(const unsigned char* data, unsigned short len)
{
//    Serial.write(data, len);
    unsigned short nwrite = 0;

    while (nwrite < len) {
        CPU_UartPutch_NFC( *(data + nwrite) );
        nwrite++;
    }
}

// *******************************************************************************/
//   -Name(en)   :   RCS620S_readSerial                                      */
// *******************************************************************************/
int RCS620S_readSerial(unsigned char* data, unsigned short len)
{
    unsigned short nread = 0;
    unsigned int t0 = 0;

    while (nread < len) 
    {
//受信タイムアウト関数も作成します。私はタイマーを用いて作成しました。
    if ((RCS620S_checkTimeout(t0))) 
    {
        return 0;
    }

    data[nread] = CPU_UartGetch_NFC();
    nread++;
    }

    return 1;
}

メインのプログラムは以下のような流れになっています。

①(修正した)初期化関数RCS620S::initDeviceでFelicaリーダー・ライターRC-S620Sの初期設定を行う。

 

Felica Plugからのリターンがあるまで(修正した)pollingコマンド送信関数RCS620S::pollingの無限ループ

 

Felica Plugからのリターンがあれば、Felica Plugへコマンドを送信して、データの送受信を開始する。

 

最初に紹介したサンプルのメインプログラムでは②のところまでしかなかったので、③は自分で作成してください。

サンプルのRCS620S::cardCommand関数を(RX62N用に修正して)使用すればデータの送受信が出来ます。

送信するデータの構造については「Felicaリーダー・ライターとFelica Plug の通信プロトコル」のCommunicationThruEXコマンド図のData Outを参照してください。

 

RCS620S::cardCommand関数がデータ長を自動計算してくれるので、こちらで用意するのはData Outのコード部以下のデータになります。

 

以上の大雑把な説明ではよく分からないということでしたら、mbedやArudinoでサンプルプログラムをそのまま使用すればいいと思います。