もう一回だけ 続最終回
C++ Builder CEで作ったGUIなアプリケーションが作成できるのを確認してほんとの最終回としますね。一つ前のコマンドラインプログラムをベースにVCLなアプリケーションを作ります。ま、手順を間違えなければ動くはずですね。前の記事は、
適当
でした。ここで作ったインポートライブラリを使います。32bit版と64bit版の両方使います。また、実行時にはlibmpsse.dllが必要ですが、32bit版も64bit版も同名で同じディレクトリには置けませんから、混同しないように注意が必要です。さて、起動してスタートボタンを押すと、

で、ストップボタン押すと、

となります、Memo1の空白部分で右クリックすると、上のようなメニューが出ますから、必要に応じて行を選択して、コピーするなりが可能です。ただコンソールに流れるより柔軟に扱えますよね。さて、まずは、Unit1.hから、
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE で管理されるコンポーネント
TMemo *Memo1;
TButton *Stop;
TButton *Start;
void __fastcall StopClick(TObject *Sender);
void __fastcall StartClick(TObject *Sender);
void __fastcall FormDestroy(TObject *Sender);
private: // ユーザー宣言
public: // ユーザー宣言
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endifUnit1.cppは、
#include <vcl.h>
#pragma hdrstop
#include "ftd2xx.h"
#include "libMPSSE_i2c.h"
#define ADT7410_ADDRESS 0x48 // 7ビットI2Cアドレス (libmpsse内部で自動シフトされます)
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
bool looping = true;
FT_HANDLE ftHandle;
FT_STATUS status;
DWORD bytesTransferred;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
ChannelConfig channelConf;
//uint32_t channels;
DWORD channels;
uint8_t buffer[4];
Memo1->Lines->Clear();
// 1. libmpsse の初期化
Init_libMPSSE();
status = I2C_GetNumChannels(&channels);
if (status != FT_OK || channels == 0) {
ShowMessage("エラー: 利用可能なFTDIデバイスが見つかりません。\n");
//return -1;
}
// 2. 最初のチャンネル(0)を開く
status = I2C_OpenChannel(0, &ftHandle);
if (status != FT_OK) {
ShowMessage("エラー: チャンネルを開けませんでした。\n");
//return -1;
}
// 3. I2C通信速度などの設定 (400kHzに設定)
channelConf.ClockRate = I2C_CLOCK_STANDARD_MODE; // もしくは 400000 (FAST_MODE)
channelConf.LatencyTimer = 255;
channelConf.Options = 0x03;
status = I2C_InitChannel(ftHandle, &channelConf);
if (status != FT_OK) {
ShowMessage("エラー: チャンネル初期化失敗。\n");
I2C_CloseChannel(ftHandle);
//return -1;
}
// 4. ADT7410 を 16ビット分解能モードに設定する (レジスタ 0x03 に 0x80 を書き込み)
buffer[0] = 0x03; // 設定レジスタアドレス
buffer[1] = 0x80; // 16bit mode bit (Bit7 = 1)
status = I2C_DeviceWrite(ftHandle, ADT7410_ADDRESS, 2, buffer, &bytesTransferred,
I2C_TRANSFER_OPTIONS_START_BIT | I2C_TRANSFER_OPTIONS_STOP_BIT);
if (status != FT_OK) {
ShowMessage("警告: 16bitモードへの設定に失敗しました。デフォルトの13bitで動作します。\n");
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::StopClick(TObject *Sender)
{
looping = false;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::StartClick(TObject *Sender)
{
looping = true;
uint8_t buffer[4];
Memo1->Lines->Add("ADT7410 から温度データの読み込みを開始します...\n");
while (looping ) {
// 5. ポインタレジスタを 0x00 (温度データ) に指定する
buffer[0] = 0x00;
I2C_DeviceWrite(ftHandle, ADT7410_ADDRESS, 1, buffer, &bytesTransferred,
I2C_TRANSFER_OPTIONS_START_BIT | I2C_TRANSFER_OPTIONS_STOP_BIT);
// 6. 温度データ (2バイト) を読み出す
// ※libmpsseのI2C_DeviceReadは内部で「スタート -> リード -> ストップ」の一連を処理
status = I2C_DeviceRead(ftHandle, ADT7410_ADDRESS, 2, buffer, &bytesTransferred,
I2C_TRANSFER_OPTIONS_START_BIT | I2C_TRANSFER_OPTIONS_STOP_BIT);
if (status == FT_OK && bytesTransferred == 2) {
// 上位・下位バイトを16ビット値に結合
int16_t raw_temp = (int16_t)((buffer[0] << 8) | buffer[1]);
double temperature = 0.0;
// 16ビット分解能の場合の計算方法
// 最上位ビット(MSB)は符号ビット、1 LSB = 0.0078度
temperature = (double)raw_temp / 128.0;
/*
int16_t raw_temp = (int16_t)((buffer[0] << 8) | buffer[1]);
double temperature = 0.0;
// ※もし13ビットモード(デフォルト)のままで読み出す場合の計算方法はこちら
raw_temp = raw_temp >> 3; // 下位3ビットはフラグ等のためシフト
if (raw_temp & 0x1000) { // 13ビットの符号判定
raw_temp -= 8192;
}
temperature = (double)raw_temp * 0.0625;
*/
//ShowMessage("現在の温度: %.4f ℃\n" + FloatToStr(temperature));
Memo1->Lines->Add("現在の温度: " + FloatToStr(temperature) + "°C");
Application->ProcessMessages();
} else {
ShowMessage("データ読み込みエラー\n");
}
#ifdef _WIN32
Sleep(1000); // 1秒待機
#else
sleep(1);
#endif
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
// 7. クローズ処理
I2C_CloseChannel(ftHandle);
Cleanup_libMPSSE();
//return 0;
}
//---------------------------------------------------------------------------Memo1->Lines->Add("現在の温度: " + FloatToStr(temperature) + "°C");
Application->ProcessMessages();
上記のようにしないと、ストップボタン拾えません。32bit版と64bit版両対応のプロジェクトなので、プロジェクト関係は、

上図は64bit Debug版の場合です。あー、別の温湿度センサーsht41のことも書くかなあ?とりあえずADT7410は一旦おしまいにします。

コメント