天天看點

Cypresse+相機+步進電機開發控制背景開發工具流程

背景

之前用賽普拉斯晶片開發的一個自動攝影項目,并控制機器行為. 這裡未免遺忘,是以做一下記錄.

開發工具

平台: vs2017+Qt,使用C++語言

硬體:cpress晶片+一台相機+一個步進電機.

流程

連接配接好硬體之後,通過上層軟體,控制電機的旋轉平移,并在到達指定位置之後,進行資料采集.

原本為了控制,開發了許多獨立的小功能,為了傻瓜式調用,是以進行了功能封裝.

主要功能代碼

cyPressControl.h頭檔案

class cyPressControl : public QObject
{
	Q_OBJECT

public:

	enum cyPressStatus
	{
		MOTOR_SUCCESS = 0,															//初始化成功.
		MOTOR_WRITESUCCESS = 1,													    //寫入成功.
		MOTOR_READSUCCESS = 2,														//讀取成功.
		MOTOR_FAILED = -1,															//失敗
		MOTOR_NOFOUNDDEVICE = -2,													//找不到裝置.
		MOTOR_BULKOUTEPTNULL = -3,													//寫入端點異常.
		MOTOR_BULKINEPTNULL = -4,													//讀取端點異常.
		MOTOR_WRITEFAILED = -5,														//寫入失敗.
		MOTOR_READFAILED = -6,														//讀取失敗
		MOTOR_HANDLEISNULL = -7,													//裝置句柄為空
		MOTOR_PARAMSERROR = -8													    //設定的參數異常.
	};

	enum cypressDateControlStyle
	{
		Date_Sync,																	//同步讀寫
		Date_Async,																    //異步讀寫
		Date_Thread																	//異步線程讀寫.
	};

	cyPressControl(QObject *parent = nullptr);

	~cyPressControl();

	bool isDeviceStatus{ false };												   //裝置是否初始化成功.

	bool exeCommandFlow();														    //數值測試 執行指令流.

	bool exeCommandFlowHandshake();												    //互動式執行.

	void stopExeCommand();															//停止執行指令.

	int getTotalSteps();														    //擷取電機前進總步數.這裡式内部維護的一個變量.

	int getTotalStepsByCommand();													//通過讀取指令,擷取總步數.

	void setTotalSteps(int steps);													//設定總步數.

	bool reSetCommand();															//電機複位(即回退指令)

	inline void LoopTime(int time = 100);

	bool isAbnormal();																//異常


protected:

	cyPressStatus InitCpressDevice();												 //初始化,并設定端點

	bool destroyCpressDevice();														 //銷毀裝置資訊,以及釋放資源.

	virtual cyPressStatus writeDate(byte* buffer, long bufferLength,
		byte wEndPtrAddress = 0x02);												 //指定寫入端點,寫入資料.

	virtual cyPressStatus SyncWriteDate(byte* buffer, long bufferLength,
		byte wEndPtrAddress = 0x02);

	virtual cyPressStatus writeCommand(byte command, UINT16 numberPerStpes = 800);	//寫入指令.以及前進的步數. 機關um微米.

	virtual cyPressStatus readCommand(byte &outStatus);								//讀取下位機傳回值.

	cyPressStatus readDate(byte* outbuffer, long bufferLength,
		byte rEndPtrAddress = 0x86);												//指定讀取端點,讀取資料.

	virtual cyPressStatus SyncReadDate(byte* outbuffer,
		long bufferLength, byte rEndPtrAddress = 0x86);								 //同步讀取資料

	bool cellCommand(int input, int &resullt, int spaceTime = 1000,
		bool isWrite = true, bool isRead = true);

	bool cellCommandHandshake(byte input, byte &result, bool isWrite = true,
		bool isRead = true, int spaceTime = 1000);									 //讀寫指令

	std::tuple<byte, byte> dec2Towhex(UINT16 number);

	QMutex _mutex;


signals:

	void sigPopStep(QString msg, bool effective);									   //彈射指令序号.

private:

	std::shared_ptr<CCyUSBDevice> _ccyusbDevice{ nullptr };							 	  //内部維護.

	CCyBulkEndPoint *bulkoutEpt = { nullptr };										 	  //寫入端點

