忘備録-備忘録

技術的な備忘録

RX62NのUSB機能を使う その2

2016-01-28 17:39:01 | RX62N
前回「RX62NのUSB機能を使う」でRX62NのUSB機能を利用してCDCデバイスでパソコンと通信するプログラムを紹介しましたが、パソコン側からうまく認識されないことがあるようです。ルネサスエレクトロニクス社のサンプルを見ていたら「Renesas USB MCU USB Peripheral Communication Device Class Driver(PCDC)」を見つけました。とりあえず手持ちのe2studioに読み込み実行しようとしましたが、E1デバッガ経由で実行することができませんでした。
プロジェクトを新たに作成し、ソースコードをコピーし、一部手直ししたら動作しました。

修正したファイル

demo_src\r_usb_pcdc_descriptor.c
  1. /******************************************************************************
  2. User define macro definitions
  3. ******************************************************************************/
  4. /* bcdUSB */
  5. #define USB_BCDNUM (0x0200u)
  6. /* Release Number */
  7. #define USB_RELEASE (0x0200u)
  8. /* DCP max packet size */
  9. #define USB_DCPMAXP (64u)
  10. /* Configuration number */
  11. #define USB_CONFIGNUM (1u)
  12. /* Vendor ID */
  13. #define USB_VENDORID 0x045B
  14. /* Product ID */
  15. #define USB_PRODUCTID 0x2014
ベンダIDとプロダクトIDを手直しします。

r_config\r_bsp_config.h
使用しているMPUに合わせて変更(コメント通りに変更する)

RXマイコン基板(RX62N) | Renesas MCU Software Libraryの仮想COMポートファームウェアを試す 」にも書かれています。

手直ししたプロジェクト

改造しやすいように手直ししました。
USB機能を動作させるためには、一定間隔で次のプログラムを実行する必要があります。
  1.         usb_cdc_driver(); /* USB Driver(Peripheral CDC) */
  2.         switch( cdc_dev_info.state ) /* Check application state */
  3.         {
  4.         case STATE_DATA_TRANSFER: /* Data transfer state */
  5.             lcd_update = cdc_data_transfer();
  6.         break;
  7.         case STATE_ATTACH: /* Wait Connect(USB Configured) state */
  8.             lcd_update = cdc_connect_wait();
  9.         break;
  10.         case STATE_DETACH:
  11.             cdc_detach_device(); /* Detach process */
  12.         break;
  13.         default:
  14.         break;
  15.         }

変更したプロジェクト

さらに、printf,scanfなどの標準入出力関数が使えるように変更しました。
一定間隔でusb_cdc_manage()関数を呼び出せば動作します。時間待ちの時にもこの関数を呼び出してください。

標準入出力が使えるプロジェクト

usb_cdc_manage()関数をタイマ割り込みで動かせば、プログラムが簡単にできると思い、プログラムを変更しました。タイマ割り込みで呼び出しても、問題なく動作しています。初期化のためinitUSB_cdc()関数を呼び出すだけで、パソコンとUSB通信することが可能です。

タイマ割り込みを利用したプロジェクト

