首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >并行端口输入频率计数- C#

并行端口输入频率计数- C#
EN

Stack Overflow用户
提问于 2012-07-16 14:30:46
回答 3查看 1.5K关注 0票数 0

我必须计算来自555定时器IC的13号引脚上的并行端口的输入频率,实际频率应该在3-4 Hz左右(ON Pulse)。我尝试了几个代码,几次,但每次都给出了不同的值。我已经尝试了以下代码:

代码语言:javascript
复制
    [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来控制并口。

EN

回答 3

Stack Overflow用户

发布于 2012-07-16 14:50:10

请尝试使用以下函数:

代码语言:javascript
复制
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
}

当您需要调用该函数时,只需执行以下操作:

代码语言:javascript
复制
int highCount, lowCount;
double frequenct = GetFreq(1000, out highCount, out lowCount);

在我的代码中,我使用了按位运算符AND来屏蔽不必要的位,这应该比直接与120进行比较要好。记住,当结果是按位计算时,永远不要直接使用==!=运算符进行比较。

我使用了System.Diagnostics.Stopwatch,它的比使用DateTime.Now.Second精确得多。

票数 0
EN

Stack Overflow用户

发布于 2012-07-16 14:50:46

你做的所有事情都有点不对劲。首先,您要计算整整一秒的脉冲,您要计算多达一秒的脉冲(这取决于第二个GetFreq被调用的位置)。

其次,您在计算向上和向下脉冲,尽管我认为频率应该是每秒向上(或向下)脉冲的数量,而不是两个脉冲(这将是频率的两倍)。

最后,如果你想测量3或4赫兹,测量一秒钟会引入舍入误差。试着测量5秒钟。使用Stopwatch来测量这5秒。

票数 0
EN

Stack Overflow用户

发布于 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

代码语言:javascript
复制
[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);
        }
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11499113

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档