做一个数字采样示波器一向是我长久以来的希望,不过究竟这个方针难度比较大,触及的方面真实太多,模仿前端电路、高速ADC、单片机、CPLD/FPGA、通讯、上位机程序、数据处理等等,不是一会儿就能成的,渐渐一步步来呗,呵呵,好歹有个方针,一向在学习各方面的常识,也有动力:)因为高速ADC触及到采样后的数据存储问题,很多的数据涌入使得单片机无法接受,因而一般需求用外部高速RAM加CPLD合作,或许爽性用大容量的 FPGA做数据存储处理等,然后告诉单片机将数据发送出去。这部分真实是难度比较大,电路十分复杂,自己是有心无力啊,还得渐渐地技能堆集。。。
正好ST新推出商场的以CORTEX-M3为中心的STM32,内部集成了2个1Msps 12bit的独立ADC,而且内部高达72MHZ的主频,高达1.25DMIPS/MHZ的处理速度,高速的DMA传输功用,灵敏强壮的4个TIMER等等,这些真是十分有吸引力,何不必它来完结一个低频的数字示波器功用呢,我的方针是暂时只需定量定性地剖析20KHZ以下的低频信号就行了,方针不高吧,用STM32能够便利地完结,等有了必定经历之后渐渐再用FPGA和高速ADC搞个100Msps采样的示波器!
1、 ADC转化:STM32增强型芯片内置的2个独立ADC,能够有16个通道,而且2个通道能够并行的同步采样,触发方法很灵敏,能够经过TIMER以及外部电相等方法触发,并行方法下ADC2主动同步于ADC1;ADC在最高速采样的时分需求1.5+12.5个ADC周期,在14M的ADC时钟下到达 1Msps的速度,因为我主频是72M所以4分频后略微高了点,18MHZ的ADC时钟,采样速度应该高于1M了。ADC 采样2路一起采样方法,用TIM2 CC2来生成时钟信号触发ADC来完结指定频率的采样。ADC1/ADC2采样的结果是一个word
2、采样频率操控:因为STM32内部的4个TIMER十分强壮,每个TIMER又有4个通道,再加上独立的预分配器,实际上能够完结恣意分频,因而用TIM2 CC2来发生指定频率的时钟,用来触发ADC1接连采样。
3、采样数据传输及每次采样深度操控:ADC发生的转化数据经过高速DMA 通道1来传输置指定的内部RAM中,而且将DMA通道一设置成最高优先级,以确保数据精确,而且用DMA每次传输的个数来操控采样的深度,例如我要收集 100个点那么就设置DMA传输100个次,每次从32位ADC转化寄存器传输一个word到RAM中,等完结了100次传输后,DMA通道主动中止(实际上ADC是一向依照要求的采样频率接连在后台采样,仅仅我去取数据罢了),下次收集的时分我只需再设置下采样的个数使能DMA CHANNEL1就行了。
4、与上位机通讯:通讯也是个难题,要到达快速地将很多数据发给上位机的意图,传输的速率必定低不了,开端我想先用串口,不过很快就抛弃了,一则即便我用外部USB转串口的芯片最高也只能到达1M的速度,而且数据会丢掉;后来仍是选用了网络传输的方法,用SPI 接口的ENC28J60芯片,这个芯片我在MEGA32和AT91SAM7S64上都用过,接口简略挺便利的,速度还能够,在SAM7S64上DMA凡是用UDP协议单向发送的速度能够到达400KB/S以上,这次用了STM32发现速度大增,经过我用STM32的DMA传输后,相同UDP协议单向发速度居然到达了500KB/S以上,乃至最高能够到达600KB/S,这个真是意外的收成。
5、上位机程序:仍是用VS2005,我仍是喜爱用C++#,首要是微软的C#做得是在太舒服了,编辑器智能化程度真高,我只需刚刚输个开始的字母,立刻就感知出来一堆让你挑选,连挨个敲字符的功夫都省了,还不必忧虑拼写犯错到时分找原因的费事,呵呵,缺陷便是程序履行时分CPU利用率要高点,什么时分它的C++ 编辑器也到这个程度我就换回C++,哈哈。波形显现仍是用NI的measurementStudio8来完结,一个是美丽便利,别的最要紧的便是 MeasurementStudio8里边有一大堆数据处理的库,从简略的波形有效值核算,频率核算,到各式各样的函数滤波器功用,还有FFT频域剖析,时域剖析等等,凡是要用到的仪器相关处理里边都有,别的原本我计划要在模仿前端里边加一个相位确定的电路,以固定显现的波形起点,后来发现 MeasurementStudio8里边有个PeakDetector的类,用这个来完结波形的确定连这个电路都能够省了。用 MeasurementStudio8来完结真实是十分便利,而且精确。仅仅我没啥材料,还在探究傍边
显现的界面及部分相片:
数据采样后输出到PC上显现的图形很精确,包含MAX038发生的正弦波上部的小尖峰也很清楚,STM32的ADC精度很安稳性适当好,关于音频规模的低频信号来说,1Msps的采样也根本够用了。只需收集满足的点送给measurementsudio供给的函数来剖析,能够到达十分精确的程度,12BIT 的分辨率适当于数字表的3位半的作用,用来测验信号的频率、真有效值、峰值、峰峰值等等十分便利和精确,和我用硬件完结的频率计和真有效值的读数相同(这也阐明晰我做的信号发生器的硬件是精确的,哈哈,之前跟数字表总对不上,看来是数字表精确度差),完结彻底能够当作低频示波器来用,再加上个模仿前端电路,彻底能够有用化了
正弦波:
点击检查图片
上位机的程序:
上位机的程序还处在关于measuremenStudio的探索傍边,仅仅开端了解到了几个函数,用它来完结数据处理真实是便利,look public void DataReceived_Proc() //UDP数据接纳、数据处理、数据显现函数
{
try
{
while (bStates)
{
myudpcomm.Receive(ref CommReceiveBuffer);
Received_Command = Bytes2Struct(ref CommReceiveBuffer);
//textBox3.Text = Received_Command.SampleRate.ToString() + (acEstimate++).ToString();
dADC1_Result = new double[Received_Command.SampleDepth];
dADC2_Result = new double[Received_Command.SampleDepth];
//数据处理,将通讯接纳区中的ADC数据传入绘图用数组中
for (int i = 0; i 《 (int)(Received_Command.SampleDepth); i++)
{
dADC1_Result = (BitConverter.ToUInt16(CommReceiveBuffer, 40 + 4 * (i + 0))) * (3.3 / 4096.0);
dADC2_Result = (BitConverter.ToUInt16(CommReceiveBuffer, 40 + 4 * (i + 0) + 2)) * (3.3 / 4096.0);
}
str = “通道A(绿色)\r\n”;
//测验真有效值
Measurements.ACDCEstimator(dADC1_Result, out acEstimate, out dcEstimate);//沟通(AC方法适当于信号经过一个电容隔直后进行丈量)和直流(DC直通方法进行丈量)真有效值丈量
str += “AC方法有效值:” + ((int)(acEstimate * 1000)).ToString() + “mV” + “DC方法有效值” + ((int)(dcEstimate * 1000)).ToString() + “mV\r\n”;
//测验信号频率、振幅Vp
mySingleToneInformationADC1 = new SingleToneInformation(dADC1_Result, Received_Command.SampleRate);
str += “频率:” + ((int)(acEstimate * 1000)==0 ? 0int )mySingleToneInformationADC1.Frequency).ToString() + “Hz” + “振幅Vp:” + ((int )mySingleToneInformationADC1.Amplitude*1000).ToString() + “mV\r\n”;
str += “\r\n通道B(赤色)\r\n”;
//测验真有效值
Measurements.ACDCEstimator(dADC2_Result, out acEstimate, out dcEstimate);//沟通(AC方法适当于信号经过一个电容隔直后进行丈量)和直流(DC直通方法进行丈量)真有效值丈量
str += “AC方法有效值:” + ((int)(acEstimate * 1000)).ToString() + “mV” + “DC方法有效值” + ((int)(dcEstimate * 1000)).ToString() + “mV\r\n”;
//测验信号频率、振幅Vp
mySingleToneInformationADC2 = new SingleToneInformation(dADC2_Result, Received_Command.SampleRate);
str += “频率:” + ((int)(acEstimate * 1000) == 0 ? 0 : (int)mySingleToneInformationADC1.Frequency).ToString() + “Hz” + “振幅Vp:” + ((int)mySingleToneInformationADC1.Amplitude * 1000).ToString() + “mV\r\n”;
textBox3.Text = str;
//ThresholdPeakDetector.Analyze用来找出从波谷到波峰上升沿极点的数组序号
//能够用于固定显现波形从上升沿的某固定点开端,适当与硬件的同步触发电路功用
//b = ThresholdPeakDetector.Analyze(dADC2_Result, 2, 10);
//foreach (int k in b)
//{
//textBox3.Text += k.ToString() + “ ”;
//}
//for (int i = 0; i 《 Received_Command.SampleDepth – b[1]; i++)
{
//dADC1_Result = dADC2_Result[i + b[1]];
}
//textBox3.Text += b[b.Length – 1].ToString();
//bIsUdpDataReceived = true;//表明接纳到了UDP数据,答应进行再次发送
bIsDataReadyForPlot = true;
myGraphPlotProc();//绘图输出*/
//myD1 = new myMethodDelegate(h);
//myD1(1);
}
}
catch (Exception e1)
{
timer1.Enabled = false;
MessageBox.Show(e1.ToString());
}
finally
{
timer1.Enabled = false;
}
}
/************************************************************************************
* 绘图输出进程函数供,mygGraphPlotThread进程调用
* 一直循环检测bIsDataReadyForPlot,一旦为真则进行绘图,绘图完结后置标志为false
* **********************************************************************************/
public void myGraphPlotProc()//绘图输出函数
{
//while (true )
{
if(bIsDataReadyForPlot)
{
waveformPlot1.PlotY(dADC1_Result);
waveformPlot2.PlotY(dADC2_Result);
bIsDataReadyForPlot = false;
}
}
}
下位机的程序:
下位机的程序,也还在完善,现在只做到了根本的功用,还不安稳,首要问题仍是在传输上的,这次为了一次传输比较多的数据,要将UDP数据包分化,分红多个小于1518字节的帧发送,因而发现当数据发送快的时分很简略导致数据中止发送,曾经用MEGA32和SAM7的时分没留意过,其时的处理速度也慢,没露出出来,想来想去可能是因为接连发送的时分速度太快导致的抵触,ENC28J60犯错挂起了,仍是ENC28J60没有吃透,关于里边的流控、以太网抵触检测这些还需求进一步研讨。
/******************** (C) COPYRIGHT 2007 STMicroelectronics ********************
*STM32F10*** 双通道ADC数据收集并经过ENC28J60完结UDP通讯传输
*作者:alien2006
*环境:keil for arm mdk 3.15b
*版别:V0.2
*时刻:20071202
*阐明:V0.2
*一、网络通讯部分
*1、先选用STM32 SPI轮询方法进行传输实验,ping 192.168.1.100 -l 1400 -n 10
*在轮询方法下未改善SPI1_SendByte()函数(内部直接用ST供给的函数句子)需 avg=9ms时刻
*轮询方法下将SPI1_SendByte()函数中的4条句子修正为直接寄存器存取后avg提高到7ms
*轮询方法下撤销SPI1_SendByte()直接代之以函数中四句子avg提高到6ms
*经过上述的逐渐修正,传输UDP1400个字符时双向传输(接纳1400个字节再发送这1400个字节)距离4MS可达210KB/S
*2、enc28j60.c修正添加STM32 SPI传输DMA和非DMA编译选项,DMA方法下网络最大传输速度测验到达350KB/S
*3、改善了ZYP_UDP.C完结了当要发送的UDP数据长度超越单帧所能包容时,将UDP数据
*主动进行分组,并可在编译时自界说每个分组长度;
*改善了ENC28J60.C加入了ENC28J60DMA闲暇和网络发送结束的判别,处理了当发送速度过快时导
*致传输犯错问题。测验单向发送速度超越500KB/S;
*二、STM32数据收集部分
*1、ADC1/ADC2完结并行一起数据收集,12BIT最高可达1MSPS采样速度并经过STM32的DMA传输放入内存中
*2、TIM2 CC2完结对ADC采样的触发,ADC_Sample_Frequency_Set函数完结自界说TIM2 OC2频率输出,
*3、采样的频率和采样个数经过接纳到的UDP操控指令来指定
*采样的频率为20HZ~1MHZ;
*采样深度为1~4000个数据(受限于STM32内存20KB容量,一个数据为2个12bitADC通道读数,需一个word)
*4、界说了简略的UDP操控指令结构,用于完结与PC通讯和操控采样频率和采样深度
*三、其他
*1、程序待处理问题:UDP分组发送犯错问题未彻底处理,有待进一步处理
*2、等待添加模仿前端电路,并完结扩大倍数程控,经过上位机程序能够设置
*
* V0.1:开始程序,完结简略固定频率和深度的并行ADC采样和UDP通讯,并编制了简略的上位机程序,
*能够进行采样波形的显现