Windows用デバイスドライバ
Windows用のデバイスドライバはルネサスエレクトロニクスの「RX62Nグループ、RX621グループ USBペリフェラルCDCによるフラッシュブートローダ」サンプル内に「CDC_Demo_Win7.inf」ファイルが入っています。ベンダIDとプロダクトIDをRX62Nのプログラムに合わせて書き換えます。

  1. ;--------------------------------------------------------
  2. ;    Renesas
  3. ;
  4. ;    Communication Device Class
  5. ;    Virtual Serial Port
  6. ;    
  7. ;    20/12/04
  8. ;--------------------------------------------------------
  9. [Version]
  10. Signature="$Windows NT$"
  11. Class=Ports
  12. ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318}
  13. Provider=%MANUFACTURER%
  14. LayoutFile=layout.inf
  15. ;CatalogFile=%FILENAME%.cat
  16. DriverVer= 3/10/2010,1.1.2600.0
  17. [Manufacturer]
  18. %MANUFACTURER%=DeviceList,NTamd64
  19. [DestinationDirs]
  20. DefaultDestDir=12
  21. ;--------------------------------------------------------
  22. ; Windows XP Support
  23. ;--------------------------------------------------------
  24. [DriverInstall.nt]
  25. include=mdmcpq.inf
  26. CopyFiles=DriverCopyFiles.nt
  27. AddReg=DriverInstall.nt.AddReg
  28. [DriverCopyFiles.nt]
  29. usbser.sys,,,0x20
  30. [DriverInstall.nt.AddReg]
  31. HKR,,DevLoader,,*ntkern
  32. HKR,,NTMPDriver,,%DRIVERFILENAME%.sys
  33. HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
  34. [DriverInstall.nt.Services]
  35. AddService=usbser, 0x00000002, DriverService.nt
  36. [DriverService.nt]
  37. DisplayName=%SERVICE%
  38. ServiceType=1
  39. StartType=3
  40. ErrorControl=1
  41. ServiceBinary=%12%\%DRIVERFILENAME%.sys
  42. ;--------------------------------------------------------
  43. ; Windows Support
  44. ;--------------------------------------------------------
  45. [DriverInstall.NTamd64]
  46. include=mdmcpq.inf
  47. CopyFiles=DriverCopyFiles.NTamd64
  48. AddReg=DriverInstall.NTamd64.AddReg
  49. [DriverCopyFiles.NTamd64]
  50. %DRIVERFILENAME%.sys,,,0x20
  51. [DriverInstall.NTamd64.AddReg]
  52. HKR,,DevLoader,,*ntkern
  53. HKR,,NTMPDriver,,%DRIVERFILENAME%.sys
  54. HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
  55. [DriverInstall.NTamd64.Services]
  56. AddService=usbser, 0x00000002, DriverService.NTamd64
  57. [DriverService.NTamd64]
  58. DisplayName=%SERVICE%
  59. ServiceType=1
  60. StartType=3
  61. ErrorControl=1
  62. ServiceBinary=%12%\%DRIVERFILENAME%.sys
  63. ;**********************************************
  64. ; Please change to your company's information *
  65. ;**********************************************
  66. [SourceDisksFiles]
  67. [SourceDisksNames]
  68. [DeviceList]
  69. %DESCRIPTION%=DriverInstall, USB\VID_045B&PID_2014
  70. [DeviceList.NTamd64]
  71. %DESCRIPTION%=DriverInstall, USB\VID_045B&PID_2014
  72. ;**********************************************
  73. ; Please change to your company's information *
  74. ;**********************************************
  75. [Strings]
  76. FILENAME="Renesas_cdc"
  77. DRIVERFILENAME ="usbser"
  78. MANUFACTURER="Renesas"
  79. INSTDISK="USB2UART"
  80. DESCRIPTION="CDC USB Demonstration"
  81. SERVICE="CDC USB Demonstration Driver"

FFTアナライザを作る

2016-01-28 12:38:02 | processing
シリアルプロッタを作る」でプロッタを作成したので、フーリエ変換を行うプログラムも作ってみました。使用している言語はProcessingです。
FFT変換プログラムはFFT.javaのものを使わせてもらいました。

動作画面


