忘備録-備忘録

技術的な備忘録

RX210でi2cを使う

2016-01-15 13:02:55 | RX210
ルネサスエレクトロニクス社製のマイコンRX210を使用してI2C通信を行うプログラムのサンプルです。

  1. #include "iodefine.h"
  2. #include <stdio.h>
  3. #include <machine.h>
  4. #include "rs232c.h"
  5. /*
  6.    Interface 2011年6月号を参考にして作成したIIC通信プログラム
  7.      割込みを使用しない
  8. */
  9. /*
  10.    RIICの初期化
  11.    引数  無し
  12.    戻り値 無し
  13. */
  14. void initRIIC0(void)
  15. {
  16.     SYSTEM.PRCR.WORD = 0xA502;    /* Enables writing to the registers */
  17.     MSTP(RIIC0) = 0;            // モジュールスタンバイ解除
  18.     SYSTEM.PRCR.WORD = 0xA500;    /* Disables writing to the registers */
  19.     /* Set the pins */
  20.     PORT1.PDR.BIT.B2 = 0; /* SCL: input */
  21.     PORT1.PDR.BIT.B3 = 0; /* SDA: input */
  22.     PORT1.PMR.BIT.B2 = 0; /* SCL: general I/O port */
  23.     PORT1.PMR.BIT.B3 = 0; /* SDA: general I/O port */
  24.     MPC.PWPR.BIT.B0WI = 0; /* Writing to the PFSWE bit is enabled */
  25.     MPC.PWPR.BIT.PFSWE = 1; /* Writing to the PFS register is enabled */
  26.     MPC.P12PFS.BIT.PSEL = 0x0F; /* SCL */
  27.     MPC.P13PFS.BIT.PSEL = 0x0F; /* SDA */
  28.     MPC.PWPR.BIT.PFSWE = 0; /* Writing to the PFS register is disabled */
  29.     MPC.PWPR.BIT.B0WI = 1; /* Writing to the PFSWE bit is disabled */
  30.     /* Set the pins */
  31.     PORT1.PMR.BIT.B2 = 1; /* SCL: peripheral function */
  32.     PORT1.PMR.BIT.B3 = 1; /* SDA: peripheral function */
  33.     /* RIIC disable for RIIC initial */
  34.     RIIC0.ICCR1.BIT.ICE = 0;
  35.     while(RIIC0.ICCR1.BIT.ICE != 0); /* Confirm that the ICCR1.ICE bit is 0 */
  36.     RIIC0.ICCR1.BIT.IICRST = 1;            /* RIICリセット */
  37.     RIIC0.ICCR1.BIT.ICE = 1;            /* 内部リセット */
  38.     /* Set transfer bit rate : 100kbps (PCLK = 25MHz) */
  39.     RIIC0.ICMR1.BIT.CKS = 2; /* Internal Reference Clock: PCLK/4 clock */
  40.     RIIC0.ICBRH.BIT.BRH = 24; /* Set the High-level period of SCL clock */
  41.     RIIC0.ICBRL.BIT.BRL = 29; /* Set the Low-level period of SCL clock */
  42.     /* disable all address detection. Master mode only. */
  43.     RIIC0.ICSER.BYTE = 0x00;
  44.     /* ACKWP is protect bit for ACKBT */
  45.     RIIC0.ICMR3.BIT.ACKWP = 1;        /* disable protect for ACKBT */
  46.     RIIC0.ICCR1.BIT.IICRST = 0;        /* 内部リセット解除 */
  47. }
  48. /*
  49.    バスフリーの確認
  50.    引数  無し
  51.    戻り値 無し
  52. */
  53. inline void i2cBusFree(void)
  54. {
  55.     while(RIIC0.ICCR2.BIT.BBSY == 1);
  56. }
  57. /*
  58.    バス・スタートを実行
  59.    引数  無し
  60.    戻り値 無し
  61. */
  62. inline void i2cStart(void)
  63. {
  64.     RIIC0.ICCR2.BIT.ST = 1;
  65.     while(RIIC0.ICSR2.BIT.START != 1);
  66.     RIIC0.ICSR2.BIT.START = 0;
  67. }
  68. /*
  69.    バスがBusy中にバス・スタート
  70.    引数  無し
  71.    戻り値 無し
  72. */
  73. inline void i2cReStart(void)
  74. {
  75.     RIIC0.ICCR2.BIT.RS = 1;
  76.     while(RIIC0.ICSR2.BIT.START != 1);
  77.     RIIC0.ICSR2.BIT.START = 0;
  78. }
  79. /*
  80.    バス・ストップを実行
  81.    引数  無し
  82.    戻り値 無し
  83. */
  84. inline void i2cStop(void)
  85. {
  86.     RIIC0.ICSR2.BIT.STOP = 0;
  87.     RIIC0.ICCR2.BIT.SP = 1;
  88.     while(RIIC0.ICSR2.BIT.STOP != 1);
  89.     RIIC0.ICSR2.BIT.STOP = 0;
  90.     RIIC0.ICSR2.BIT.NACKF = 0;
  91. }
  92. /*
  93.    デバイスに1byteデータ転送
  94.    引数  送信データ
  95.    戻り値 無し
  96. */
  97. inline void i2cSendByte(unsigned char data)
  98. {
  99.     while(RIIC0.ICSR2.BIT.TDRE != 1);
  100.     RIIC0.ICDRT = data;
  101. }
  102. /*
  103.    データの転送完了を確認
  104.    引数  無し
  105.    戻り値 無し
  106. */
  107. inline void i2cCheckTEND(void)
  108. {
  109.     while(RIIC0.ICSR2.BIT.TEND != 1);
  110. }
  111. /*
  112.    デバイスから1byte読み取りバスストップを実行
  113.    引数   無し
  114.    戻り値  デバイスから読み取ったデータ
  115. */
  116. unsigned char i2cReceiveByteStop(void)
  117. {
  118.     unsigned char rdt;
  119.     while(RIIC0.ICSR2.BIT.RDRF != 1);
  120.     RIIC0.ICMR3.BIT.WAIT = 1;
  121.     RIIC0.ICMR3.BIT.ACKBT = 1;
  122.     rdt = RIIC0.ICDRR;                //dummy read
  123.     while(RIIC0.ICSR2.BIT.RDRF != 1);
  124.     RIIC0.ICSR2.BIT.STOP = 0;
  125.     RIIC0.ICCR2.BIT.SP = 1;            //stop
  126.     rdt = RIIC0.ICDRR;                //data read
  127.     RIIC0.ICMR3.BIT.WAIT = 0;
  128.     while(RIIC0.ICSR2.BIT.STOP != 1);
  129.     RIIC0.ICSR2.BIT.STOP = 0;
  130.     RIIC0.ICSR2.BIT.NACKF = 0;
  131.     return rdt;
  132. }
  133. /*
  134.    スレーブ・アドレスを指定してデバイスのレジスタ・メモリにデータを書き込む
  135.    引数   sadr : スレーブ・アドレス
  136.         madr : レジスタ・メモリアドレス 8bit
  137.         data : 書き込むデータ
  138.    戻り値  無し
  139. */
  140. void i2cDevWrite8(unsigned char sadr, unsigned char madr, unsigned char data)
  141. {
  142.     i2cBusFree();
  143.     i2cStart();
  144.     i2cSendByte(sadr);
  145.     i2cSendByte(madr);
  146.     i2cSendByte(data);
  147.     i2cCheckTEND();
  148.     i2cStop();
  149. }
  150. /*
  151.   スレーブアドレスとデバイスのレジスタ・アドレスを指定してデバイスからデータを読み込む
  152.   引数   sadr : スレーブ・アドレス
  153.        madr : レジスタ・メモリアドレス 8bit
  154.   戻り値  読み込んだデバイスのデータ
  155. */
  156. unsigned char i2cDevRead8(unsigned char sadr, unsigned char madr)
  157. {
  158.     unsigned char rdt;
  159.     i2cBusFree();
  160.     i2cStart();
  161.     i2cSendByte(sadr);
  162.     i2cSendByte(madr);
  163.     i2cCheckTEND();
  164.     i2cReStart();
  165.     i2cSendByte(sadr | 0x01);
  166.     rdt = i2cReceiveByteStop();
  167.     return rdt;
  168. }
  169. /*
  170.    スレーブアドレスを指定して複数byteのデータを送信する
  171.    引数  sadr : スレーブアドレス
  172.        databuff: 送信するデータの入った配列
  173.        datanum : 送信するデータ数
  174.    戻り値 0 : 送信完了  -1 : 送信エラー
  175. */
  176. int i2cSendData(unsigned char sadr, const unsigned char databuff[], int datanum)
  177. {
  178.     int senddata=-1,ret=-1;
  179.     i2cBusFree();
  180.     i2cStart();
  181.     while(senddata<datanum) {
  182.         if(RIIC0.ICSR2.BIT.NACKF != 0) goto sendstop;    //送信エラー
  183.         if(RIIC0.ICSR2.BIT.TDRE != 1) continue;
  184.         if(senddata < 0) {
  185.             RIIC0.ICDRT = sadr;            //最初にアドレスを送信
  186.         } else {
  187.             RIIC0.ICDRT = databuff[senddata];
  188.         }
  189.         senddata++;
  190.     }
  191.     i2cCheckTEND();
  192.     ret = 0;        //送信完了
  193. sendstop:
  194.     i2cStop();
  195.     return ret;
  196. }
  197. /*
  198.    スレーブアドレスを指定して複数byteのデータを受信する
  199.    引数  sadr : スレーブアドレス
  200.        databuff: 受信したデータを入れる配列
  201.        datanum : 受信するデータ数
  202.    戻り値 0 : 受信完了  -1 : 受信エラー
  203. */
  204. int i2cReceiveData(unsigned char sadr, unsigned char databuff[], int datanum)
  205. {
  206.     int recvdata=0,ret=-1;
  207.     unsigned char dummy;
  208.     i2cBusFree();
  209.     i2cStart();
  210.     i2cSendByte(sadr | 0x01);        // アドレス送信 受信設定(|0x01)
  211.     i2cCheckTEND();
  212.     if(datanum == 1 ) {
  213.         databuff[0] = i2cReceiveByteStop();
  214.         return 0;
  215.     }
  216.     if(RIIC0.ICSR2.BIT.NACKF == 0) {
  217.     /* データ受信処理 */
  218.         dummy = RIIC0.ICDRR;                //dummy read
  219.         while(recvdata < datanum) {
  220.             if(RIIC0.ICSR2.BIT.RDRF != 1) continue;
  221.             if(recvdata == (datanum-2) ) break;
  222.             if(recvdata == (datanum-3) ) {
  223.                 RIIC0.ICMR3.BIT.WAIT = 1;
  224.             }
  225.             databuff[recvdata++] = RIIC0.ICDRR;
  226.         }
  227.         RIIC0.ICMR3.BIT.ACKBT = 1;
  228.         databuff[recvdata++] = RIIC0.ICDRR;
  229.         while(RIIC0.ICSR2.BIT.RDRF != 1);
  230.         RIIC0.ICSR2.BIT.STOP = 0;
  231.         RIIC0.ICCR2.BIT.SP = 1;
  232.         databuff[recvdata++] = RIIC0.ICDRR;
  233.         RIIC0.ICMR3.BIT.WAIT = 0;
  234.         ret = 0;
  235.     } else {
  236.     /* 受信エラー */
  237.         RIIC0.ICSR2.BIT.STOP = 0;
  238.         RIIC0.ICCR2.BIT.SP = 1;
  239.         dummy = RIIC0.ICDRR;        //dummy read
  240.     }
  241.     while(RIIC0.ICSR2.BIT.STOP != 1);
  242.     RIIC0.ICSR2.BIT.STOP = 0;
  243.     RIIC0.ICSR2.BIT.NACKF = 0;
  244.     return ret;
  245. }
  246. /*
  247.    スレーブ・アドレスを指定してデバイスのレジスタ・メモリにデータを書き込む
  248.    引数   sadr : スレーブ・アドレス
  249.         madr : レジスタ・メモリアドレス 16bit
  250.         data : 書き込むデータ
  251.    戻り値  無し
  252. */
  253. void i2cDevWrite16(unsigned char sadr, unsigned short madr, unsigned char data)
  254. {
  255.     unsigned char buf[3];
  256.     buf[0] = madr >> 8;
  257.     buf[1] = madr & 0xFF;
  258.     buf[2] = data;
  259.     i2cSendData(sadr,buf,3);
  260. /*
  261.     i2cBusFree();
  262.     i2cStart();
  263.     i2cSendByte(sadr);
  264.     i2cSendByte(madr >> 8);
  265.     i2cSendByte(madr & 0xFF);
  266.     i2cSendByte(data);
  267.     i2cCheckTEND();
  268.     i2cStop();
  269. */
  270. }
  271. /*
  272.   スレーブアドレスとデバイスのレジスタ・アドレスを指定してデバイスからデータを読み込む
  273.   引数   sadr : スレーブ・アドレス
  274.        madr : レジスタ・メモリアドレス 16bit
  275.   戻り値  読み込んだデバイスのデータ
  276. */
  277. unsigned char i2cDevRead16(unsigned char sadr, unsigned short madr)
  278. {
  279.     unsigned char rdt;
  280.     i2cBusFree();
  281.     i2cStart();
  282.     i2cSendByte(sadr);
  283.     i2cSendByte(madr >> 8);
  284.     i2cSendByte(madr & 0xFF);
  285.     i2cCheckTEND();
  286.     i2cReStart();
  287.     i2cSendByte(sadr | 0x01);
  288.     rdt = i2cReceiveByteStop();
  289.     return rdt;
  290. }


最新の画像もっと見る

2 コメント

コメント日が  古い順  |   新しい順
受信最後バイトのNACKチェック (LM324)
2020-03-02 12:11:54
意図していないです。
適宜修正してください。
返信する
受信最後バイトのNACKチェック (しんいち)
2020-02-27 18:37:41
ソースコードの開示ありがとうございます。
疑問に思ったのですが、
i2cSendData()関数でI2C送信後、最後のバイトのACKを検出しなかった場合、200行目のNACKチェックせずに正常0でリターンしてしまいます。
意図したソースコードですか?
返信する

コメントを投稿