	CCyBulkEndPoint *bulkInEpt = { nullptr };										 	  //讀取端點

	cypressDateControlStyle _syPressaDateStyle = { cypressDateControlStyle::Date_Async };

	bool exeCommandStop{ false };														 //步進電機停止執行疊代.

	int reCordTotalSteps = { 0 };														 //記錄電機總步數.

	const int LengthPerStep = { 800 };													 //設定初始步伐常量為800um;
};
           

cyPressControl.cpp

#include "cyPressControl.h"
#include <QEventLoop>
#include <QTimer>
#include <qfuture.h>
#include <QtConcurrent/qtconcurrentmapkernel.h>
#include <QtConcurrent/qtconcurrentrun.h>

cyPressControl::cyPressControl(QObject *parent)
	: QObject(parent)
{
	if (InitCpressDevice() == 0)
	{
		isDeviceStatus = true;
	}
	else
	{
		isDeviceStatus = false;
	}
}

cyPressControl::~cyPressControl()
{
	destroyCpressDevice();
}

cyPressControl::cyPressStatus cyPressControl::InitCpressDevice()
{
	if (_ccyusbDevice = std::make_shared<CCyUSBDevice>())
	{
		//查找目标裝置.
		int sourceID = -1;
		for (int i = 0; i < _ccyusbDevice->DeviceCount(); i++)
		{
			if (_ccyusbDevice->Open(i))
			{
				if (_ccyusbDevice->IsOpen() == true) //過濾掉已經打開的裝置.
				{
					QString deviceName = _ccyusbDevice->DeviceName;
					if (deviceName.toUpper().contains("EZ-USB"))
					{
						sourceID = i;
						break;
					}
				}
			}
			_ccyusbDevice->Close();
		}

		//和目标裝置建立連接配接.
		if (sourceID != -1)
		{
			_ccyusbDevice->Open(sourceID);

			if (_ccyusbDevice->IsOpen() == false)
			{
				std::cout << "打開裝置失敗" << std::endl;
				return cyPressStatus::MOTOR_NOFOUNDDEVICE;
			}
			else
			{
				CCyUSBEndPoint *endpt;
				std::cout << "已經找到了裝置: " << _ccyusbDevice->DeviceName << std::endl;
				int eptCount = _ccyusbDevice->EndPointCount();
				for (int i = 1; i < eptCount; i++)
				{
					endpt = _ccyusbDevice->EndPoints[i];
					qDebug() << QStringLiteral("目前端點: %1").arg(endpt->Address);
					bool bIn = ((_ccyusbDevice->EndPoints[i]->Address & 0x80) == 0x80);
					bool bBulk = (_ccyusbDevice->EndPoints[i]->Attributes == 2);
					if (bBulk && bIn) bulkInEpt = (CCyBulkEndPoint *)_ccyusbDevice->EndPoints[i];
					if (bBulk && !bIn) bulkoutEpt = (CCyBulkEndPoint *)_ccyusbDevice->EndPoints[i];
				}
			}
		}
		else
		{
			return MOTOR_NOFOUNDDEVICE;
			qDebug() << QStringLiteral("找不到裝置");
		}

		if (bulkoutEpt == nullptr || bulkInEpt == nullptr)
		{
			return cyPressStatus::MOTOR_BULKINEPTNULL;
		}

		return cyPressStatus::MOTOR_SUCCESS;
	}
	else
	{
		qDebug() << QStringLiteral("USBDevice is nullptr");
		return cyPressStatus::MOTOR_FAILED;
	}
}

bool cyPressControl::destroyCpressDevice()
{
	if (_ccyusbDevice != nullptr)
	{
		_ccyusbDevice->Close();
		_ccyusbDevice.reset();
	}

	return true;
}