プログラム RS232CgraphFFT03.pde
  1. // シリアルFFTアナライザ
  2. // シリアル入力の値をフーリエ変換する
  3. //
  4. // 参考サイト http://shirotsuku.sakura.ne.jp/blog/?p=192
  5. // http://hp.vector.co.jp/authors/VA046927/fft4gjava.html
  6. // https://www.ee.columbia.edu/~ronw/code/MEAPsoft/doc/html/FFT_8java-source.html
  7. //
  8. //
  9. import processing.serial.*;
  10. float gscale = 10; // 縦軸の倍率
  11. float goffset = 30; //オフセット
  12. float fmag = 2; //横軸の倍率
  13. int samplingrate = 1000; //サンプリングレート
  14. int displayxsize = 1000; //ディスプレイの横幅
  15. int displayysize = 600; //ディスプレイの高さ
  16. String comport = "COM5"; //シリアルポート
  17. int comspeed = 115200; //通信速度
  18. //fft data size 2^N
  19. int DATASIZE = 1024;
  20. Serial myPort;
  21. float val;
  22. float [] x = new float[DATASIZE]; //グラフ用データ x:時間
  23. float [] y1 = new float[DATASIZE]; //グラフ用データ y:電圧
  24. float [] y2 = new float[DATASIZE]; //グラフ用データ y:電圧
  25. //FFT用
  26. int fftdatasize = DATASIZE;
  27. FFT fft = new FFT(fftdatasize);
  28. float[] fftdata1r = new float[fftdatasize]; //data1実数部
  29. float[] fftdata1i = new float[fftdatasize]; //data1虚数部
  30. float[] fftdata2r = new float[fftdatasize]; //data2実数部
  31. float[] fftdata2i = new float[fftdatasize]; //data2虚数部
  32. float[] fftdata1 = new float[fftdatasize]; //data1絶対値
  33. float[] fftdata2 = new float[fftdatasize]; //data2絶対値
  34. void setup()
  35. {
  36.   frameRate(50); //20msec毎にグラフを更新
  37.   size(displayxsize, displayysize);
  38.   myPort = new Serial(this, comport, comspeed);
  39.   textSize(20);
  40.   //グラフ用データの初期化
  41.   for (int i = 0; i < x.length; i++) {
  42.     x[i] = (float)i * (float)(displayxsize-100)/(float)DATASIZE*fmag;
  43.     y1[i] = 0;
  44.     y2[i] = 0;
  45.   }
  46. }
  47. //縦軸の数値の加工 対数化
  48. float dispfunc(float data)
  49. {
  50.   float ans;
  51.   ans = gscale *( log(data) + goffset);
  52.   return ans;
  53. }
  54. void draw()
  55. {
  56.   background(0);
  57.   //グラフエリアの描画
  58.   fill(255);
  59.   text((int)(samplingrate/fmag) + "Hz", displayxsize - 80, displayysize-10);
  60.   float t = DATASIZE/1000;
  61.   text("0Hz", 30, displayysize-10);
  62.   fill(0, 255, 0);
  63.   for (int i = 0; i < fftdata1r.length; i++)
  64.   {
  65.     float[] wnd = fft.getWindow();
  66.     fftdata1[i] = (fftdata1r[i]*fftdata1r[i]+fftdata1i[i]*fftdata1i[i]);
  67.     fftdata2[i] = (fftdata2r[i]*fftdata2r[i]+fftdata2i[i]*fftdata2i[i]);
  68.     fftdata1r[i] = y1[i] * wnd[i];
  69.     fftdata2r[i] = y2[i] * wnd[i];
  70.     fftdata1i[i] = fftdata2i[i]=0;
  71.   }
  72.   fft.fft(fftdata1r, fftdata1i);
  73.   fft.fft(fftdata2r, fftdata2i);
  74.   //グラフのプロット
  75.   pushMatrix();
  76.   translate(50, displayysize-50);
  77.   scale(1, -1);
  78.   fill(0);
  79.   stroke(255);
  80.   rect(0, 0, displayxsize-100, displayysize-94);
  81.   stroke(0, 255, 0);
  82.   strokeWeight(1);
  83.   for (int i = 0; i < x.length/fmag - 1; i++) {
  84.     line(x[i], dispfunc(fftdata1[i]), x[i+1], dispfunc(fftdata1[i+1]));
  85.   }
  86.   stroke(255, 0, 0);
  87.   for (int i = 0; i < x.length/fmag - 1; i++) {
  88.     line(x[i], dispfunc(fftdata2[i]), x[i+1], dispfunc(fftdata2[i+1]));
  89.   }
  90.   popMatrix();
  91. }
  92. int bufsize = 512;
  93. char[] buf = new char[bufsize];
  94. int i = 0;
  95. void serialEvent(Serial myPort) {
  96.   char c = char(myPort.read());
  97.   if ((i<bufsize)&&(c!='\n'))
  98.   {
  99.     buf[i] = c;
  100.     i++;
  101.   } else
  102.   {
  103.     buf[i]='\0';
  104.     i=0;
  105.     String s = new String(buf);
  106.     float data[] = float(s.split(",", 0));
  107.     //グラフ用データの更新
  108.     for (int i = 0; i < y1.length - 1; i++) {
  109.       y1[i] = y1[i+1];
  110.       y2[i] = y2[i+1];
  111.     }
  112.     y1[y1.length - 1] = data[0];
  113.     y2[y2.length - 1] = data[1];
  114.   }
  115. }

