WinCE工控主板支持高速脉冲计数

       ESM7000是支持正版WEC7 / Linux的双核Cortex-A7工业级工控主板,支持双网口、双CAN6路串口、触摸屏显示接口等,广泛应用于工控智能终端设备。根据客户的应用需求,我们为ESM7000增加了输入脉冲计数功能,支持对几赫兹到数十兆赫兹的输入脉冲信号进行准确计数,实现脉冲数量统计,脉冲频率换算功能。

WinCE工控主板支持高速脉冲计数_第1张图片

ESM7000 WinCE / Linux工控主板

1.  实现原理

       对于低频脉冲信号计数,可通过简单的GPIO中断来实现。当输入脉冲频率超过数千赫兹时,频繁的GPIO中断会降低系统性能,并存在丢数风险,所以对高速脉冲计数通常需要专门的硬件来实现。

       ESM7000主CPUNXPi.MX7D,我们利用了i.MX7D的通常定时器(GPT)Capture功能来实现对高速脉冲的硬件计数。脉冲计数涉及到两个输入信号:1)被测信号——脉冲信号输入;2)测量周期控制信号——用于触发CPU Capture功能实现计数捕捉。

WinCE工控主板支持高速脉冲计数_第2张图片

ESM7000脉冲计数功能对应的GPIO如下所示:

ESM7000 Pin

ESM7000 GPIO

功能说明

D9

GPIO8

测量周期控制信号输出

D10

GPIO9

测量周期控制信号输入

D15

GPIO14

脉冲信号输入

       测量周期控制信号由驱动程序从GPIO8输出,所以实际应用时,需要将GPIO8GPIO9短接(建议使用0R电阻短接)GPIO14为被测脉冲信号输入,需要注意输入信号电平不能直接3.3V,否则必须通过电平转换后才能接入。

2.  应用程序

       ESM7000脉冲计数功能的设备驱动名为“CNT1:”,ESM7000所有GPIO在系统上电后的缺省状态为GPIO输入上拉,打开“CNT1:”后,GPIO8,GPIO9, GPIO14会自动切换为脉冲计数功能引脚。

       在应用程序中设置测量周期后,驱动程序就开始对输入脉冲连续计数,DeviceIoControl会在每个测量周期自动返回,并运回脉冲计数值。

       完整的应用程序代码如下:

#include "stdafx.h"
#include 
#include "bsp_drivers.h"

BOOL	bThreadStop = FALSE;
DWORD	dwCountingPeriod;
DWORD	max = 0, min = 0xffffffff;

DWORD WINAPI CntThread(PVOID pArg)
{
	BOOL	bRet;
	DWORD	dwTimeout;
	DWORD	dwCount;
	HANDLE	hCnt;
	
	hCnt = (HANDLE)pArg;
	dwTimeout = INFINITE;
	while (!bThreadStop) {
		// 等待获取脉冲计数值
		bRet = DeviceIoControl(hCnt,		// file handle to the driver
			IOCTL_WAIT_FOR_EVENT,			// I/O control code
			NULL,						// in buffer
			0,  							// in buffer size
			&dwCount,					// out buffer
			sizeof(DWORD),					// out buffer size
			NULL,							// pointer to number of bytes returned
			NULL);							// ignored (=NULL)

		if(bRet) {			
			if(dwCount > max){
				max = dwCount;
				if(min != 0xffffffff)
					printf("max:%d min:%d Frequency:%.2fKHz\r\n", 
						max, min, (float)dwCount/(float)dwCountingPeriod);
			}
			if(dwCount < min){
				min = dwCount;
				printf("max:%d min:%d Frequency:%.2fKHz\r\n", 
					max, min, (float)dwCount/(float)dwCountingPeriod);
			}
		}
	}
	
	return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{	
	int		num = 10;

	HANDLE hCnt = CreateFile(L"CNT1:", 0,	0,	NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL);	HANDLE hThread = CreateThread(NULL, 0, CntThread, (LPVOID)hCnt, 0, NULL);
	
	// 配置并启动计数
	dwCountingPeriod = 1000;		// 计数周期,单位毫秒(可设置范围1ms ~ 1000ms)
	DeviceIoControl(hCnt,			// file handle to the driver
			IOCTL_GENERIC_START,	// I/O control code
			&dwCountingPeriod,	// in buffer
			sizeof(DWORD),  		// in buffer size
			NULL,				// out buffer
			0,					// out buffer size
			NULL,				// pointer to number of bytes returned
			NULL);	

	while(num--) {
		Sleep(1000);
	}

	/* 可调用IOCTL_GENERIC_STOP临时停止计数,调用IOCTL_GENERIC_SETUP再次开始计数	*/
	DeviceIoControl(hCnt, IOCTL_GENERIC_STOP, NULL, 0, NULL, 0, NULL, NULL);	

	bThreadStop = TRUE;
	
	CloseHandle(hThread);
	CloseHandle(hCnt);
	return 0;
}

你可能感兴趣的:(嵌入式硬件,arm开发)