cyPressControl::cyPressStatus cyPressControl::writeDate(byte * buffer, long bufferLength, byte wEndPtrAddress)
{
	qDebug() << QStringLiteral("寫入線程ID: %1").arg(GetCurrentThreadId());
	if (_ccyusbDevice != nullptr)
	{
		if (buffer == nullptr || bufferLength < 0)
		{
			return cyPressStatus::MOTOR_PARAMSERROR;
		}

		bulkoutEpt = (CCyBulkEndPoint *)_ccyusbDevice->EndPointOf(wEndPtrAddress);
		if (bulkoutEpt == nullptr)
		{
			return cyPressStatus::MOTOR_HANDLEISNULL;
		}
		OVERLAPPED outOvLap;
		outOvLap.hEvent = CreateEvent(NULL, false, false, L"CYUSB_OUT");
		if (outOvLap.hEvent == nullptr)
		{
			return cyPressStatus::MOTOR_HANDLEISNULL;
		}

		UCHAR *outContext = bulkoutEpt->BeginDataXfer(buffer, bufferLength, &outOvLap);
		if (outContext != nullptr)
		{
			bulkoutEpt->WaitForXfer(&outOvLap, 200);//100ms
			bool success = bulkoutEpt->FinishDataXfer(buffer, bufferLength, &outOvLap, outContext);
			CloseHandle(outOvLap.hEvent);
			if (success == true)
			{
				return cyPressStatus::MOTOR_WRITESUCCESS;
			}
			else
			{
				return cyPressStatus::MOTOR_WRITEFAILED;
			}
		}
		else
		{
			return cyPressStatus::MOTOR_HANDLEISNULL;
		}
	}
	else
	{
		return cyPressStatus::MOTOR_HANDLEISNULL;
	}
}

cyPressControl::cyPressStatus cyPressControl::SyncWriteDate(byte * buffer, long bufferLength, byte wEndPtrAddress)
{
	qDebug() << QStringLiteral("寫入線程ID: %1").arg(GetCurrentThreadId());
	if (_ccyusbDevice != nullptr)
	{
		if (buffer == nullptr || bufferLength < 0)
		{
			return cyPressStatus::MOTOR_PARAMSERROR;
		}

		bulkoutEpt = (CCyBulkEndPoint *)_ccyusbDevice->EndPointOf(wEndPtrAddress);
		if (bulkoutEpt == nullptr)
		{
			return cyPressStatus::MOTOR_HANDLEISNULL;
		}

		bool success = bulkoutEpt->XferData(buffer, bufferLength);
		if (success == true)
		{
			return cyPressStatus::MOTOR_WRITESUCCESS;
		}
		else
		{
			return cyPressStatus::MOTOR_WRITEFAILED;
		}
	}
	else
	{
		return cyPressStatus::MOTOR_HANDLEISNULL;
	}
}

cyPressControl::cyPressStatus cyPressControl::writeCommand(byte command, UINT16 numberPerStpes)
{
	cyPressStatus wStatus = cyPressStatus::MOTOR_FAILED;
	byte *writebuffer = new byte[10];
	int length = 10;
	if (writebuffer != nullptr)
	{
		ZeroMemory(writebuffer, 10);
		writebuffer[0] = command; //第一個為指令位址.

		//解析指令numberPerStpes
		std::tuple<byte, byte> getDate = dec2Towhex(numberPerStpes);
		writebuffer[1] = std::get<0>(getDate);
		writebuffer[2] = std::get<1>(getDate);
		qDebug() << QStringLiteral("解析步長: 0x%1  0x%2").arg(writebuffer[1]).arg(writebuffer[2]);

		switch (_syPressaDateStyle)
		{
		case cyPressControl::Date_Sync:
		{
			wStatus = SyncWriteDate(writebuffer, 10); //同步寫入資料.
			break;
		}
		case cyPressControl::Date_Async:
		{
			wStatus = writeDate(writebuffer, 10);	  //異步寫入資料.
			break;
		}
		case cyPressControl::Date_Thread:
		{
			byte rEndPtrAddress = 0x02;
			QFuture<cyPressStatus> f1 = QtConcurrent::run(this, &cyPressControl::SyncWriteDate, writebuffer, length, rEndPtrAddress);
			f1.waitForFinished();
			break;
		}
		default:
			wStatus = writeDate(writebuffer, 10);
			break;
		}

		delete[]writebuffer;
		writebuffer = nullptr;
	}
	return wStatus;
}