プログラム fft.pde
  1. /*
  2.  * Copyright 2006-2007 Columbia University.
  3.  *
  4.  * This file is part of MEAPsoft.
  5.  *
  6.  * MEAPsoft is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License version 2 as
  8.  * published by the Free Software Foundation.
  9.  *
  10.  * MEAPsoft is distributed in the hope that it will be useful, but
  11.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13.  * General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with MEAPsoft; if not, write to the Free Software
  17.  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  18.  * 02110-1301 USA
  19.  *
  20.  * See the file "COPYING" for the text of the license.
  21.  */
  22. public class FFT {
  23.   int n, m;
  24.   // Lookup tables. Only need to recompute when size of FFT changes.
  25.   float[] cos;
  26.   float[] sin;
  27.   float[] window;
  28.   public FFT(int n) {
  29.     this.n = n;
  30.     this.m = (int)(log(n) / log(2));
  31.     // Make sure n is a power of 2
  32.     if (n != (1<<m))
  33.       throw new RuntimeException("FFT length must be power of 2");
  34.     // precompute tables
  35.     cos = new float[n/2];
  36.     sin = new float[n/2];
  37.     for (int i=0; i<n/2; i++) {
  38.       cos[i] = cos(-2*PI*i/n);
  39.       sin[i] = sin(-2*PI*i/n);
  40.     }
  41.     makeWindow();
  42.   }
  43.   protected void makeWindow() {
  44.     // Make a blackman window:
  45.     // w(n)=0.42-0.5cos{(2*PI*n)/(N-1)}+0.08cos{(4*PI*n)/(N-1)};
  46.     window = new float[n];
  47.     for (int i = 0; i < window.length; i++)
  48.       window[i] = 0.42 - 0.5 * cos(2*PI*i/(n-1))
  49.         + 0.08 * cos(4*PI*i/(n-1));
  50.   }
  51.   public float[] getWindow() {
  52.     return window;
  53.   }
  54.   /***************************************************************
  55.    * fft.c
  56.    * Douglas L. Jones
  57.    * University of Illinois at Urbana-Champaign
  58.    * January 19, 1992
  59.    * http://cnx.rice.edu/content/m12016/latest/
  60.    *
  61.    * fft: in-place radix-2 DIT DFT of a complex input
  62.    *
  63.    * input:
  64.    * n: length of FFT: must be a power of two
  65.    * m: n = 2**m
  66.    * input/output
  67.    * x: float array of length n with real part of data
  68.    * y: float array of length n with imag part of data
  69.    *
  70.    * Permission to copy and use this program is granted
  71.    * as long as this header is included.
  72.    ****************************************************************/
  73.   public void fft(float[] x, float[] y)
  74.   {
  75.     int i, j, k, n1, n2, a;
  76.     float c, s, e, t1, t2;
  77.     // Bit-reverse
  78.     j = 0;
  79.     n2 = n/2;
  80.     for (i=1; i < n - 1; i++) {
  81.       n1 = n2;
  82.       while ( j >= n1 ) {
  83.         j = j - n1;
  84.         n1 = n1/2;
  85.       }
  86.       j = j + n1;
  87.       if (i < j) {
  88.         t1 = x[i];
  89.         x[i] = x[j];
  90.         x[j] = t1;
  91.         t1 = y[i];
  92.         y[i] = y[j];
  93.         y[j] = t1;
  94.       }
  95.     }
  96.     // FFT
  97.     n1 = 0;
  98.     n2 = 1;
  99.     for (i=0; i < m; i++) {
  100.       n1 = n2;
  101.       n2 = n2 + n2;
  102.       a = 0;
  103.       for (j=0; j < n1; j++) {
  104.         c = cos[a];
  105.         s = sin[a];
  106.         a += 1 << (m-i-1);
  107.         for (k=j; k < n; k=k+n2) {
  108.           t1 = c*x[k+n1] - s*y[k+n1];
  109.           t2 = s*x[k+n1] + c*y[k+n1];
  110.           x[k+n1] = x[k] - t1;
  111.           y[k+n1] = y[k] - t2;
  112.           x[k] = x[k] + t1;
  113.           y[k] = y[k] + t2;
  114.         }
  115.       }
  116.     }
  117.   }
  118. }

