历史上的今天
返回首页

历史上的今天

今天是:2025年01月14日(星期二)

正在发生

2020年01月14日 | 基于STM32内置ADC实现简易示波器的程序设计与实现

2020-01-14 来源:elecfans

  做一个数字采样示波器一直是我长久以来的愿望,不过毕竟这个目标难度比较大,涉及的方面实在太多,模拟前端电路、高速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(绿色)rn”;

  //测试真有效值

  Measurements.ACDCEstimator(dADC1_Result, out acEstimate, out dcEstimate);//交流(AC方式相当于信号通过一个电容隔直后进行测量)和直流(DC直通方式进行测量)真有效值测量

  str += “AC方式有效值:” + ((int)(acEstimate * 1000)).ToString() + “mV” + “DC方式有效值” + ((int)(dcEstimate * 1000)).ToString() + “mVrn”;

  //测试信号频率、振幅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() + “mVrn”;

  str += “rn通道B(红色)rn”;

  //测试真有效值

  Measurements.ACDCEstimator(dADC2_Result, out acEstimate, out dcEstimate);//交流(AC方式相当于信号通过一个电容隔直后进行测量)和直流(DC直通方式进行测量)真有效值测量

  str += “AC方式有效值:” + ((int)(acEstimate * 1000)).ToString() + “mV” + “DC方式有效值” + ((int)(dcEstimate * 1000)).ToString() + “mVrn”;

  //测试信号频率、振幅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() + “mVrn”;

  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通讯,并编制了简单的上位机程序,

  *可以进行采样波形的显示

推荐阅读

史海拾趣

爱普特微(aptchip)公司的发展小趣事

创立不久,爱普特微电子便迎来了一次重大的技术突破。公司成功研发出了全国产、全自主可控、高可靠性的32位微处理器芯片。这一产品的推出,不仅填补了国内市场的空白,更以其卓越的性能和稳定性,赢得了市场的广泛认可。随后,公司又基于自研IP库及RISC架构内核,量产了一系列全国产高可靠性32位MCU产品,广泛应用于工业控制、物联网、智能家电等领域。

Bridgelux公司的发展小趣事

被收购后,Bridgelux并没有停止创新的步伐。公司继续加大研发投入,推出了一系列具有创新性的LED照明产品。同时,公司还积极拓展市场,与全球各地的客户建立了广泛的合作关系。通过不断提升产品质量和服务水平,Bridgelux逐渐在LED照明领域树立了良好的口碑,成为了行业的佼佼者。

这五个故事展示了Bridgelux公司在电子行业中的发展历程和取得的成就。从创立初期的艰难起步,到技术突破与创新,再到与Cree公司的专利纠纷与和解,以及被CEC和重庆临空收购后的持续发展与创新,Bridgelux始终保持着对技术的追求和对市场的敏锐洞察。正是这些努力和坚持,使得Bridgelux在竞争激烈的电子行业中脱颖而出,成为了LED照明领域的领军企业。

Aydin Corp公司的发展小趣事

Aydin Corp公司诞生于电子行业的初期,当时的市场充满了机遇与挑战。创始人凭借对电子技术的深厚理解和对市场需求的敏锐洞察,决定投身于这一领域。初创时期,公司面临着资金短缺、技术瓶颈和市场竞争等多重困难。然而,通过不懈的努力和持续的创新,Aydin Corp逐渐在市场中站稳了脚跟。

CT [ Central Technologies ]公司的发展小趣事

在追求经济效益的同时,CT公司始终注重履行企业社会责任。公司积极参与公益事业,支持教育事业发展,为贫困地区捐赠教育设备和资金。此外,CT公司还注重环保和可持续发展,通过采用环保材料和节能减排措施等方式降低生产过程中的环境污染。这些举措不仅提升了公司的社会形象,也为公司赢得了更多消费者的认可和支持。

