Transistor Gijutsu, October 2014, Special Features Chapter 8,Software of the thermistor thermometer of 0.001 ° resolution, トランジスタ技術2014年10月号 特集第8章のソフトウェア 0.001℃分解能で気配もキャッチ「超敏感肌温度計」

Dependencies:   USBDevice mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers AD7714.cpp Source File

AD7714.cpp

00001 #include "AD7714.h"
00002 
00003 
00004 #define MAINCLKF (48)   // main clock 48MHz
00005 #define CLKFRQ (1000)   // clkout の周波数 kHz
00006 
00007 /// コンストラクタ
00008 /// - PWMおよびSPIポートを初期化
00009 /// - PWMはAD7714のマスタークロック1MHzを生成する
00010 AD7714::AD7714(void)
00011 {
00012     // CLKOUT を1MHzに設定
00013     // set clock divider
00014     LPC_SYSCON->CLKOUTDIV = (CLKFRQ * MAINCLKF) / 1000;
00015     // main clock -> CLKOUT
00016     LPC_SYSCON->CLKOUTSEL = 0x3;
00017     LPC_SYSCON->CLKOUTUEN = 0;
00018     LPC_SYSCON->CLKOUTUEN = 1;
00019     // P0_1 -> CLKOUT
00020     LPC_IOCON->PIO0_1 |= 0x01;
00021 
00022 
00023     // SPIポート初期化
00024     spi = new SPI(P0_9, P0_8, P0_10);
00025     // SPI信号のアイドルレベルとクロック位相を設定
00026     LPC_SSP0->CR0 |= 0xc0;
00027 
00028     // ADCのリセットとフィルタ設定
00029     reset();
00030     setFilter(2);
00031 
00032     // 各チャネルのゼロ点とフルスケールの校正(キャリブレーション)
00033     // 内部的に入力を短絡してゼロスケールを校正
00034     // 内部的に入力をVrefに接続してフルスケールを校正
00035     // 他のチャネルを使う場合は、コメントを外す
00036     // キャリブレーションには時間がかかるので必要なチャネルだけ初期化
00037     channel = Ch.A1A2;
00038     calib();
00039     //channel = Ch.A3A4;
00040     //calib();
00041     //channel = Ch.A5A6;
00042     //calib();
00043 };
00044 
00045 /// キャリブレーション
00046 /// チャネル、ゲイン、フィルタ周波数を変更したあと必ず実行せよ
00047 void AD7714::calib(void)
00048 {
00049     write(Reg.Mode, 0x20);
00050     while(isBusy()){
00051     }
00052 }
00053 
00054 /// SPI通信ポートの初期化
00055 void AD7714::reset(void)
00056 {
00057     for(int a = 0; a < 5; a++){
00058         writeByte(0xff);
00059     }
00060 }
00061 
00062 /// 変換中なら真を返す
00063 bool AD7714::isBusy(void)
00064 {
00065     writeByte(CRegister::Comun | CmdRead | channel);
00066     return (writeByte(CmdRead) & 0x80) != 0;
00067 }
00068 
00069 /// 1バイト送信
00070 /// @param txd 送信データ
00071 /// @return 受信データ
00072 int AD7714::writeByte(int txd)
00073 {
00074     return spi->write(txd);
00075 };
00076 
00077 /// レジスタの内容を読む
00078 /// @param reg レジスタを指定する値 Reg構造体のメンバー
00079 /// @return レジスタの内容
00080 int AD7714::read(int reg)
00081 {
00082     int r, cmd;
00083     cmd = reg | CmdRead | channel;
00084     writeByte(cmd);
00085     r = writeByte(cmd);
00086     if(reg >= Reg.Data){
00087         r = (r<<8) | writeByte(cmd);
00088         r = (r<<8) | writeByte(cmd);
00089     }
00090     return r;
00091 }
00092 
00093 /// 指定レジスタに書き込む
00094 /// 指定レジスタが8bitか24bitがを判別して書き込む
00095 /// @param reg レジスタを指定する値 Reg構造体のメンバー
00096 /// @param data 書き込むデータ
00097 /// @return なし
00098 void AD7714::write(int reg, int data)
00099 {
00100     writeByte(reg | CmdWrite | channel);
00101     writeByte(data & 0xff);
00102     if(reg >= Reg.Data){
00103         data >>= 8;
00104         writeByte(data & 0xff);
00105         data >>= 8;
00106         writeByte(data & 0xff);
00107     }
00108 }
00109 
00110 /// フィルターノッチ周波数の設定(19Hz - 4000Hz)
00111 ///-# 周波数を上げると変換時間は短縮されるがノイズが増える
00112 ///-# 60に設定すると60Hzの電源ノイズのキャンセルに有効
00113 /// @param freq ノッチ周波数[Hz] 
00114 /// @return なし
00115 void AD7714::setFilter(int freq)
00116 {
00117     int code = (FclkIn / 128) / freq;
00118     if(code < 19){
00119         code = 19;
00120     }else if(code > 4000){
00121         code = 4000;
00122     }
00123     // バイポーラ入力に設定
00124     write(Reg.FltHi, 0x40 | ((code >> 8) & 0x0f));
00125     write(Reg.FltLo, code & 0xff);
00126 }
00127 
00128 
00129 /// レシオメトリックADCクラスのコンストラクタ(初期化に数秒を要する)
00130 /// @param Rpu プラス入力のVcc側抵抗値、GND側抵抗としてセンサを接続する。
00131 /// @param Rmu マイナス入力のVcc側抵抗値
00132 /// @param Rml マイナス入力のGND側抵抗値
00133 /// @param Rru リファレンス入力のVcc側抵抗値
00134 /// @param Rrl リファレンス入力のGND側抵抗値
00135 RatioMetric7714::RatioMetric7714(double Rpu, double Rmu, double Rml, double Rru, double Rrl)
00136 {
00137     af = 1 << bits;
00138     rpu = Rpu; rmu = Rmu; rml = Rml; rru = Rru; rrl = Rrl;  
00139 }
00140 
00141 /// 与えられたADC値をレシオメトリックにより抵抗値に変換する
00142 /// @param int adVal AD変換値
00143 /// @return 変換さた抵抗値
00144 double RatioMetric7714::toResistorValue(int adVal)
00145 {
00146     return  -((rpu*(2*adVal*(rml + rmu)*rrl + af*(-(rmu*rrl) + rml*rru)))
00147             /(2*adVal*(rml + rmu)*rrl - af*(rml*rrl + rmu*(2*rrl + rru))));
00148 
00149 }
00150 
00151 /// 現在のADC値を抵抗値に変換して返す
00152 /// @return 測定された抵抗値
00153 double RatioMetric7714::getResistorValue(void)
00154 {
00155     return toResistorValue(getValue());
00156 }