シリアルプロッタを作る

2016-01-27 18:02:26 | processing
Arduinoに追加されたシリアルプロッタは手軽に使えて動作の確認も簡単です。
自動的に、縦軸のレンジが自動で変化するのはお手軽に使えて良いのですが、サンプリングレートが高くなると表示が変化しすぎて目が回るような感じになります。
縦軸、横軸のレンジを決めて動作するプログラムがほしくなりました。手軽に使えるProcessing言語を利用して作ってみました。ひな型になるプログラムが「Arduino シリアル通信 その1:processing」にあったのでそのプログラムを手直ししたものです。

シリアル受信データ
2つの数字をカンマ区切りで一定間隔に出力したものです。シリアルポートから受信します。
-0.369629,0.001532
-0.450195,0.002479
-0.546875,0.003281
-0.650879,0.004101
-0.796875,0.004864

動作画面


プログラムリスト
  1. // 参考サイト http://shirotsuku.sakura.ne.jp/blog/?p=192
  2. import processing.serial.*;
  3. int displaytime = 4; //表示時間
  4. float gscale = 1; // 縦軸の倍率
  5. int samplingrate = 1000; //サンプリングレート
  6. int displayxsize = 1200; //ディスプレイの横幅
  7. int displayysize = 800; //ディスプレイの高さ
  8. String comport = "COM5"; //シリアルポート
  9. int comspeed = 115200; //通信速度
  10. int DATASIZE = samplingrate * displaytime;
  11. //int lf = 0x0d; // ASCII linefeed
  12. //シリアルポートを使用する
  13. Serial myPort;
  14. float val;
  15. float [] x = new float[DATASIZE]; //グラフ用データ x:時間
  16. float [] y1 = new float[DATASIZE]; //グラフ用データ y:電圧
  17. float [] y2 = new float[DATASIZE]; //グラフ用データ y:電圧
  18. void setup()
  19. {
  20.   frameRate(50); //20msec毎にグラフを更新
  21.   size(displayxsize, displayysize);
  22.   myPort = new Serial(this, comport, comspeed);
  23.   //myPort.bufferUntil(lf);
  24.   textSize(20);
  25.   //グラフ用データの初期化
  26.   for (int i = 0; i < x.length; i++) {
  27.     x[i] = (float)i * (float)(displayxsize-100)/(float)DATASIZE;
  28.     y1[i] = 0;
  29.     y2[i] = 0;
  30.   }
  31. }
  32. void draw()
  33. {
  34.   background(0);
  35.   //グラフエリアの描画
  36.   fill(255);
  37.   // text("-1.6V",10,310);
  38.   // text("+1.6V",10,54);
  39.   text("0sec", displayxsize - 70, displayysize-10);
  40.   float t = DATASIZE/1000;
  41.   text("-" + t + "sec", 30, displayysize-10);
  42.   fill(0, 255, 0);
  43.   //text(val/255.0*5,560,100);
  44.   //グラフのプロット
  45.   pushMatrix();
  46.   translate(50, displayysize-50);
  47.   scale(1, -1);
  48.   fill(0);
  49.   stroke(255);
  50.   rect(0, 0, displayxsize-100, displayysize-94);
  51.   stroke(0, 255, 0);
  52.   strokeWeight(1);
  53.   for (int i = 0; i < x.length - 1; i++) {
  54.     line(x[i], y1[i], x[i+1], y1[i+1]);
  55.   }
  56.   stroke(255, 0, 0);
  57.   for (int i = 0; i < x.length - 1; i++) {
  58.     line(x[i], y2[i], x[i+1], y2[i+1]);
  59.   }
  60.   popMatrix();
  61. }
  62. int bufsize = 512;
  63. char[] buf = new char[bufsize];
  64. int i = 0;
  65. void serialEvent(Serial myPort) {
  66.   char c = char(myPort.read());
  67.   //if(c=='\r') return;
  68.   if ((i<bufsize)&&(c!='\n'))
  69.   {
  70.     buf[i] = c;
  71.     i++;
  72.   } else
  73.   {
  74.     buf[i]=0;
  75.     i=0;
  76.     String s = new String(buf);
  77.     float data[] = float(s.split(",", 0));
  78.     //グラフ用データの更新
  79.     for (int i = 0; i < y1.length - 1; i++) {
  80.       y1[i] = y1[i+1];
  81.       y2[i] = y2[i+1];
  82.     }
  83.     // 0〜(displayysize-94)の間で変化するように
  84.     y1[y1.length - 1] = (data[0]+0)*(displayysize-94)*gscale/2 + (displayysize-94)/2;
  85.     // 0〜(displayysize-94)の間で変化するように
  86.     y2[y2.length - 1] = (data[1]+0)*(displayysize-94)*gscale/2 + (displayysize-94)/2;
  87.     //print(data[0]);
  88.     //print(" ");
  89.     //println(s);
  90.   }
  91. }

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. }

