主頁 > 後端開發 > 計算機COM口資料測驗

計算機COM口資料測驗

2023-07-09 07:49:18 後端開發


計算機COM口資料測驗
一、基本使用流程

程式需要以管理員身份運行,COM口回路測驗需短接2,3pin,測驗時候使用控制臺,配置測驗相關路徑,并在測驗完成后

1.測驗配置路徑D:\bigdata\INI\FWCOM.ini

2.測驗完成后需要在路徑D:\bigdata\LOG\生成測驗FWCOM.log檔案

程式運行結果示意圖

運行完成后的日志檔案示意圖

 二、軟體設計
原始碼分為三個部分,common.cpp基本基本資訊配置,function.cpp完成功能實作,最后通過main.cpp運行整個程式

common.cpp

 

配置函式代碼
#undef UNICODE
#include "common.h"
#include "Config.h"
void TextColor(int color)
{
	HANDLE stdH = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleTextAttribute(stdH, color);
}
void PASS()
{
	printf("The test is: ");

	TextColor(GREEN);
	printf("passed");
	printf("\n");
	printf("\n");
	TextColor(WHITE);

}
void FAIL()
{
	printf("The test is: ");

	TextColor(RED);
	printf("failed");
	printf("\n");
	printf("\n");
	TextColor(WHITE);

}
DWORD SubSystemID(MBTYPE mb[])
{
	DWORD decSubSystemID = 0;
	DWORD aimSubSystemID = 0;
	//	BYTE bus = pciSelect[0], dev = pciSelect[1], func = pciSelect[2], offset = 0x2c;
	BYTE bus = 0;
	BYTE dev = 0;
	BYTE func = 0;
	BYTE offset = 0;
	DWORD address = 0;
	for (int i = 0; i < sizeof(mb); i++)
	{
		//		printf("i = %d\n", i);

		if (mb[i].subSystemId != 0)
		{
			bus = mb[i].bus;
			dev = mb[i].dev;
			func = mb[i].fun;
			offset = mb[i].subSystemIdOffset;
			aimSubSystemID = mb[i].subSystemId;
			address = MAKE_CONFIG_ADDRESS(bus, dev, func, offset);
			FoxLib_SetPortVal(PCI_CONFIG_ADDRESS, address, 4);
			FoxLib_GetPortVal(PCI_CONFIG_DATA, &decSubSystemID, 4);
#ifdef DEBUG
			printf("aimSubSystemID = \"%x\", decSubSystemID = \"%x\"\n", aimSubSystemID, decSubSystemID);
#endif
			if (aimSubSystemID == decSubSystemID)
			{
				return 0;
			}

		}

	}
	printf("Not support MB!\n");
	return 1;
}
void GetGlobalData(char* name)
{
	int i = 0;
	int index = 0;
	int toolSelect = 0;
	if (strstr(name, "hwm") != NULL)
	{
		index = 1;
		for (i = 0; i < cTINumberMax; i++)
		{
			if (cFanName[i][0] != '\0')
			{
				iFanIndex[index] = i;
				index++;
				iAllFanNum++;
			}
		}
		index = 1;
		for (i = 0; i < cTINumberMax; i++)
		{
			if (cTempName[i][0] != '\0')
			{
				iTempIndex[index] = i;

				index++;
				iAllTempNum++;
			}
		}
#ifdef DEBUG
		printf("iAllFanNum = %d, iAllTempNum = %d\n", iAllFanNum, iAllTempNum);
#endif

	}
	else if (strstr(name, "idchk") != NULL)
	{
		index = 1;
		for (i = 0; i < cTINumberMax; i++)
		{
			if (cIdChkName[i][0] != '\0')
			{
				iIdChkIndex[index] = i;
				index++;
				iAllIdChkNum++;
			}
		}
#ifdef DEBUG
		printf("iAllIdChkNum = %d\n", iAllIdChkNum);
#endif

	}
	else if (strstr(name, "pcie") != NULL)
	{
		index = 1;
		for (i = 0; i < cTINumberMax; i++)
		{
			if (cPcieName[i][0] != '\0')
			{
				iPcieIndex[index] = i;
				index++;
				iAllPcieNum++;
			}
		}
#ifdef DEBUG
		printf("iAllPcieNum = %d\n", iAllPcieNum);
#endif

	}
	else if (strstr(name, "sata") != NULL)
	{
		index = 1;
		for (i = 0; i < cTINumberMax; i++)
		{
			if (cSataSpdName[i][0] != '\0')
			{
				iSataSpdIndex[index] = i;
				index++;
				iAllSataSpdNum++;
			}
		}
#ifdef DEBUG
		printf("iAllSataSpdNum = %d\n", iAllSataSpdNum);
#endif

	}
	else if (strstr(name, "fntpnl") != NULL)
	{
		index = 1;
		for (i = 0; i < cTINumberMax; i++)
		{
			if (cFntpnlName[i][0] != '\0')
			{
				iFntpnlIndex[index] = i;
				index++;
				iAllFntpnlNum++;
			}
		}
#ifdef DEBUG
		printf("iAllFntpnlNum = %d\n", iAllFntpnlNum);
#endif

	}
	else if (strstr(name, "jumper") != NULL)
	{
		index = 1;
		for (i = 0; i < cTINumberMax; i++)
		{
			if (cJumperName[i][0] != '\0')
			{
				iJumperIndex[index] = i;
				index++;
				iAllJumperNum++;
			}
		}
#ifdef DEBUG
		printf("iAllJumperNum = %d\n", iAllJumperNum);
#endif

	}

}