cyPressControl::cyPressStatus cyPressControl::readCommand(byte &outStatus)
{
	cyPressStatus rStatus = cyPressStatus::MOTOR_FAILED;
	long length = 10;
	byte* readbuffer = new byte[10];
	if (readbuffer != nullptr)
	{
		ZeroMemory(readbuffer, length);
		switch (_syPressaDateStyle)
		{
		case cyPressControl::Date_Sync:
		{
			rStatus = SyncReadDate(readbuffer, length); //同步讀取資料
			break;
		}
		case cyPressControl::Date_Async:
		{
			rStatus = readDate(readbuffer, length);	   //異步讀取資料
			break;
		}
		case cyPressControl::Date_Thread:
		{
			byte rEndPtrAddress = 0x86;
			QFuture<cyPressStatus> f1 = QtConcurrent::run(this, &cyPressControl::SyncReadDate, readbuffer, length, rEndPtrAddress);
			f1.waitForFinished();
			break;
		}
		default:
			rStatus = readDate(readbuffer, length);
			break;
		}

		if (readbuffer != nullptr)
		{
			outStatus = readbuffer[0];
		}

		QString logInfoRead = QStringLiteral("讀取資料: %1   讀取裝置狀态: %2   ").arg(outStatus).arg(rStatus);
		qDebug() << logInfoRead;

		if (readbuffer != nullptr)
		{
			delete[] readbuffer;
			readbuffer = nullptr;
		}
	}

	return rStatus;
}

cyPressControl::cyPressStatus cyPressControl::readDate(byte *outbuffer, long bufferLength, byte rEndPtrAddress)
{
	qDebug() << QStringLiteral("讀取線程ID: %1").arg(GetCurrentThreadId());
	if (_ccyusbDevice != nullptr)
	{
		if (outbuffer == nullptr)
		{
			return cyPressStatus::MOTOR_PARAMSERROR;
		}

		if (!(bulkInEpt = (CCyBulkEndPoint *)_ccyusbDevice->EndPointOf(rEndPtrAddress)))
		{
			//端點位址失敗後,嘗試重新擷取.
			bulkInEpt = _ccyusbDevice->BulkInEndPt;
		}

		if (bulkInEpt == nullptr)
		{
			qDebug() << QStringLiteral("bulkInEpt is null");
			return  cyPressStatus::MOTOR_HANDLEISNULL;
		}

		OVERLAPPED inOvLap;
		inOvLap.hEvent = CreateEvent(NULL, false, false, L"CYUSB_IN");
		if (inOvLap.hEvent == nullptr)
		{
			qDebug() << QStringLiteral("inOvLap.hEvent is null");
			return  cyPressStatus::MOTOR_HANDLEISNULL;
		}
		UCHAR *inContext = bulkInEpt->BeginDataXfer(outbuffer, bufferLength, &inOvLap);
		if (inContext != nullptr)
		{
			bulkInEpt->WaitForXfer(&inOvLap, 2000); //100mS等待.
			bool success_read = bulkInEpt->FinishDataXfer(outbuffer, bufferLength, &inOvLap, inContext);

			if (success_read == true)
			{
				CloseHandle(inOvLap.hEvent);
				return  cyPressStatus::MOTOR_READSUCCESS;
			}
			else
			{
				CloseHandle(inOvLap.hEvent);
				return cyPressStatus::MOTOR_READFAILED;
			}
		}
		else
		{
			qDebug() << QStringLiteral("_ccyusbDevice is null");
			return  cyPressStatus::MOTOR_HANDLEISNULL;
		}
	}
	else
	{
		return cyPressStatus::MOTOR_READFAILED;
	}
}

cyPressControl::cyPressStatus cyPressControl::SyncReadDate(byte * outbuffer, long bufferLength, byte rEndPtrAddress)
{
	qDebug() << QStringLiteral("讀取線程ID: %1").arg(GetCurrentThreadId());
	if (_ccyusbDevice != nullptr)
	{
		if (outbuffer == nullptr)
		{
			return cyPressStatus::MOTOR_PARAMSERROR;
		}

		if (!(bulkInEpt = (CCyBulkEndPoint *)_ccyusbDevice->EndPointOf(rEndPtrAddress)))
		{
			//端點位址失敗後,嘗試重新擷取.
			bulkInEpt = _ccyusbDevice->BulkInEndPt;
		}

		if (bulkInEpt == nullptr)
		{
			qDebug() << QStringLiteral("bulkInEpt is null");
			return  cyPressStatus::MOTOR_HANDLEISNULL;
		}
		else
		{
			//傳輸資料 同步傳輸資料.
			bool success_read = bulkInEpt->XferData(outbuffer, bufferLength, nullptr);
			if (success_read == true)
			{
				return  cyPressStatus::MOTOR_READSUCCESS;
			}
			else
			{
				return cyPressStatus::MOTOR_READFAILED;
			}
		}
	}
	else
	{
		return cyPressStatus::MOTOR_READFAILED;
	}
}

