我必须计算来自555定时器IC的13号引脚上的并行端口的输入频率,实际频率应该在3-4 Hz左右(ON Pulse)。我尝试了几个代码,几次,但每次都给出了不同的值。我已经尝试了以下代码:
[DllImport("inpout32.dll", EntryPoint = "Inp32")]
public static extern int Input(int adress);
private void button1_Click(object sender, EventArgs e)
{
int currentState = Input(889);
int LastState;
while (true)
{
int State = Input(889);
if (State != currentState)
{
if (Input(889) == 120)
{
LastState = 0;
}
else
{
LastState = 1;
}
break;
}
}
GetFreq(LastState);
}
void GetFreq(int LastPulse)
{
int highPulseFreq = 0;
int lowPulseFreq = 0;
if (LastPulse == 1)
{
highPulseFreq++;
}
if (LastPulse == 0)
{
lowPulseFreq++;
}
int startTime = DateTime.Now.Second;
while (true)
{
if (startTime == DateTime.Now.Second)
{
if (Input(889) != 120)// ON
{
if (LastPulse == 0)
{
highPulseFreq++;
LastPulse = 1;
}
}
else
{
if (LastPulse == 1)
{
lowPulseFreq++;
LastPulse = 0;
}
}
}
else
{
MessageBox.Show("ON Pulses: " + highPulseFreq.ToString() + Environment.NewLine + "OFF Pulses: " + lowPulseFreq.ToString());
break;
}
}
}输出:



我该怎么做,才能得到准确的频率?我的代码中有什么地方出了问题吗?我正在使用inpout32.dll来控制并口。
发布于 2012-07-16 14:50:10
请尝试使用以下函数:
double GetFreq(long time, out int highCount, out int lowCount)
{
const int ADDRESS = 0x378 + 1, MASK = 0x10;
highCount = lowCount = 0;
bool LastState = (Input(ADDRESS) & MASK) == MASK;
if (LastState)
{
highCount++;
}
else
{
lowCount++;
}
System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
stopwatch.Start();
while (stopwatch.ElapsedMilliseconds <= time)
{
if ((Input(ADDRESS) & MASK) == MASK) // High
{
if (!LastState)
{
highCount++;
LastState = true;
}
}
else
{
if (!LastState)
{
lowCount++;
LastState = false;
}
}
}
stopwatch.Stop();
return ((double)(highCount + lowCount)) / time * 500
}当您需要调用该函数时,只需执行以下操作:
int highCount, lowCount;
double frequenct = GetFreq(1000, out highCount, out lowCount);在我的代码中,我使用了按位运算符AND来屏蔽不必要的位,这应该比直接与120进行比较要好。记住,当结果是按位计算时,永远不要直接使用==或!=运算符进行比较。
我使用了System.Diagnostics.Stopwatch,它的比使用DateTime.Now.Second的精确得多。
发布于 2012-07-16 14:50:46
你做的所有事情都有点不对劲。首先,您要计算整整一秒的脉冲,您要计算多达一秒的脉冲(这取决于第二个GetFreq被调用的位置)。
其次,您在计算向上和向下脉冲,尽管我认为频率应该是每秒向上(或向下)脉冲的数量,而不是两个脉冲(这将是频率的两倍)。
最后,如果你想测量3或4赫兹,测量一秒钟会引入舍入误差。试着测量5秒钟。使用Stopwatch来测量这5秒。
发布于 2012-07-18 06:35:49
您需要以至少是信号中最高频率的两倍的速率对信号进行采样。如果您期望的最高频率约为4 4Hz,那么在15 -20 4Hz范围内对信号进行采样应该会得到很好的结果。
幸运的是,在Windows上,以这种速率进行采样是可以做到的,而不需要在Windows上使用高精度的定时器(如果您对精度要求不是很高)。20 so采样率对应于50ms的采样周期,因此您可以使用在记录采样值之间休眠约50ms的循环。你不会在样本之间得到非常精确的增量-T(你可能会看到每个样本之间的时间变化高达15-30ms,这取决于你的系统),但对于你正在处理的频率来说,它应该足够好了。
您可以记录几秒钟的样本(以及相关的时间戳),然后将数据导出到电子表格。一旦进入电子表格,您就可以进行一些分析和绘图。或者,您可以找到一些时间序列分析代码来分析样本列表,例如使用傅立叶变换(FFT)将信号从时域转换到频域。
以下是创建示例的示例。如果您确实需要更精确的时间戳,可以在GetInputSamples中用StopWatch替换DateTime.Now。
[DllImport("inpout32.dll", EntryPoint = "Inp32")]
public static extern int Input(int adress);
struct Sample
{
public int Value;
public int Milliseconds;
};
private void button1_Click(object sender, EventArgs e)
{
TimeSpan duration = TimeSpan.FromSeconds(5);
TimeSpan samplePeriod = TimeSpan.FromMilliseconds(50);
var samples = GetInputSamples(889, duration, samplePeriod);
SaveSamplesCSV(samples, "test.csv");
}
private static List<Sample> GetInputSamples(int inputPort, TimeSpan duration, TimeSpan samplePeriod)
{
List<Sample> samples = new List<Sample>();
var oldPriority = Thread.CurrentThread.Priority;
try
{
Thread.CurrentThread.Priority = ThreadPriority.Highest;
DateTime start = DateTime.Now;
while (DateTime.Now - start < duration)
{
int value = Input(inputPort);
TimeSpan timestamp = DateTime.Now - start;
samples.Add(new Sample() { Value = value, Milliseconds = (int)timestamp.TotalMilliseconds });
Thread.Sleep(samplePeriod);
}
}
finally
{
Thread.CurrentThread.Priority = oldPriority;
}
return samples;
}
private static void SaveSamplesCSV(List<Sample> samples, string fileName)
{
using (StreamWriter writer = File.CreateText(fileName))
{
writer.WriteLine("Sample, Time (ms)");
foreach (var sample in samples)
{
writer.WriteLine("{0}, {1}", sample.Value, sample.Milliseconds);
}
}
}https://stackoverflow.com/questions/11499113
复制相似问题