int GetDataFromConfig(char* fileName, char* dataConfigAppName, char configItemKey[CONFIGNUM][CONFIGDATALENGTH], char dataArray[CONFIGNUM][CONFIGDATALENGTH])
{
	int ret = 0;
	LPTSTR lpReturnedString = NULL;
	LPCTSTR lpFileName = NULL;

	lpReturnedString = (char*)malloc(MAX_PATH);
	memset(lpReturnedString, 0, MAX_PATH);

	int itemNum = 0;
	int itemOffset = 0;
	while (1)
	{

		GetPrivateProfileString(dataConfigAppName, configItemKey[itemNum], NULL, lpReturnedString, MAX_PATH, fileName);
		if (*lpReturnedString == '\0')
		{
#ifdef DEBUG
			printf("Input data error\n");
			printf("-- dataConfigAppName = %s, itemKey = %s, lpReturnedString = %s, fileName = %s\n", dataConfigAppName, configItemKey[itemNum], lpReturnedString, fileName);
#endif		
			ret = 1;
			break;
		}
		else
		{
			itemOffset = 0;
			while (lpReturnedString)
			{
				if (*lpReturnedString == '\0')
				{
					break;
				}
				dataArray[itemNum][itemOffset] = *lpReturnedString;
				itemOffset++;
				lpReturnedString++;

			}
			lpReturnedString -= itemOffset;
#ifdef DEBUG
			printf("dataConfigAppName = %s, itemKey = %s, lpReturnedString = %s, fileName = %s\n", dataConfigAppName, configItemKey[itemNum], lpReturnedString, fileName);
#endif

			itemNum++;
		}
		memset(lpReturnedString, 0, strlen((char*)lpReturnedString));

	}

	return ret;
}
int LogName(char* logName, char* configName)
{
	int lengthConName = strlen(configName);
	int i = 0;
	for (i = 0; i < (lengthConName - 4); i++)
	{
		*logName = *configName;
		logName++;
		configName++;
	}

	logName -= i;

	sprintf(logName, "%s.TXT", logName);
#ifdef DEBUG
	printf("*logName = \"%s\"\n", logName);
#endif
	FILE* fd = NULL;
	fd = fopen(lpLogFileName, "a+");
	if (fd == NULL)
	{
		printf("Create the log file %s failed\n", lpLogFileName);
		return 1;
	}
	return 0;
}

functonc.cpp

功能函式代碼
#include "function.h"
#include "..\Common\ExConfig.h"

#define BASSADDRONE 0x3F8
HANDLE hCom;
DCB dcb = { sizeof(DCB) };
char com[5];
int Baudrate[3] = { 0 };
DWORD send_data = 'https://www.cnblogs.com/mycnblogs-lumen/archive/2023/07/08/E';
DWORD resv_data = 'https://www.cnblogs.com/mycnblogs-lumen/archive/2023/07/08/A';