std::tuple<byte, byte> cyPressControl::dec2Towhex(UINT16 number)
{
	short int right, left;
	right = number & 0x00ff; // 取右8位
	left = number >> 8;	     // 取左8位
	return std::tuple<byte, byte>(left, right);
}
bool cyPressControl::exeCommandFlow()
{
	qDebug() << QStringLiteral("相機次線程ID: %1").arg(GetCurrentThreadId());
	//執行指令循環.
	int timeOut = 200;
	int input = 2;
	int result[5]{ 0,0,0,0,0 };
	QString sendstr;
	if (cellCommand(input, result[0]) == true)
	{
		sendstr = QStringLiteral("step: %1  %2  %3").arg(1).arg(input).arg(result[0]);
		emit sigPopStep(sendstr, false);
		emit sigPopStep(QStringLiteral("STEP1"), true);
		input = 4;
		LoopTime(1500);
		if (cellCommand(input, result[1]) == true)
		{
			sendstr = QStringLiteral("step: %1  %2  %3").arg(2).arg(input).arg(result[1]);
			emit sigPopStep(sendstr, false);
			emit sigPopStep(QStringLiteral("STEP2"), true);
			input = 6;
			LoopTime(1200);
			if (cellCommand(input, result[2]) == true)
			{
				sendstr = QStringLiteral("step: %1  %2  %3").arg(3).arg(input).arg(result[2]);
				emit sigPopStep(sendstr, false);
				emit sigPopStep(QStringLiteral("STEP3"), true);
				input = 8;
				LoopTime(1200);
				bool eightStatus = false;
				do
				{
					LoopTime(1200);
					eightStatus = cellCommand(input, result[3], 3000, true, true);
					sendstr = QStringLiteral("step: %1  %2  %3").arg(4).arg(input).arg(result[3]);
					emit sigPopStep(sendstr, false);
					emit sigPopStep(QStringLiteral("STEP4"), false);
					emit sigPopStep("ExeEnd", false);
					break;
				} while (1);

				return eightStatus;
			}
			else
			{
				return false;
			}
		}
		else
		{
			return false;
		}
	}
	else
	{
		return false;
	}
}