ESP-WROOM-02を使う

2016-01-14 11:07:20 | ESP8266

単体でも使えるWifiモジュールESP-WROOM-02を使ってみました。その時ときのメモです。

注意点

  • 電源電圧が3.3V
  • Wifi動作時に電流が必要

 

接続

  • 電源 3.3V
  • GND
  • EN 10kΩくらいでプルアップ
  • RST 10kΩくらいでプルアップ
  • TXD ホストコンピュータの RXDに (注意 3.3V)
  • RXD ホストコンピュータの TXDに (注意 3.3V)
  • IO0,IO2,IO15 モード設定端子(動作モードでつなぎ変え)

モード設定(適当)
  • ATモード                
    IO15 プルダウン | 他なし
  • Arduinoランモード            
    IO0 プルアップ |IO2 プルアップ(無くてもOK?) |IO15 プルダウン
  • Arduinoプログラミング,ファーム書き換え 
    IO0 プルダウン |IO2 プルアップ(無くてもOK?) |IO15 プルダウン

プルアップ,プルダウンとも10kΩ程度

モード切替後、リセットか電源のOFF-ONが必要


ATコマンドで使用する


Arduinoでプログラミング

Arduino IDEの設定
Arduinoでプログラムを転送するとATコマンドモードが使えなくなるので元に戻したい場合はファームウェアの書き換えが必要です。
 
OTA(wifi経由でのスケッチ書き換え) 


ファームウェアの書き換え