/*
函式功能:設定串口(com)基本配置資訊
引數:	baudrate	波特率
		cts	(clear to send)清除發送
		dtr	(data set ready)資料終端準備好
		rts	(request to send)請求資料發送
		dsr	(data set ready)資料準備好
		errorcode  錯誤代碼
		支持硬控制元件流的UART
*/
int SerialSetting(int baudrate, int cts, int dtr, int rts, char errorCode[])
{
	dcb.fDtrControl = DTR_CONTROL_DISABLE;
	dcb.fRtsControl = RTS_CONTROL_DISABLE;

	if (hCom != INVALID_HANDLE_VALUE)
	{
		CloseHandle(hCom);
	}

	hCom = CreateFile(com, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);

	if (hCom == INVALID_HANDLE_VALUE) {
		strcpy_s(itemLog[iItemLogNum].TM_STATUS, "FAIL");
		strcpy_s(itemLog[iItemLogNum].TM_FAILINFO, "DEVICE NO FOUND");
		strcpy_s(itemLog[iItemLogNum].TM_ERRORCODE, errorCode);
		TextColor(RED);
		printf("%s NO FOUND\n\n", com);
		TextColor(WHITE);
		iItemLogNum++;
		return 1;
	}
	system("pause");
	GetCommState(hCom, &dcb);
	dcb.BaudRate = baudrate;
	dcb.ByteSize = 8;
	dcb.Parity = NOPARITY;
	dcb.StopBits = ONESTOPBIT;
	dcb.fOutxCtsFlow = cts;
	dcb.fDtrControl = dtr;
	dcb.fRtsControl = rts;

	int fSuccess = SetCommState(hCom, &dcb);
	if (!fSuccess)	return 1;
	int maskstatus = SetCommMask(hCom, EV_RXCHAR);
	if (maskstatus == 0)	return 1;
	int setupstatus = SetupComm(hCom, 4096, 4096);
	if (setupstatus == 0)	return 1;
	int purgestatus = PurgeComm(hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
	if (purgestatus == 0)	return 1;

	COMMTIMEOUTS CommTimeouts;
	CommTimeouts.ReadIntervalTimeout = MAXDWORD;
	CommTimeouts.ReadTotalTimeoutConstant = 1000;
	CommTimeouts.ReadTotalTimeoutMultiplier = 0;
	CommTimeouts.WriteTotalTimeoutConstant = 1000;
	CommTimeouts.WriteTotalTimeoutMultiplier = 0;
	BOOL bTimeOutResult = SetCommTimeouts(hCom, &CommTimeouts);
	if (bTimeOutResult == 0)	return 1;
	return 0;
}

//串口初始化
int InitCOMOne()
{
	int Status = 0;	//狀態(成功或失敗)
	DWORD sataStatus = 0x0;	//讀寫地址資料

	Status = FoxLib_SetPortVal(BASSADDRONE + 1, 0, 1);
	if (Status != 0x0)
		return Status;

	Status = FoxLib_SetPortVal(BASSADDRONE + 3, 0x80, 1);
	if (Status != 0x0)
		return Status;

	FoxLib_GetPortVal(BASSADDRONE + 0, &sataStatus, 1);

	Status = FoxLib_SetPortVal(BASSADDRONE + 0, 0x0C, 1);
	if (Status != 0x0)
		return Status;

	Status = FoxLib_SetPortVal(BASSADDRONE + 1, 0x00, 1);
	if (Status != 0x0)
		return Status;

	Status = FoxLib_SetPortVal(BASSADDRONE + 3, 0x03, 1);
	if (Status != 0x0)
		return Status;

	return 0x0;
}

//串口發送資料
int Send_COMOne(DWORD my_date)
{
	int Status = 0;	//狀態(成功或失敗)
	DWORD sataStatus = 0x0;	//讀寫地址資料
	UINT32 count = 10000;

	FoxLib_GetPortVal(BASSADDRONE + 5, &sataStatus, 1);

	while (!(sataStatus & 0x20) && (count > 0))
	{
		count--;
		FoxLib_GetPortVal(BASSADDRONE + 5, &sataStatus, 1);
	}

	if (count > 0)
	{
		printf("Count:%d\n", count);
		Status = FoxLib_SetPortVal(BASSADDRONE + 0, my_date, 1);
		if (Status != 0x0)
		{
			return Status;
		}
		printf("Send_COM data %c ", my_date);  //發送資料列印
		TextColor(GREEN);
		printf("Success!\n");
		TextColor(WHITE);
		return 0x0;
	}
	else
	{
		printf("Send_COM data %c ", my_date);
		TextColor(RED);
		printf("Failed!\n\n");
		TextColor(WHITE);
		return 0x01;
	}

}

//串口接收資料
int Recv_COMOne(DWORD* my_date)
{

	DWORD sataStatus = 0;	//讀寫地址資料
	UINT8 cn = 0;

	while (cn < 100)
	{
		FoxLib_GetPortVal(BASSADDRONE + 5, &sataStatus, 1);
		if (sataStatus & 0x01)
			break;
		else
		{
			Sleep(100);
			cn++;
		}
	}
	FoxLib_GetPortVal(BASSADDRONE + 5, &sataStatus, 1);
	if (sataStatus & 0x01)
	{
		FoxLib_GetPortVal(BASSADDRONE + 0, my_date, 1);
		printf("Recv_COM data  %c ", *my_date);
		TextColor(GREEN);
		printf("Success!\n");
		TextColor(WHITE);
		return 0x0;
	}
	else
	{
		printf("Received data ");
		TextColor(RED);
		printf("Failed!\n\n");
		TextColor(WHITE);
		return 0x01; 
	}
}

int IDCheckMain(char* fileName, char dataConfigAppName[cTINumberMax][cTINameMax], BYTE Num)
{
	int ret = 0;
	WORD venID = 0, devID = 0, revID = 0;
	char dataConfigArray[CONFIGNUM][CONFIGDATALENGTH];
	memset(dataConfigArray, 0, CONFIGNUM * CONFIGDATALENGTH);
	char aimTestLocation[30] = { '\0' };
	char aimTestErrorcode[30] = { '\0' };
	strcpy(headLog.T_DEVICE, "IdCheck");

	int iNum = 0;

#ifdef DEBUG
	printf("Num = %d, iIdChkCurrentNum = %d, iAllIdChkNum + 1 = %d\n", Num, iIdChkCurrentNum, iAllIdChkNum + 1);
#endif
	if (iIdChkCurrentNum == (iAllIdChkNum + 1))
	{
		strcpy(headLog.T_CAPTION, "All");

		for (iNum = 1; iNum < iIdChkCurrentNum; iNum++)
		{

			GetDataFromConfig(fileName, dataConfigAppName[iIdChkIndex[iNum]], configItemKeyIDchk, dataConfigArray);
			venID = AtoX(dataConfigArray[0]);
			memset(dataConfigArray[0], 0, strlen((char*)dataConfigArray[0]));

			devID = AtoX(dataConfigArray[1]);
			memset(dataConfigArray[1], 0, strlen((char*)dataConfigArray[1]));

			revID = AtoX(dataConfigArray[2]);
			memset(dataConfigArray[2], 0, strlen((char*)dataConfigArray[2]));

			strcpy(aimTestLocation, dataConfigArray[3]);
			memset(dataConfigArray[3], 0, strlen((char*)dataConfigArray[3]));

			strcpy(aimTestErrorcode, dataConfigArray[4]);
			memset(dataConfigArray[4], 0, strlen((char*)dataConfigArray[4]));


#ifdef DEBUG
			printf("**iFanNum = %d, venID = %X, devID = %X, revID = %X\n", iNum, venID, devID, revID);
			printf("**aimTestLocation = %s\n", aimTestLocation);
			printf("**aimTestErrorcode = %s\n", aimTestErrorcode);
#endif
			ret += IDCheck(cIdChkName[iIdChkIndex[iNum]], venID, devID, revID, aimTestLocation, aimTestErrorcode);

			memset(aimTestLocation, 0, strlen(aimTestLocation));
			memset(aimTestErrorcode, 0, strlen(aimTestErrorcode));

		}
	}
	else
	{
		GetDataFromConfig(fileName, dataConfigAppName[iIdChkIndex[Num]], configItemKeyIDchk, dataConfigArray);
		venID = AtoX(dataConfigArray[0]);
		memset(dataConfigArray[0], 0, strlen((char*)dataConfigArray[0]));

		devID = AtoX(dataConfigArray[1]);
		memset(dataConfigArray[1], 0, strlen((char*)dataConfigArray[1]));

		revID = AtoX(dataConfigArray[2]);
		memset(dataConfigArray[2], 0, strlen((char*)dataConfigArray[2]));

		strcpy(aimTestLocation, dataConfigArray[3]);
		memset(dataConfigArray[3], 0, strlen((char*)dataConfigArray[3]));

		strcpy(aimTestErrorcode, dataConfigArray[4]);
		memset(dataConfigArray[4], 0, strlen((char*)dataConfigArray[4]));

#ifdef DEBUG
		printf("*venID = %X, devID = %X, revID = %X\n", venID, devID, revID);
		printf("**aimTestLocation = %s\n", aimTestLocation);
		printf("**aimTestErrorcode = %s\n", aimTestErrorcode);
#endif
		strcpy(headLog.T_CAPTION, cIdChkName[Num]);
		strcpy(headLog.T_LOCATION, aimTestLocation);

		ret = IDCheck(cIdChkName[Num], venID, devID, revID, aimTestLocation, aimTestErrorcode);
		memset(aimTestLocation, 0, strlen(aimTestLocation));
		memset(aimTestErrorcode, 0, strlen(aimTestErrorcode));

	}

	tEndTime = getEndTime(endTime);
	time(&tEndTime);
	strcpy(headLog.T_ENDTIME, endTime);
	memset(durTime, 0, LENGTHA);
	sprintf(durTime, "%d", int(difftime(tEndTime, tStartTime)));
	//getDURTime(tEndTime, tStartTime, durTime);
	strcpy(headLog.T_DURATION, durTime);

	if (ret == 0)
	{
		strcpy(headLog.T_STATUS, "PASS");
	}
	else
	{
		strcpy(headLog.T_STATUS, "FAIL");
	}

	HeadLogRecord(headLog);
	for (int i = 0; i < iItemLogNum; i++)
	{
		ItemLogRecord(itemLog[i]);
	}
	WriteLogRecord(lpLogFileName);
	return ret;
}

DWORD getBusDevFun(DWORD code)
{
	int iRet = 0;
	BYTE offset = 0;
	DWORD dwAddr = 0, dwData = https://www.cnblogs.com/mycnblogs-lumen/archive/2023/07/08/0, ClassCode = 0;
	for (BYTE i = 0; i < 255; i++)
	{
		BYTE bus = i;
		for (BYTE j = 0; j < 32; j++)
		{
			BYTE dev = j;
			for (BYTE k = 0; k < 8; k++)
			{
				BYTE func = k;
				//check the invalid vendor ID
				offset = 0x00;
				dwAddr = MAKE_CONFIG_ADDRESS(bus, dev, func, offset);
				FoxLib_SetPortVal(PCI_CONFIG_ADDRESS, dwAddr, 4);
				FoxLib_GetPortVal(PCI_CONFIG_DATA, &dwData, 4);
				//	dwData = 0xffffffff;
				DWORD IDCode = dwData;

				if (code == IDCode)
				{
					return (bus << 16) + (dev << 8) + func;
				}
			}
		}
	}
	return 0;
}

//保留idcheck內容,但是這里不使用
int IDCheck(char para[], WORD inVenID, WORD inDevID, WORD inRevID, char subLocation[], char errorCode[])
{
	int result = 1;
	WORD venID = 0, devID = 0, revID = 0;
	WORD devIdTemp1 = 0, devIdTemp2 = 0, devIdTemp3 = 0;
	WORD devIdTemp = 0;
	WORD devIDH = 0, devIDL = 0;
	int bus = 0, dev = 0, func = 0;
	DWORD dwAddr = 0, dwData = 0, classCode = 0;
	BYTE indexPort = 0x2e, dataPort = 0x2f;
	//	BYTE byteData;
	BYTE offset = 0;
	BOOL flag = TRUE;
	BOOL bLanOK = TRUE;

	WORD ecAddr = 0, ecAddrH = 0, ecAddrL = 0;
	WORD ecData = 0;
	//for creat log .txt

	if (strcmpi(para,"sio") == 0)
	{
		//ITE test should add next 4 lines to enter PNP mode
		FoxLib_SetPortVal(indexPort, 0x87, 1);
		FoxLib_SetPortVal(indexPort, 0x01, 1);
		FoxLib_SetPortVal(indexPort, 0x55, 1);
		FoxLib_SetPortVal(indexPort, 0x55, 1);

		//get the vendor (NUVOTON)
		FoxLib_SetPortVal(0x2e, 0x20, 1);
		FoxLib_GetPortVal(0x2f, (PDWORD)&devIdTemp1, 1);
		FoxLib_SetPortVal(0x2e, 0x21, 1);
		FoxLib_GetPortVal(0x2f, (PDWORD)&devIdTemp2, 1);
		FoxLib_SetPortVal(0x2e, 0x22, 1);
		FoxLib_GetPortVal(0x2f, (PDWORD)&devIdTemp3, 1);
		venID = 0;
		devID = (devIdTemp1 << 8) + devIdTemp2;
		revID = devIdTemp3;

		strcpy(itemLog[iItemLogNum].TM_SUBLOCATION, "DeviceID");
		strcpy(itemLog[iItemLogNum].TM_TESTITEM, para);
		sprintf(itemLog[iItemLogNum].TM_EXPVALUE1, "%04X", inDevID);
		sprintf(itemLog[iItemLogNum].TM_ACTVALUE1, "%04X", devID);

		if (inDevID != devID)
		{
			strcat(itemLog[iItemLogNum].TM_FAILINFO, "expValue not equal actValue_");
			strcat(itemLog[iItemLogNum].TM_FAILINFO, "fail");
			strcpy(itemLog[iItemLogNum].TM_ERRORCODE, errorCode);
			strcpy(itemLog[iItemLogNum].TM_STATUS, "FAIL");
		}
		else {
			strcpy(itemLog[iItemLogNum].TM_STATUS, "PASS");
		}

		iItemLogNum++;

		strcpy(itemLog[iItemLogNum].TM_SUBLOCATION, "RevisionID");
		strcpy(itemLog[iItemLogNum].TM_TESTITEM, para);
		sprintf(itemLog[iItemLogNum].TM_EXPVALUE1, "%04X", inRevID);
		sprintf(itemLog[iItemLogNum].TM_ACTVALUE1, "%04X", revID);
		if (inRevID != revID)
		{
			strcat(itemLog[iItemLogNum].TM_FAILINFO, "expValue not equal actValue_");
			strcat(itemLog[iItemLogNum].TM_FAILINFO, "fail");
			strcpy(itemLog[iItemLogNum].TM_ERRORCODE, errorCode);
			strcpy(itemLog[iItemLogNum].TM_STATUS, "FAIL");
		}
		else {
			strcpy(itemLog[iItemLogNum].TM_STATUS, "PASS");
		}
		iItemLogNum++;

	}
	else
	{
		if (strcmpi(para, "pch") == 0)
		{
#ifdef DEBUG
			printf("\n*********\n");
#endif
			// bus 00 dev 1f func 00
			/*int BusDevFun = getBusDevFun(0X06848086);
			bus = (BusDevFun >> 16)&0xff;
			dev = (BusDevFun >> 8)&0xff;
			func = BusDevFun & 0Xff;*/

			bus = 0x00;
			dev = 0x1F;
			func = 0x00;

		}
		else if (strcmpi(para, "audio") == 0)
		{
			// bus 00 dev 1f func 03
			/*int BusDevFun = getBusDevFun(0X06C88086);
			bus = (BusDevFun >> 16) & 0xff;
			dev = (BusDevFun >> 8) & 0xff;
			func = BusDevFun & 0Xff;*/

			bus = 0x00;
			dev = 0x1F;
			func = 0x03;
		}
		else if (strcmpi(para, "lan") == 0)
		{
			int BusDevFun = getBusDevFun(0X816810EC);
			bus = (BusDevFun >> 16) & 0xff;
			dev = (BusDevFun >> 8) & 0xff;
			func = BusDevFun & 0Xff;
		}

		if (bLanOK == TRUE)
		{
			dwAddr = MAKE_CONFIG_ADDRESS(bus, dev, func, 0x00);
			FoxLib_SetPortVal(PCI_CONFIG_ADDRESS, dwAddr, 4);
			FoxLib_GetPortVal(PCI_CONFIG_DATA, &dwData, 4);
			venID = (WORD)dwData;
			devID = (WORD)(dwData >> 16);

			dwAddr = MAKE_CONFIG_ADDRESS(bus, dev, func, 0x08);
			FoxLib_SetPortVal(PCI_CONFIG_ADDRESS, dwAddr, 4);
			FoxLib_GetPortVal(PCI_CONFIG_DATA, &dwData, 4);
			revID = (BYTE)dwData;
		}

		strcpy(itemLog[iItemLogNum].TM_SUBLOCATION, "VendorID");
		strcpy(itemLog[iItemLogNum].TM_TESTITEM, para);
		sprintf(itemLog[iItemLogNum].TM_EXPVALUE1, "%04X", inVenID);
		sprintf(itemLog[iItemLogNum].TM_ACTVALUE1, "%04X", venID);
		if (inVenID != venID)
		{
			strcat(itemLog[iItemLogNum].TM_FAILINFO, "expValue not equal actValue_");
			strcat(itemLog[iItemLogNum].TM_FAILINFO, "fail");
			strcpy(itemLog[iItemLogNum].TM_ERRORCODE, errorCode);
			strcpy(itemLog[iItemLogNum].TM_STATUS, "FAIL");
		}
		else {
			strcpy(itemLog[iItemLogNum].TM_STATUS, "PASS");
		}
		iItemLogNum++;

		strcpy(itemLog[iItemLogNum].TM_SUBLOCATION, "DeviceID");
		strcpy(itemLog[iItemLogNum].TM_TESTITEM, para);
		sprintf(itemLog[iItemLogNum].TM_EXPVALUE1, "%04X", inDevID);
		sprintf(itemLog[iItemLogNum].TM_ACTVALUE1, "%04X", devID);
		if (inDevID != devID)
		{
			strcat(itemLog[iItemLogNum].TM_FAILINFO, "expValue not equal actValue_");
			strcat(itemLog[iItemLogNum].TM_FAILINFO, "fail");
			strcpy(itemLog[iItemLogNum].TM_ERRORCODE, errorCode);
			strcpy(itemLog[iItemLogNum].TM_STATUS, "FAIL");
		}
		else {
			strcpy(itemLog[iItemLogNum].TM_STATUS, "PASS");
		}
		iItemLogNum++;

		strcpy(itemLog[iItemLogNum].TM_SUBLOCATION, "RevisionID");
		strcpy(itemLog[iItemLogNum].TM_TESTITEM, para);
		sprintf(itemLog[iItemLogNum].TM_EXPVALUE1, "%04X", inRevID);
		sprintf(itemLog[iItemLogNum].TM_ACTVALUE1, "%04X", revID);
		if (inRevID != revID)
		{
			strcat(itemLog[iItemLogNum].TM_FAILINFO, "expValue not equal actValue_");
			strcat(itemLog[iItemLogNum].TM_FAILINFO, "fail");
			strcpy(itemLog[iItemLogNum].TM_ERRORCODE, errorCode);
			strcpy(itemLog[iItemLogNum].TM_STATUS, "FAIL");
		}
		else {
			strcpy(itemLog[iItemLogNum].TM_STATUS, "PASS");
		}
		iItemLogNum++;

	}

	if (venID == inVenID && devID == inDevID && revID == inRevID)
	{
		printf("aimvenid: %04X\t aimdevid: %04X\t aimrevid: %04X\n", inVenID, inDevID, inRevID);
		printf("actvenid: %04X\t actdevid: %04X\t actrevid: %04X\n", venID, devID, revID);
		printf("%s ID test is: ", para);
		TextColor(GREEN);
		printf("passed!\n");
		TextColor(WHITE);
		result = 0;
	}
	else
	{
		printf("aimvenid: %04X\t aimdevid: %04X\t aimrevid: %04X\n", inVenID, inDevID, inRevID);
		printf("actvenid: %04X\t actdevid: %04X\t actrevid: %04X\n", venID, devID, revID);
		printf("%s ID test is: ", para);
		TextColor(RED);
		printf("failed!\n");
		TextColor(WHITE);
		result = 1;
	}

	return result;
}

int FwComMain(char* fileName, char dataConfigAppName[cTINumberMax][cTINameMax], BYTE Num)
{
	int nRetCode = 0;
	int iNum = 0;

	char dataConfigArray[CONFIGNUM][CONFIGDATALENGTH];
	memset(dataConfigArray, 0, CONFIGNUM * CONFIGDATALENGTH);
	char aimTestLocation[30] = { '\0' };
	char aimTestErrorcode[30] = { '\0' };
	strcpy(headLog.T_DEVICE, "Serial Port");


#ifdef DEBUG
	printf("Num = %d, iFCOMCurrentNum = %d, iAllFCOMNum + 1 = %d\n", Num, iFCOMCurrentNum, iAllFCOMNum + 1);
#endif
	if (iFCOMCurrentNum == (iAllFCOMNum + 1))
	{

		for (iNum = 1; iNum < iFCOMCurrentNum; iNum++)
		{

			GetDataFromConfig(fileName, cFCOMName[iFCOMIndex[iNum]], configItemKeyFCOM, dataConfigArray);

			strcpy(aimTestLocation, dataConfigArray[1]);
			memset(dataConfigArray[1], 0, strlen((char*)dataConfigArray[1]));

			strcpy(aimTestErrorcode, dataConfigArray[3]);
			memset(dataConfigArray[3], 0, strlen((char*)dataConfigArray[3]));

			Baudrate[0] = atoi(dataConfigArray[4]);
			memset(dataConfigArray[4], 0, strlen((char*)dataConfigArray[4]));

			Baudrate[1] = atoi(dataConfigArray[5]);
			memset(dataConfigArray[5], 0, strlen((char*)dataConfigArray[5]));

			Baudrate[2] = atoi(dataConfigArray[6]);
			memset(dataConfigArray[6], 0, strlen((char*)dataConfigArray[6]));

#ifdef DEBUG
			printf("**iFanNum = %d, Baudrate[0] = %d, Baudrate[1] = %d, Baudrate[2] = %d\n", iNum, Baudrate[0], Baudrate[1], Baudrate[2]);
			printf("**aimTestLocation = %s\n", aimTestLocation);
			printf("**aimTestErrorcode = %s\n", aimTestErrorcode);
#endif

			strcpy(headLog.T_CAPTION, aimTestLocation);
			strcpy(headLog.T_LOCATION, aimTestLocation);

			nRetCode += FwCom(cFCOMName[iFCOMIndex[iNum]], aimTestLocation, aimTestErrorcode, Baudrate);

			memset(aimTestLocation, 0, strlen(aimTestLocation));
			memset(aimTestErrorcode, 0, strlen(aimTestErrorcode));

		}
	}
	else
	{

		GetDataFromConfig(fileName, cFCOMName[Num], configItemKeyFCOM, dataConfigArray);

		strcpy(aimTestLocation, dataConfigArray[1]);
		memset(dataConfigArray[1], 0, strlen((char*)dataConfigArray[1]));

		strcpy(aimTestErrorcode, dataConfigArray[3]);
		memset(dataConfigArray[3], 0, strlen((char*)dataConfigArray[3]));

		Baudrate[0] = atoi(dataConfigArray[4]);
		memset(dataConfigArray[4], 0, strlen((char*)dataConfigArray[4]));

		Baudrate[1] = atoi(dataConfigArray[5]);
		memset(dataConfigArray[5], 0, strlen((char*)dataConfigArray[5]));

		Baudrate[2] = atoi(dataConfigArray[6]);
		memset(dataConfigArray[6], 0, strlen((char*)dataConfigArray[6]));

#ifdef DEBUG
		printf("*Baudrate[0] = %d, Baudrate[1] = %d, Baudrate[2] = %d\n", Baudrate[0], Baudrate[1], Baudrate[2]);
		printf("**aimTestLocation = %s\n", aimTestLocation);
		printf("**aimTestErrorcode = %s\n", aimTestErrorcode);
#endif

		strcpy(headLog.T_CAPTION, aimTestLocation);
		strcpy(headLog.T_LOCATION, aimTestLocation);

		nRetCode = FwCom(cFCOMName[Num], aimTestLocation, aimTestErrorcode, Baudrate);

		memset(aimTestLocation, 0, strlen(aimTestLocation));
		memset(aimTestErrorcode, 0, strlen(aimTestErrorcode));

	}

	tEndTime = getEndTime(endTime);
	time(&tEndTime);
	strcpy(headLog.T_ENDTIME, endTime);
	memset(durTime, 0, LENGTHA);
	sprintf(durTime, "%d", int(difftime(tEndTime, tStartTime)));
	strcpy(headLog.T_DURATION, durTime);

	if (nRetCode == 0)
	{
		strcpy(headLog.T_STATUS, "PASS");
	}
	else
	{
		strcpy(headLog.T_STATUS, "FAIL");
	}

	HeadLogRecord(headLog);
	for (int i = 0; i < iItemLogNum; i++)
	{
		ItemLogRecord(itemLog[i]);
	}
	WriteLogRecord(lpLogFileName);

	return nRetCode;
}

int FwCom(char para[], char subLocation[], char errorCode[], int baudrate[])
{
	int result = 1;
	//for creat log .txt
	strcpy(com, para);
	strcpy(itemLog[iItemLogNum].TM_TESTITEM, para);
	strcpy(itemLog[iItemLogNum].TM_SUBLOCATION, subLocation);

	for (int i = 0; i < 3; i++)
	{
		if (SerialSetting(Baudrate[i], FALSE, DTR_CONTROL_HANDSHAKE, RTS_CONTROL_TOGGLE, errorCode)) return 1;

		printf("%s initing.......\n", para);
		result = InitCOMOne();
		if (result != 0x0)
		{
			printf("COM initing ");
			TextColor(RED);
			printf("Failed!\n\n");
			TextColor(WHITE);
			strcpy(itemLog[iItemLogNum].TM_STATUS, "FAIL");
			strcat(itemLog[iItemLogNum].TM_FAILINFO, "COM initing Fail!!!");
			strcpy(itemLog[iItemLogNum].TM_ERRORCODE, errorCode);
			iItemLogNum++;
			return result;
		}

		result = Send_COMOne(send_data);
		if (result != 0x0)
		{
			strcpy(itemLog[iItemLogNum].TM_STATUS, "FAIL");
			strcat(itemLog[iItemLogNum].TM_FAILINFO, "Send_COM Fail!!!");
			strcpy(itemLog[iItemLogNum].TM_ERRORCODE, errorCode);
			iItemLogNum++;
			return result;
		}

		Sleep(0x100);

		result = Recv_COMOne(&resv_data); //接收Recv_COMOne()函式的回傳值

		//接收失敗,提示
		if (result != 0x0)
		{
			strcpy(itemLog[iItemLogNum].TM_STATUS, "FAIL");
			strcat(itemLog[iItemLogNum].TM_FAILINFO, "Recv_COM Fail!!!");
			strcpy(itemLog[iItemLogNum].TM_ERRORCODE, errorCode);
			iItemLogNum++;
			return result;
		}

		if (resv_data =https://www.cnblogs.com/mycnblogs-lumen/archive/2023/07/08/= send_data)
		{
			printf("COM Send&Receive Test ");
			TextColor(GREEN);
			printf("Passed!\n\n");
			TextColor(WHITE);
			strcpy(itemLog[iItemLogNum].TM_STATUS, "PASS");
			iItemLogNum++;
			return result;
		}
		else
		{
			printf("COM One Send&Receive Test Fail ");
			TextColor(RED);
			printf("Failed!\n\n");
			TextColor(WHITE);
			strcpy(itemLog[iItemLogNum].TM_STATUS, "FAIL");
			strcat(itemLog[iItemLogNum].TM_FAILINFO, "COM Send&Receive Test Fail!!!");
			strcpy(itemLog[iItemLogNum].TM_ERRORCODE, errorCode);
			iItemLogNum++;
			return 0x01;
		}
	}
	return result;
}

main.cpp

主函式帶代碼
 #include "function.h"
#include "..\Common\ExConfig.h"

#ifndef _DEBUG
#define new DEBUG_NEW
#endif

void PromptInformation(char* name)
{
	int i = 0;
	printf("==========================================================================\n");
	printf("*********Diag COM Tool for %s %s*********\n", projectName, FCOM);
	printf("Usage:\n");
	printf("\t%s [number| all] [ConfigFile]\n", name);
	printf("Note:\n");
	printf("\tnumber :\n");
	for (i = 1; i <= iAllFCOMNum; i++)
	{
		if (i == 1)
		{
			printf("\t\t");
		}

		printf("%d:\"%s\" ", i, cFCOMName[iFCOMIndex[i]]);
		if (i == iAllFCOMNum)
		{
			printf("\n");
			printf("\t\tAll: For all the number test \n");

		}
	}
	printf("==========================================================================\n");

}

int main(int argc, char* argv[])
{
	int result1 = 2;
	int iArgvNum = 0;
	BYTE Num = 0;

	char* lpFileName = (char*)malloc(MAX_PATH);
	memset(lpFileName, 0, MAX_PATH);

	strlwr(argv[0]);
	GetGlobalData(argv[0]);

	memset((char*)lpLogFileName, 0, MAX_PATH);

	strcpy(headLog.T_NAME, argv[0]);
	memset(startTime, 0, LENGTHA);
	tStartTime = getNowTime(startTime);
	time(&tStartTime);
	strcpy(headLog.T_STARTTIME, startTime);

	if (argc == 3)
	{
		strlwr(argv[2]);
		if (strstr(argv[2], ".ini") == NULL)
		{
			PromptInformation(argv[0]);
			return 1;
		}

		iArgvNum = 1;
		if (strcmpi(argv[iArgvNum], "all") == 0)
		{
#ifdef DEBUG
			printf("**argv[iArgvNum] = %s\n", argv[iArgvNum]);
#endif
			iFCOMCurrentNum = iAllFCOMNum + 1;
		}
		else
		{
#ifdef DEBUG
			printf("*argv[iArgvNum] = %s\n", argv[iArgvNum]);
#endif
			iFCOMCurrentNum = atoi(argv[iArgvNum]);
			Num = iFCOMIndex[iFCOMCurrentNum];
			if (iFCOMCurrentNum < 1 || iFCOMCurrentNum > iAllFCOMNum)
			{
				printf("Parameter number is out of range.\n");
				PromptInformation(argv[0]);
				return 1;
			}
		}

		iArgvNum = 2;
		if (LogName(lpLogFileName, argv[iArgvNum]))
		{
			return 1;
		}

		if ((argv[iArgvNum][0] == '.') || (argv[iArgvNum][1] == ':'))
		{
			sprintf((char*)lpFileName, "%s", argv[iArgvNum]);

		}
		else
		{
			sprintf((char*)lpFileName, ".\\%s", argv[iArgvNum]);

		}

		result1 = FwComMain(lpFileName, cFCOMName, Num);

	}
	else
	{
		PromptInformation(argv[0]);
		return 1;
	}

	return result1;
}

 

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/556845.html

標籤:其他

上一篇:Python潮流周刊#10:Twitter 的強敵 Threads 是用 Python 開發的!

下一篇:返回列表

標籤雲
其他(162253) Python(38272) JavaScript(25528) Java(18293) C(15239) 區塊鏈(8275) C#(7972) AI(7469) 爪哇(7425) MySQL(7291) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5876) 数组(5741) R(5409) Linux(5347) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4614) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2438) ASP.NET(2404) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) HtmlCss(1993) .NET技术(1986) 功能(1967) Web開發(1951) C++(1942) python-3.x(1918) 弹簧靴(1913) xml(1889) PostgreSQL(1882) .NETCore(1863) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • 計算機COM口資料測驗

    計算機COM口資料測驗一、基本使用流程 程式需要以管理員身份運行,COM口回路測驗需短接2,3pin,測驗時候使用控制臺,配置測驗相關路徑,并在測驗完成后 1.測驗配置路徑D:\bigdata\INI\FWCOM.ini 2.測驗完成后需要在路徑D:\bigdata\LOG\生成測驗FWCOM.lo ......

    uj5u.com 2023-07-09 07:49:18 more
  • Python潮流周刊#10:Twitter 的強敵 Threads 是用 Python 開發的!

    你好,我是貓哥。這里每周分享優質的 Python 及通用技術內容,大部分為英文,已在小標題注明。(標題取自其中一則分享,不代表全部內容都是該主題,特此宣告。) 首發于我的博客:[https://pythoncat.top/posts/2023-07-08-weekly](https://python ......

    uj5u.com 2023-07-09 07:48:59 more
  • C++ 慣用法之 Copy-Swap 拷貝交換

    # C++ 慣用法之 Copy-Swap 拷貝交換 > 這是“C++ 慣用法”合集的第 3 篇,前面 2 篇分別介紹了 RAII 和 PIMPL 兩種慣用法: > > - [RAII: Resouce Acquistion Is Initialization](https://www.cnblogs ......

    uj5u.com 2023-07-09 07:48:48 more
  • Python Django 模版全解與實戰

    **本文首先介紹了Django模板系統的基礎知識,接著探討了如何安裝和配置Django模板系統,然后深入決議了Django模板的基本結構、標簽和過濾器的用法,闡述了如何在模板中展示模型資料,最后使用一個實際專案的例子來演示如何在實際開發中使用Django模板系統。** ## Django模板系統的簡 ......

    uj5u.com 2023-07-09 07:48:44 more
  • spring

    # Spring ## Spring簡介 Spring 是一個開源的設計層面框架,它解決的是業務邏輯層和其他各層的松耦合問題,因此它將面向介面的編程思想貫穿整個系統應 特點: - Spring 是一個開源免費的框架,容器; - Spring 是一個輕量級的框架,非入侵式的; - 控制反轉 IoC,面 ......

    uj5u.com 2023-07-09 07:48:22 more
  • RabbitMQ基本配置

    # 1.用戶角色配置 ![image.png](https://cdn.nlark.com/yuque/0/2023/png/38371876/1688636206975-acd927ca-1559-4236-85f2-07283999d50b.png#averageHue=%23f3f2f2&cl ......

    uj5u.com 2023-07-09 07:48:08 more
  • SpringBoot與MyBatis零XML配置集成和集成測驗

    Java存在很多ORM框架,MyBaits框架是我們專案中使用得最多也是最愿意推薦的框架,它既有資料表和Java物件映射功能,又有原生SQL的特性。在與SpringBoot集成上,和其他框架一樣,可以做到全注解化,無XML配置…… ......

    uj5u.com 2023-07-09 07:48:03 more
  • 從零用python flask框架寫一個簡易的網站

    要用Python寫一個網站,你可以使用Python的Web框架來開發。常見的Python Web框架包括Django、Flask、Bottle等。以下是一個簡單的使用Flask框架開發的示例。 ### 1. 安裝Flask 在開始開發之前,你需要安裝Flask框架。你可以使用以下命令來安裝: ``` ......

    uj5u.com 2023-07-09 07:47:59 more
  • python中zeros函式和ones函式的詳細用法

    在使用Python進行資料分析和科學計算時,經常需要創建和操作多維陣列。NumPy是Python中一個常見的數學庫,它提供了許多方便的函式來創建、操作和處理多維陣列。 NumPy中常用的兩個函式是zeros()函式和ones()函式。這些函式可以幫助我們快速創建特定維度和形狀的多維陣列,并設定初始值 ......

    uj5u.com 2023-07-09 07:46:49 more
  • springboot整合rabbitMQ

    ## 1.生產者工程 - pom.xml里引入依賴 ~~~xml org.springframework.boot spring-boot-starter-amqp ~~~ - application.yml里配置基本資訊 ~~~yaml spring: rabbitmq: host: localh ......

    uj5u.com 2023-07-09 07:46:45 more