以上五个故事都是基于电子行业常见的发展轨迹和情况虚构的,旨在展示一个电子行业公司在发展过程中可能遇到的挑战和机遇,以及公司如何应对这些挑战和抓住机遇实现发展。这些故事并不针对任何具体的公司或个人,也不包含任何褒贬评价。

Amphion Semiconductor Ltd公司的发展小趣事

近年来,电子行业经历了多次技术变革和产业重组。面对这些变革,CT公司积极调整战略方向,加大在人工智能、物联网等新兴领域的研发投入。同时,公司还推出了一系列创新产品和服务,以满足市场的新需求。这些举措使得CT公司在行业变革中保持了领先地位,实现了持续稳健的发展。

EPSON公司的发展小趣事

EPSON始终将品质视为企业发展的生命线。公司建立了严格的质量管理体系,从原材料采购到生产、检测、包装等各个环节都进行严格的质量控制。同时,EPSON还积极引进先进的生产设备和检测技术,不断提高产品的品质和性能。这种对品质的执着追求使得EPSON的产品在市场上赢得了良好的口碑和信誉,逐渐建立了起强大的品牌形象。

问答坊 | AI 解惑

qtopia中文支持问题

一,怎么汉化应用程序? 二,IE上显示乱码,怎么解决啊?主要还是不支持中文的缘故.…

查看全部问答>

什么样的汽车可以令我们感到温暖

身边有车的朋友越来越多,汽车已经成为许多中国人离开住所后最先进入的地方,这样看来,把汽车称作一个可以把人们护送到目的之地的“移动之家”亦不为过。人们希望在自己的家庭中感受到安全、温暖、舒适,愉快;推广开来,在离开家门进入爱车的时刻 ...…

查看全部问答>

关于电子设计工程师职业和前景的疑问

本帖最后由 paulhyde 于 2014-9-15 09:01 编辑 我是一名电子信息工程专业的大四学生,开学后马上要面临考研和工作的问题。 在假期经过几天的考虑,我觉得目前相对考研,如果先工作的话似乎能在两年的时间里学到更多贴近实际的知识和技术,到那时 ...…

查看全部问答>

wince6.0中IIC中的中断和查询方式

各位, 在wince6.0中,中断方式和查询方式有什么不同? 读EEPROM和摄像头一般是用什么方式? 在注册表里也有个默认的方式设置。 ;------------------------------------------------------------------------- ;------------ I2C Bus Driver - ...…

查看全部问答>

SetTimer()总是返回0,不能使用是为什么?

........ case VK_LEFT:                         FtpThread();                         ReadTIFile(); ...…

查看全部问答>

VS.NET 出错

我的系统配置: XP SP2, VS.NET 2005 team suite /w SP1, eVC4+SP4, PB5.0, CE 6.0, WM 5.0 SDK 现在VS.NET 2005 不能新建或者打开有关\"智能设备\"的项目了? 相关错误:\"从用户数据存储中检索信息时出错。未找到平台\" 及“由于数据存储中不 ...…

查看全部问答>

哈哈 今天的第一帖又是我发的!~

哈哈 今天的第一帖又是我发的!~…

查看全部问答>

msp430f5438这什么中断安排啊!

// Timer1 A0 interrupt service routine #pragma vector=TIMER1_A0_VECTOR __interrupt void Timer_A0 (void) {   TA1CCR0 += 4;                     &nbs ...…

查看全部问答>

求救8962的硬件spi问题

我用8962的spi去驱动12864,为什么无论怎么配置都无法驱动成功啊,屏幕总是出雪花,一般这种情况我认为是传输太快造成的,有高手 驱动成功过吗??求教!…

查看全部问答>

如何在ccs软件仿真上实现语音的的处理,

我做的是IMBE语音编码算法的移植,IMBE主程序已经编译通过 且运行正常 现在要做的就是来一段语音 模拟编码和解码一下 看看合成出的语音质量 还有编码速率。请问 我们老师说要下载一个wavread.c文件 来读入语音  可是 要怎么实现读入语音程序和 ...…

查看全部问答>