日曜技術者のメモ

趣味でやった事のメモ書きです。

Zedboard ADCでアナログ値を読んでみた -2-

前回の続き

前回はTOPモジュールを作成した。
次にこれをPlanAheadに取り込む。

Add Sources->「Add or Create Design Sources」を選択し
「Add Files」で先ほど作成したsystem.vを選択する。

保存場所自分で変えていなければ以下場所にあるはず↓

\<Project location>\<Project name>\<Project name>.srcs\sources_1\edk\system

問題なく読み込めるとHierarchy表示で階層表示される。
f:id:ginnyu-tei:20121022214252j:plain
system_stubとsystemが階層表示されない場合は
コードが間違っている場合があるので再度確認。

3.UCFファイルの設定。
SPIをEMIO経由で接続した前回はUCFファイルを2つに分けたが
管理が面倒になるので今回は1つにする。
「zedboard_master_UCF_RevC_v2.ucf」をPlanAheadにて
Add Fileした後以下を変更する。

NET XADC-AD0N-R   LOC = E16;  # "XADC-AD0N-R"
NET XADC-AD0P-R   LOC = F16;  # "XADC-AD0P-R"
NET XADC-AD8N-R   LOC = D17;  # "XADC-AD8N-R"
NET XADC-AD8P-R   LOC = D16;  # "XADC-AD8P-R"
                      ↓
NET axi_xadc_0_VAUXN0_pin  LOC = E16;  # "XADC-AD0N-R"
NET axi_xadc_0_VAUXP0_pin  LOC = F16;  # "XADC-AD0P-R"
NET axi_xadc_0_VAUXN8_pin  LOC = D17;  # "XADC-AD8N-R"
NET axi_xadc_0_VAUXP8_pin  LOC = D16;  # "XADC-AD8P-R"

4.合成・インプリ
Synthesis、Implementationを実行。
出来たらBitstreamを生成し、ハードウェア部分は完成です。

ここでちょっと気になったことが・・・
Implementationの結果をみたら「Bonded IPAD」が200%になっていました。
f:id:ginnyu-tei:20121022232451j:plain
調べたけど良くわからなかったのでとりあえず保留


5.ソフトの作成
PlanAheadからSDKへExportし、SDKを起動します。
CTTではNew C Projectで「Hello World」を使用していましたが、
新規に作成するという意味でEmpty Applicationを選択。

次にソースコードを追加します。
srcフォルダを右クリック-> New -> Source Fileでファイルを追加します。名前は適当で
f:id:ginnyu-tei:20121022233850j:plain

今回ADCを動作させるコードはadcのexampleを使用します。
system.mssタブのExamplesをクリックするとブラウザが立ち上がり
Example一覧が表示されます。その中の「xsysmon_polled_printf_example.c」の「source」
をクリックして出てきたコードを先ほど追加したSource Fileに貼り付けます。

このサンプルは内蔵温度センサー、Vccint電圧、VccAux電圧の
現在値、最大値、最小値を表示するプログラムです。

このコードに外部の電圧値を表示するコードを追加します。

コードの変更点は以下

・変数追加
159行目~

  int Status;
  XSysMon_Config *ConfigPtr;
  u32 TempRawData;
  u32 VccAuxRawData;
  u32 VccIntRawData;
  float TempData;
  float VccAuxData;
  float VccIntData;
  float MaxData;
  float MinData;

     ↓
  int Status;
  XSysMon_Config *ConfigPtr;
  u32 TempRawData;
  u32 VccAuxRawData;
  u32 VccIntRawData;
  u32 AUX00RawData;
  float TempData;
  float VccAuxData;
  float VccIntData;
  float MaxData;
  float MinData;
  float AUX00Data;

・VAUXN0、VAUXP0が双極モード(Bipolar Mode)になっているので
 単極モード(Unipolar Mode)に変更
(双極モードは差動-0.5V~+0.5V測定。単極モードは0V~1V測定)

221行目~

  Status = XSysMon_SetSeqInputMode(SysMonInstPtr, XSM_SEQ_CH_AUX00);
  if (Status != XST_SUCCESS) {
    return XST_FAILURE;
  }
                     ↓

  Status = XSysMon_SetSeqInputMode(SysMonInstPtr, 0x0);
  if (Status != XST_SUCCESS) {
    return XST_FAILURE;
  }

※ここはデフォルト0(単極モード)なので0を書き込まなくても良いと思い初めは書き込まなかったのだが、
 書き込まないと単極モードにならない時があったので一応0x0書き込み。

・VAUXN0、VAUXP0センサ値読み込み&表示
356行目~

  printf("The Minimum VCCAUX is %0d.%03d Volts. \r\n\r\n",
                (int)(MinData), SysMonFractionToInt(MinData));
  //↓追加
  AUX00RawData = XSysMon_GetAdcData(SysMonInstPtr, XSM_CH_AUX_MIN);
  AUX00Data = AUX00RawData / 65536.0f;

  printf("AUX00RawData = %x\r\n",AUX00RawData);

  printf("\r\nThe Current AUX00 is %0d.%03d Volts. \r\n\r\n",
               (int)(AUX00Data), SysMonFractionToInt(AUX00Data));
 //↑ここまで
  printf("Exiting the SysMon Polled Example. \r\n");

※ADCは12bitなのでデータも12bitかと思いますが、レジスタアドレスは4byte(32bit)分あり、
データは下位16bit中のMSB12bitとなっています。
なのでVAUXN0、VAUXP0の値は読み出し[31:0]内の[15:4]となります。

単極モードの場合1Vで0xFFFなのでADCの値をボルトにするには
(読み出し値 >> 4) / 2^12 = 読み出し値 >> 16
となり65536で割ればボルト表記にできます。


6.テスト回路作成。

ADCをテストする為以下回路を作成しました。
f:id:ginnyu-tei:20121023083600j:plain
可変抵抗は普通のやつでは細かな変更ができないので
今回は10kΩのポテンションメーターを用意しました。


7.Sim実行

配線できたらSDKで実行します。
Tera Termで以下出力が出ました。

Entering the SysMon Polled Example.

The Current Temperature is 49.510 Centigrades.
The Maximum Temperature is 49.510 Centigrades.
The Minimum Temperature is 49.156 Centigrades.

The Current VCCINT is 0.995 Volts.
The Maximum VCCINT is 0.995 Volts.
The Minimum VCCINT is 0.993 Volts.

The Current VCCAUX is 1.804 Volts.
The Maximum VCCAUX is 1.806 Volts.
The Minimum VCCAUX is 1.803 Volts.

AUX00RawData = B413

The Current AUX00 is 0.703 Volts.

Exiting the SysMon Polled Example.