bool cyPressControl::cellCommandHandshake(byte input, byte &result, bool isWrite, bool isRead, int spaceTime)
{
	//測試專用資料.
	byte commanRandom[6] = { 0x01,0x09,0x01,0x06,0x01,0x08 };
	byte GetCommand = commanRandom[(rand() % 4 + 1)];

	if (input > 0x00 && input < 253)
	{
		cyPressStatus wStatus = cyPressStatus::MOTOR_FAILED, rStatus = cyPressStatus::MOTOR_FAILED;
		int iteratorNumber = 0;
		int recordGoNumbers = 0;
		do
		{
			if (isWrite == true)
			{
				wStatus = writeCommand(input, LengthPerStep);
				//wStatus = writeCommand(GetCommand, LengthPerStep); //測試異常指令.
				if (wStatus == cyPressStatus::MOTOR_WRITESUCCESS)
				{
					isWrite = false;
				}

				QString logInfoWrite = QStringLiteral("寫入資料: %1   寫入資料的狀态: %2  ").arg(GetCommand).arg(wStatus);
				emit sigPopStep(logInfoWrite, false);
			}

			LoopTime(spaceTime);
			if ((isRead == true) && (wStatus == cyPressStatus::MOTOR_WRITESUCCESS))
			{
				recordGoNumbers = 0;
				recordGoNumbers = result;
				rStatus = readCommand(result);
				if (rStatus == cyPressStatus::MOTOR_READFAILED)
				{
					reCordTotalSteps = result;
				}

				if (iteratorNumber == 2)
				{
					QString logInfoRead = QStringLiteral("讀取狀态: %1  記錄上次觸發資料: %2   讀取資料: %3  ").arg(rStatus).arg(recordGoNumbers).arg(result);				//釋放記憶體.
					emit sigPopStep(logInfoRead, false);
				}

				LoopTime(200);
			}

			if ((result - recordGoNumbers) != 1)
			{
				//循環
				if (iteratorNumber >= 6)
				{
					break;
				}
			}
			else
			{
				if (iteratorNumber >= 2)
				{
					break;
				}
			}

			iteratorNumber++;
		} while (iteratorNumber < 6); //(iteratorNumber < 6) && (((result - recordGoNumbers) != 1))

		if ((((result != 255)) || ((result - recordGoNumbers) == 1)) && wStatus == cyPressStatus::MOTOR_WRITESUCCESS && rStatus == cyPressStatus::MOTOR_READSUCCESS)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	else
	{
		return false;
	}
}

bool cyPressControl::exeCommandFlowHandshake()
{
	const int motorGoAheadUnit = LengthPerStep;//前進的機關距離.20個脈沖前進1um
	long motorDistance = 0;					  //前進的距離 機關um
	long motorGoAheadCount = 0;				  //前進步數
	const int IteraterNumber = 50;			  //設定疊代次數
	QString sendstr;
	bool status = false;
	exeCommandStop = true;
	long reconrdIteraterContolNumber = 0;
	do
	{
		QMutexLocker lock(&_mutex);
		if (exeCommandStop == false)
		{
			break;
		}

		byte input = 0x01;
		byte result = 0;
		if (cellCommandHandshake(input, result, true, true, 200) == true)
		{
			//正常執行.發送拍照指令. 進行拍照執行.
			sendstr = QStringLiteral("step: %1  執行指令:%2  電機總步數: %3").arg(++reconrdIteraterContolNumber).arg(input).arg(result);

			emit sigPopStep(sendstr, false);

			if (result != 254 && result != 255 && result >= 0) //擷取到的資料不為0,複位成功254 或者 255異常,才可以進行拍照設定.
			{
				emit sigPopStep(QStringLiteral("%1").arg(++motorGoAheadCount), true);
			}

			LoopTime(1200);
			status = true;
		}
		else
		{
			emit sigPopStep(QStringLiteral("電機異常,正在執行複位"), false);
			emit sigPopStep(QStringLiteral("RESET"), true);
			//執行複位指令(電機回退)
			if (reSetCommand() == true)
			{
				emit sigPopStep(QStringLiteral("電機複位成功."), false);
			}

			status = false;
			break;
		}

		motorDistance = motorGoAheadCount * motorGoAheadUnit;


	} while ((motorDistance < 15000) || (motorGoAheadCount < IteraterNumber));

	return status;
}

bool cyPressControl::cellCommand(int input, int &resullt, int spaceTime, bool isWrite, bool isRead)
{
	QStringList logInfoList;
	if (input > 1 && input < 100)
	{
		cyPressStatus wStatus = cyPressStatus::MOTOR_FAILED, rStatus = cyPressStatus::MOTOR_FAILED;
		int iteratorNumber = 0;
		do
		{
			if (isWrite == true)
			{
				//寫入.
				byte *writebuffer = new byte[10];
				int length = 10;
				if (writebuffer != nullptr)
				{
					ZeroMemory(writebuffer, 10);
					for (int i = 0; i < 10; i++)
					{
						writebuffer[i] = input;
					}

					switch (_syPressaDateStyle)
					{
					case cyPressControl::Date_Sync:
					{
						wStatus = SyncWriteDate(writebuffer, 10); //同步寫入資料.
						break;
					}
					case cyPressControl::Date_Async:
					{
						wStatus = writeDate(writebuffer, 10);	  //異步寫入資料.
						break;
					}
					case cyPressControl::Date_Thread:
					{
						byte rEndPtrAddress = 0x02;
						QFuture<cyPressStatus> f1 = QtConcurrent::run(this, &cyPressControl::SyncWriteDate, writebuffer, length, rEndPtrAddress);
						f1.waitForFinished();
						break;
					}
					default:
						break;
					}

					delete[]writebuffer;
					writebuffer = nullptr;

					if (wStatus != cyPressStatus::MOTOR_WRITESUCCESS)
					{
						emit sigPopStep(QStringLiteral("寫入指令失敗..."), false);
					}
					else
					{
						isWrite = false; //隻寫一次.
					}
				}

				QString logInfoWrite = QStringLiteral("寫入資料: %1   寫入資料的狀态: %2  ").arg(input).arg(wStatus);
				emit sigPopStep(logInfoWrite, false);
			}

			QEventLoop qloop;
			QTimer::singleShot(spaceTime, &qloop, &QEventLoop::quit);
			qloop.exec();

			if ((isRead == true) && (wStatus == cyPressStatus::MOTOR_WRITESUCCESS))
			{
				//讀取.
				long length = 10;
				byte* readbuffer = new byte[10];
				if (readbuffer != nullptr)
				{
					ZeroMemory(readbuffer, length);

					switch (_syPressaDateStyle)
					{
					case cyPressControl::Date_Sync:
					{
						rStatus = SyncReadDate(readbuffer, length); //同步讀取資料
						break;
					}
					case cyPressControl::Date_Async:
					{
						rStatus = readDate(readbuffer, length);	   //異步讀取資料
						break;
					}
					case cyPressControl::Date_Thread:
					{
						byte rEndPtrAddress = 0x86;
						QFuture<cyPressStatus> f1 = QtConcurrent::run(this, &cyPressControl::SyncReadDate, readbuffer, length, rEndPtrAddress);
						f1.waitForFinished();
						break;
					}
					default:
						break;
					}

					if (readbuffer != nullptr)
					{
						resullt = readbuffer[0];
					}

					QString logInfoRead = QStringLiteral("讀取資料: %1   讀取資料的狀态: %2  ").arg(resullt).arg(rStatus);				//釋放記憶體.
					emit sigPopStep(logInfoRead, false);

					if (readbuffer != nullptr)
					{
						delete[] readbuffer;
						readbuffer = nullptr;
					}
				}

				QEventLoop qloop2;
				QTimer::singleShot(200, &qloop2, &QEventLoop::quit);
				qloop2.exec();
			}

			iteratorNumber++;
			qDebug() << "";
		} while (iteratorNumber < 4 && ((resullt - input) != 1));

		if ((resullt - input) == 1)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	else
	{
		return false;
	}
}


void cyPressControl::stopExeCommand()
{
	qDebug() << QStringLiteral("停止線程ID: %1").arg(GetCurrentThreadId());
	QMutexLocker lock(&_mutex);
	exeCommandStop = false;
}

int cyPressControl::getTotalSteps()
{
	return reCordTotalSteps;
}

int cyPressControl::getTotalStepsByCommand()
{
	byte ControlSteps = -1;
	cyPressStatus rStatus = readCommand(ControlSteps);
	if (rStatus == cyPressStatus::MOTOR_READSUCCESS)
	{
		if (ControlSteps > 0 && ControlSteps != 254 && ControlSteps != 255)
		{
			return ControlSteps;
		}
		else
		{
			return -1;
		}
	}
	else
	{
		return -1;
	}
}

void cyPressControl::setTotalSteps(int steps)
{
	reCordTotalSteps = steps;
}

bool cyPressControl::reSetCommand()
{
	int TotalSteps = getTotalStepsByCommand();
	//判斷回退步數,将非254 以及255 的資料剔除
	if ((TotalSteps == 254 || TotalSteps == 255) && TotalSteps > 0)
	{
		//異常資料,進行軟體内部資料的矯正.
		TotalSteps = getTotalSteps();
	}

	emit sigPopStep(QStringLiteral("步進電機回退步數:%1").arg(TotalSteps), false);
	long distance = TotalSteps * LengthPerStep;
	bool write = true;
	bool read = true;
	cyPressStatus wStatus = cyPressStatus::MOTOR_FAILED, rStatus = cyPressStatus::MOTOR_FAILED;
	byte outDate = 0;
	int iteratorCount = 0;
	do
	{
		if (write == true)
		{
			wStatus = writeCommand(0x02, distance);//執行複位指令
			if (wStatus == cyPressStatus::MOTOR_WRITESUCCESS)
			{
				write = false;
			}
		}

		_sleep(2000);

		if ((read == true) && (wStatus == cyPressStatus::MOTOR_WRITESUCCESS))
		{
			rStatus = readCommand(outDate);
			qDebug() << QStringLiteral("複位狀态: %1  %2").arg(rStatus).arg(outDate);
		}

		if (((outDate == 254) || (outDate == 255)) && (wStatus == cyPressStatus::MOTOR_WRITESUCCESS) && (rStatus == cyPressStatus::MOTOR_READSUCCESS))
		{
			break;
		}

		iteratorCount++;
	} while (iteratorCount < 5);

	//複位完成.
	if (outDate == 254 && (wStatus == cyPressStatus::MOTOR_WRITESUCCESS) && (rStatus == cyPressStatus::MOTOR_READSUCCESS))
	{
		emit sigPopStep(QStringLiteral("電機複位成功."), false);
		return true;
	}
	else
	{
		emit sigPopStep(QStringLiteral("電機複位失敗."), false);
		return false;
	}
}

inline void cyPressControl::LoopTime(int time)
{
	QEventLoop qloop;
	QTimer::singleShot(time, &qloop, &QEventLoop::quit);
	qloop.exec();
}

bool cyPressControl::isAbnormal()
{
	//讀取資料,判斷其是否為254;
	byte outDate;
	readCommand(outDate);
	if (outDate == 255)
	{
		return true;
	}

	return false;
}
           

封裝內建的功能展示

class cyPressControl;
class STEPPINGMOTROSDK_EXPORT StepPingMotroSDK
{
public:

	StepPingMotroSDK();

	/******************************************************/
	// 函數名   : initStepPingMotroSDK
	// 功能描述 : 初始化
	// 參數     : 
	//			: 
	//			:
	// 傳回值   : 成功傳回true  失敗傳回false
	/******************************************************/
	bool initStepPingMotroSDK();	

	/******************************************************/
	// 函數名   : dstroyStepPingMotroSDK
	// 功能描述 : 銷毀
	// 參數     : 
	//			: 
	//			:
	// 傳回值   : 成功傳回true  失敗傳回false
	/******************************************************/
	void dstroyStepPingMotroSDK();		

	/******************************************************/
	// 函數名   : stopExeCommand
	// 功能描述 : 停止執行指令
	// 參數     : 
	//			:
	//			:
	// 傳回值   : 成功傳回true  失敗傳回false
	/******************************************************/
	bool stopExeCommand();			


	/******************************************************/
	// 函數名   : startExeCommand
	// 功能描述 : 開始執行指令
	// 參數     : 
	//			:
	//			:
	// 傳回值   : 成功傳回true  失敗傳回false
	/******************************************************/
	bool startExeCommand();				


	/******************************************************/
	// 函數名   : setTotalSteps
	// 功能描述 : 設定前進步數
	// 參數     :
	//			: 
	//			:
	// 傳回值   : 成功傳回true  失敗傳回false
	/******************************************************/
	bool setTotalSteps(int steps);		

	/******************************************************/
	// 函數名   : getTotalSteps
	// 功能描述 : 擷取電機總步數
	// 參數     : 
	//			: 
	//			:
	// 傳回值   : 成功傳回true  失敗傳回false
	/******************************************************/
	int getTotalSteps();				


	/******************************************************/
	// 函數名   : reSetCommand
	// 功能描述 : 電機複位
	// 參數     :
	//			:
	//			:
	// 傳回值   : 成功傳回true  失敗傳回false
	/******************************************************/
	bool reSetCommand();				


	/******************************************************/
	// 函數名   : isAbnormal
	// 功能描述 : 電機是否運作異常
	// 參數     : 
	//			: 
	//			:
	// 傳回值    : 成功傳回true  失敗傳回false
	/******************************************************/
	bool isAbnormal();					

private:

	std::shared_ptr<cyPressControl> _cyPressControl = {nullptr};

};
           

最後,進行調用調試

Cypresse+相機+步進電機開發控制背景開發工具流程

到此,調試完成