-
做一个数字采样示波器一直是我长
久以来的愿望,不过毕竟这个目标难度比较大,涉及的方面实在
太多,模拟前端电路、高
速
ADC
、单片机、
CPLD/FPG
A
、通讯、上位机程序、数据处理等等,不是一下
子就能成的,
慢慢一步步来呗,呵呵,好歹有个目标,一直在学习各方面的知识,也有动力:)
由于高速
ADC
涉及到采样后的数据存储问题,
大量的数据涌入使得单片机无法承受,
因此通常需要用外
部高速
RAM
加
CPLD
配合,或者干脆用大容量的
FPGA
做数据存储处理等,然后通知单片机将数据发送
出去。这部分实在是难度比较大,电路非常复杂,自己是有心无力啊,还得慢慢地技术积累。。。
正好
ST
p>
新推出市场的以
CORTEX-M3
为核心
的
STM32
,内部集成了
2
个
1Msps 12bit
的独立
ADC
,
并且内部高达
72
MHZ
的主频,高达
1.25DMIPS/MHZ
的处理速度,高速的
DMA
传输功能,灵活强大的<
/p>
4
个
TIMER
等等,
这些真是非常有吸引力,
何不用它来实现一个低频的数字
示波器功能呢,
我的目标是暂时
只要定量定性地分析
20KHZ
以下的低频信号就行了,目标不高吧,用
STM32
可以方便地实现,等有了一
定经验之后慢慢再用<
/p>
FPGA
和高速
ADC
< br>搞个
100Msps
采样的示波器!
1
、
ADC
< br>转换:
STM32
增强型芯片内置的
2
个独立
ADC
,可以有
16
个通道,并且
2
个
通道可以并行的同
步采样,
触发方式很灵活,
< br>可以通过
TIMER
以及外部电平等方式触发,
并行方式下
ADC2
自动同步于
ADC1
;
ADC
在最高速采
样的时候需要
1.5+12.5
个
AD
C
周期,在
14M
的
< br>ADC
时钟下达到
1Msps
的
速度,因为
我主频是
72M
所以
4
分频后稍微高了点,
18MHZ
的
ADC
时钟,采样速度应该高于
1M
了。
ADC
采样
2
路同时采样方式,
用
TIM2 CC2
来生成时钟信号触发
ADC
来实现指定频率的采样。
ADC1/ADC2
采样的结
果是一个
word
2
、
采样频率控制:
由于
ST
M32
内部的
4
个
TIMER
非常强大,每个
TIMER
又有
4
个通道,再加上独立的
预分
配器,实际上可以实现任意分频,因此用
TIM2 CC2
来产
生指定频率的时钟,用来触发
ADC1
连续采
< br>样。
3
、采样数据传输及每
次采样深度控制:
ADC
产生的转换数据通过高速
DMA
通道
1
来传输置指
定的内部
RAM
中,并且将
DMA
p>
通道一设置成最高优先级,以保证数据准确,并且用
DMA
每次传输的个数来控制
采样的深度,例如我要采集
100
个点那么就设置
DMA
传输<
/p>
100
个次,每次从
32
位
ADC
转换寄存器传输
一个
word
到
RAM
中,
等完成了
100
次传输后,<
/p>
DMA
通道自动停止
(实际上
ADC
是一直按照要求的采样
频率连续在后台采样
,只是我去取数据而已),下次采集的时候我只要再设置下采样的个数使能
DMA
CHANNEL1
就行了。
4
、
与上位机通讯:
通讯也是个难题,
要达到快速地将大量数据发给上位机的目的,
传输的速率肯定低不了,
开始我想先用串口,
不过很快就放弃了
,
一则即使我用外部
USB
转串口的芯
片最高也只能达到
1M
的速度,
并且数
据会丢失;
后来还是采用了网络传输的方式,用
SPI
< br>接口的
ENC28J60
芯片,这个芯片我在
MEGA32
和
AT91SAM7S64
上都用过,接口简单挺方便的,速度还可以,在
SAM7S64
上
DMA
凡是用
UDP
协议单向发送的速度可以达到
400KB/S
< br>以上,这次用了
STM32
发现速度大增,经过我用
p>
STM32
的
DMA
传输后,同样
UDP
协议单向发速度竟然达到了
500KB/S
以上,甚至最高可以达到
600KB
/S
,这个
真是意外的收获。
p>
5
、上位机程序:还是用
VS2005
p>
,我还是喜欢用
C#
,主要是微软的
C#
做得是在太舒服了,编辑器智能化
程度真
高,缺点就是程序执行时候
CPU
利用率要高点,。波形显示还
是用
NI
的
measurementS
tudio8
来
实现,一个是漂亮方便,另外最要紧的就是
p>
MeasurementStudio8
里面有一大堆数据处理的库
,从简单的
波形有效值计算,频率计算,到各种各样的函数滤波器功能,还有
FFT
频域分析,时域分析等等,但凡要
用到的仪
器相关处理里面都有,另外本来我打算要在模拟前端里面加一个相位锁定的电路,以固定显示的
< br>波形起点,
后来发现
MeasurementStudi
o8
里面有个
PeakDetector
的类,
用这个来实现波形的锁定连这个
电路都可以省了。用<
/p>
MeasurementStudio8
来实现实在是非常方便,
并且准确。只是我没啥资料,还在探
索当中
ENC28J60
网络子卡以及自己
DIY
的信号发生器照片,下面的绿
板子是
STM32
的评估板
数据采样后输出到
PC
上显示的图形很精确,包括
MAX038<
/p>
产生的正弦波上部的小尖峰也很清楚,
STM32
的
ADC
精度很稳定性相当好,对于音频范围的低频信
号来说,
1Msps
的采样也基本够用了。只要
采集足够的点送给
measurementsudio
提供的函数来分析,可以达到非常精确的程度,
12BIT
的分
辨率相
当于数字表的
3
位半的效果,用
来测试信号的频率、真有效值、峰值、峰峰值等等非常方便和精确,和我
用硬件实现的频
率计和真有效值的读数相同(这也说明了我做的信号发生器的硬件是准确的,哈哈,之前
跟数字表总对不上,看来是数字表准确度差),实现完全可以当作低频示波器来用,再加上个模拟前端电
路,完全可以实用化了
上位机的程序还处在对于
measu
remenStudio
的摸索当中,只是初步了解到了几个函数,用它来实现数据
p>
处理实在是方便,
look
public void DataReceived_Proc()
//UDP
数据接收、数据处理、数据显示函数
{
try
{
while (bStates)
{
e(ref
CommReceiveBuffer);
Received_Command = Bytes2Struct(ref
CommReceiveBuffer);
// = Received_ng() +
(acEstimate++).ToString();
dADC1_Result = new double[Received_Depth];
dADC2_Result = new
double[Received_Depth];
//
数据处理,将通讯接收区中的
ADC
数据传入绘图用数组中
for (int i = 0; i < (int)(Received_Depth); i++)
{
dADC1_Result[i] = (16(CommReceiveBuffer, 40 + 4 *
(i + 0))) * (3.3 /
4096.0);
dADC2_Result[i]
= (16(CommReceiveBuffer, 40 + 4 * (i + 0) + 2)) *
(3.3 / 4096.0);
}
str
=
通道
A(
绿色
)rn
//
测试真有效值
timator(dADC1_Result, out acEstimate, out dcEstima
te);//
交流
(AC
方式相当于信
号通过一个电容隔直后进行测量
)
和直流
(DC
直通方式进行测量
)
真有效值
测量
str
+=
方式有效值:
方式有效值
//
测试信号频率、振幅
Vp
mySingleToneInformationADC1 = new
SingleToneInformation(dADC1_Result,
Received_Rate);
str +=
频率:
0:(int
)ncy).ToString() +
振幅
Vp
:
((int
)ude*1000).ToString() +
str +=
通道
B(
红色
)rn
//
测试真有效值
timator(dADC2_Result, out acEstimate, out dcEstima
te);//
交流
(AC
方式相当于信
号通过一个电容隔直后进行测量
)
和直流
(DC
直通方式进行测量
)
真有效值
测量
str
+=
方式有效值:
方式有效值
//
测试信号频率、振幅
Vp
mySingleToneInformationADC2 = new
SingleToneInformation(dADC2_Result,
Received_Rate);
str +=
频率:
(int)nc
y).ToString() +
振幅
Vp
< br>:
((int)ude *
1000).ToString() +
= str;
//e
用来找出从波谷到波峰上升沿顶点的数组序号
//
可以用于固定
显示波形从上升沿的某固定点开始,相当与硬件的同步触发电路功能
//b =
e(dADC2_Result, 2, 10);
//foreach (int k in b)
//{
// += ng()
+
//}
//for (int i = 0; i < Received_Depth - b[1]; i++)
{
//dADC1_Result[i] = dADC2_Result[i + b[1]];
}
// += b[ - 1].ToString();
//bIsUdpDataReceived = true; //
表示接收到了<
/p>
UDP
数据,允许进行再次发送
bIsDataReadyForPlot
= true;
myGraphPlotProc();
//
绘图输出
*/
//myD1 = new myMethodDelegate(h);
//myD1(1);
}
}
catch (Exception e1)
{
d = false;
(ng());
}
-
-
-
-
-
-
-
-
-
上一篇:新视角英语第二册翻译
下一篇:各厂磁芯材质对照表