您的位置 首页 技术

根据STM32内置ADC完成简易示波器的程序设计与完成

基于STM32内置ADC实现简易示波器的程序设计与实现-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来实现指定频率的采样。

  做一个数字采样示波器一向是我长久以来的希望,不过究竟这个方针难度比较大,触及的方面真实太多,模仿前端电路、高速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通讯,并编制了简略的上位机程序,

  *能够进行采样波形的显现

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/xinpin/jishu/347728.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部