你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

我的毕设总结-用STM32的高速AD和USB2.0做简易示波器

[复制链接]
北京小王儿 发布时间:2009-3-25 18:05
今天是3月9号,再过3个月就要大学毕业了,最近工作找得郁闷。干脆躲回实验室,总结下我的毕业设计,算是把自己的大学画个句号吧。
- @8 e& N2 U0 e9 f9 H  Y2 _; O* `/ j
1 概述
' l3 o( W: u4 ?7 E: s$ O5 s毕业设计的题目是“基于STM32的简易示波器设备驱动的研究”,就是利用STM32的AD采集波形数据,然后通过它内置的USB2.0把数据传到PC上面显示出来。框图如下。

  |3 C# ~4 O  x1 g/ E8 ~( o
* f% D( H( t( M题目一共是两个人做,我和我搭档耗子。他做信号处理,采集部分。我做USB在PC下的驱动开发,以及上位机界面的显示。USB固件那部分我们是一起完成的。
* `8 @6 e" w, P3 R5 K+ G5 Y" g  这个课题从08年10月开始,到12月圣诞前夕基本完成。最后基本实现了波形的显示,实测最大可以测量的频率是200KHZ, / h7 P0 Q" ?  v3 K
效果图如下:

$ A; J/ e3 Q4 ?( O3 b6 t9 G
# B+ }3 p' ~. U. m1 n! U5 Y- f  k2 U( U0 t+ J
; z$ N+ o8 ~! A3 U8 t
<font color="#000000">方波的图形好像不是很漂亮会有上升沿老是有尖刺,还需要作软件做处理。没截出来, ( c" i3 n3 c& C9 K

( E/ k* a3 ]. |; T( B  最后能出数据离不开很多前辈的经验。有些地方是借鉴了他们的东西。现在先列出来。 * @5 U. b7 F6 b6 M
第一个是21IC上面alien2006原帖地址。他也是做了一个简易示波器,但是用的是以太网传输。采集部分我很多借鉴了他的方案。
# Q+ z4 m- ?$ x2 ~& L1 c第二个是电脑圈圈,他对USB的理解令我钦佩。我能搞出驱动,他提供的源码包非常重要,有些代码也是直接在他的基础上修改的。 ( R5 _) Q& P- V# f) D4 I
& S* N3 a% p( z
2 整体方案 / I5 L% x' x" b  C
  先说下一次完整的采集,比如外面进来的波形是正弦波,波形电压有正负,STM32单片机的AD只能采集0~3.6V的电压,所以要对信号进行 处理。也就是需要一个模拟前端电路,把电压抬上去。接着就是采集了,STM32的AD可以用外设进行触发,这里用定时器进行触发。每过一个单位时间AD开 启一次,采集一个点,这样采集的频率只要调整这个单位时间也就是定时器就可以控制了。采集了一桢数据,比如200个点。DMA中断被触发,开启USB,把 数据发送到上位机,然后显示出来。
. ]$ v: @' J5 x  整个过程大体就是这样了,还有一个很重要的环节补充下。熟悉示波器的人都知道示波器有个触发概念。像刚才这样显示的话,比如前一帧数据是波 峰开始显示,后一帧是波谷开始。这样显示出来的波形就是乱的,于是为了解决这个问题,就需要做触发,也就是保证每次采集的起始电位相同。我们的采用的是用 外中断的形式,外面波形数据先不采集,先让它通过一个比较器,比如比较器的基准电压是1V,也就是每次都和1V比较,低于1V输出低电平,高于1V输出高 电平。当数据电压大于1V的时候,比较器输出高电平,高电平接到单片机外中断口,这样外中断就被触发。然后开始采集,这样就能保证每帧数据的起始点都相 同。
7 h8 q$ ?9 k% o4 |) T3 t  这个方案是大体方案,后来做了下修改。就是让AD一直在采集。外中断触发了后开启的是DMA,AD一直开着,只是控制DMA什么时候去取。从哪里开始取,取多少个点。下位机部分不再详说,贴下主要的程序,大侠们随便看看,多多指教。 + T+ I/ \7 O$ P) e+ n1 |
定时器设置代码如下:
( }. x+ F- W6 L+ L3 O/*******************************************************************************
) t+ H  k9 J8 q0 y5 K" g, \* Function Name  : TIM_Configuration 3 f0 r/ U/ d; ~- y. f4 g8 L
* Description    : Configure the TIM2. 4 C( h! x0 F- v& u" @
*******************************************************************************/
0 J" ^6 O$ g& m- @+ ^+ nvoid TIM2_Configuration(void) 0 G& `% S' \) F1 s" u4 h2 t3 R
{
/ W' Q" N( r: H. S* p  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure; & q# T! G: j6 C4 e8 r
  TIM_OCInitTypeDef  TIM_OCInitStructure; ! d. `+ d1 R" {7 [
   
2 G" C+ r# I; Z4 |" i  TIM_DeInit(TIM2); //TIM2初始化
) H0 n$ N: u( q& D" S     
$ V5 z/ R4 E0 \: C0 M  /* Time base configuration */
% d. c! Q/ o1 {  TIM_TimeBaseStructure.TIM_Period = 18; //设置了下一个更新事件装入活动的自动重装载寄存器周期的值 & t: C, ?7 j" l) `  d2 d0 R% X) j
  TIM_TimeBaseStructure.TIM_Prescaler = 0; //设置了用来作为TIMx时钟频率除数的预分频值 ; c: I8 `1 W9 i! C  \0 n
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;  //设置了时钟分割
. O' o) l* \% z( A: o  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //选择了计数器模式向上计数 7 s! p5 s  x* p! B2 `

( ?; Q9 x( z, P- W  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);  //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx ! r" u& ?/ d  u7 B# p

0 Z" O) \/ ?" P  Y  /* Prescaler configuration */
7 Z& \( }, |5 _. j: y* v//  TIM_PrescalerConfig(TIM2, 1, TIM_PSCReloadMode_Update); //设置TIMx重载次数 预分频值在更新事件装入
! H/ m% F/ w- B: D. b$ o1 W  
2 T9 R5 M$ y5 f, ^1 z2 n5 b+ N  /* TIM_OCMode_Toggle Mode configuration: Channel2 */ 1 a1 P" }9 n+ H- p% s- Y
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;           
$ U, U) m9 m8 g% c$ J' ]  TIM_OCInitStructure.TIM_Channel = TIM_Channel_2;           
$ Y3 Z# v, C# y6 w& j" N+ m* v  TIM_OCInitStructure.TIM_Pulse = 9;   ; q7 [& w5 ~5 ^5 _
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;  //TIM输出比较极性低 ; Z( _# F! q0 {
     
! m4 v  x3 a7 K: m  TIM_OCInit(TIM2, &TIM_OCInitStructure);
, G. x' Y" F9 K2 g8 d7 g; @, Z. U   
5 ?' V3 y1 b8 `3 W7 c1 H  TIM_ARRPreloadConfig(TIM2, ENABLE); //使能或者失能TIMx在ARR上的自动装载寄存器 : D, x, K  `" S- G$ G$ \$ G0 N% n: g
   0 B: \  C- R- O( l- F/ I
  /* TIM2 enable counter */ 4 i5 r  E. j2 R
  TIM_Cmd(TIM2, ENABLE); //使能TIMx外设 , I( H; b) {7 k3 {  G
}
' D4 i) g6 q3 Z: V9 g/ x; I  @AD以及DMA设置代码: 3 ~1 d2 g, O6 h7 l6 q2 V/ u% A
/******************************************************************************* 6 Q5 U, |$ X' l
* Function Name  : ADC_Configuration 2 R: b. l; T- j- T( `" D! s
* Description    : Configure the ADC1. , A7 t& Z8 t2 a; V1 _# J' ^, W
*******************************************************************************/ " S3 k! D* `7 h( q! E) }5 [5 ?6 a
void ADC_Configuration(void)
5 |1 |; @5 h- v' W! t- |. j{
$ j' q, f( w( i6 v6 @3 r  /* DMA channel1 configuration ----------------------------------------------*/ 4 t' @, ^$ E6 t8 |* ~1 c
  DMA_DeInit(DMA_Channel1); //复位DMA_Channel1 ( n+ {0 g7 _; W: V; W: }, [
  DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; //外围设备地址
: F5 ~2 t* Z1 j8 V" V  Q6 z/ h  DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_Data[0]; //memory 地址
: }4 J" O# e9 D+ {- p  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //外围设备做为源 8 q5 P' y: r( c' x$ l
  DMA_InitStructure.DMA_BufferSize = 1024;  //数据单元尺寸
/ `6 o0 t! r9 Y0 G( n, k  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  //外围地址是否自动增长 disable不增长
) N0 k* W$ O7 _, H& v7 L0 }2 O% T  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //memory 是否自动增长
: ~6 C. Z7 u% g4 @5 K( ]  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //外围设备寄存器尺寸16位
; q4 S/ t9 O  O2 V; ^" B; O  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;  //memory尺寸16位
- C) a3 |5 m! R& }  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;  //DMA 循环模式
5 z( J- {' F  \6 q" Z  DMA_InitStructure.DMA_Priority = DMA_Priority_High;  //DMA 通道优先级 5 Q& h! q/ f" u0 }
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //memory- to-memory转换 2 ^/ U$ `5 P5 a  H) U+ e- }
  DMA_Init(DMA_Channel1, &DMA_InitStructure);  //初始化DMA通道1 $ M3 P+ E" j' o$ T% Y

. c8 O) P3 G/ Z- b# K) g+ k" ?  /* DMA IT enable */ 9 b* v5 X  P. N. g  _
  DMA_ITConfig(DMA_Channel1, DMA_IT_TC, ENABLE); //使能DMA传输完成中断 0 y! Z/ W+ g& Z+ Q2 B
  * [; _" k- P* c, r! `
  /* ADC1 configuration ------------------------------------------------------*/                                                      
0 C9 [7 ]. ?' o) R% E8 f  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;  //ADC 工作模式 ADC1 ADC2 单独工作     
+ w& e9 W$ T) k4 j: s  ADC_InitStructure.ADC_ScanConvMode = DISABLE;  //多通道扫描模式 $ A! V- T" ?2 [9 K. T
  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //是否启用连续转换模式 0 D: C! g& x4 n  n# U- V6 ?, W
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2;  //触发方式 , A  ]" b' r8 p3 C7 Z& ]
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;   //数据右对齐 5 [/ Q( U1 a5 q9 U
  ADC_InitStructure.ADC_NbrOfChannel = 1;  //ADC规则转换通道数量
# C$ p; x; {! ~1 A- f3 R9 A  ADC_Init(ADC1, &ADC_InitStructure); ( @! Z: k& v' F2 H- _4 ]! Z, f9 l
( [3 F3 E! E* {; S! ~
  /* ADC1 regular channel10 configuration */ //配置转换规则 6 u  W6 l; ?% ]: F8 |) ], W
  ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_1Cycles5);
& r# r. L0 D" _! y, u+ H; ?! x   
2 t- K4 M* \6 g9 O8 ?  /* Enable ADC1 DMA */
+ z7 H& s, H: I  ADC_DMACmd(ADC1, ENABLE);
0 p- h6 X! }9 l. T# y* E) I) E1 W" A& ^. A. ?2 U4 ^" y
  /* Enable ADC1 */
6 T9 T: `2 k0 Z4 J& ?7 N  ADC_Cmd(ADC1, ENABLE);
8 c9 b  \  ~" o0 i2 K% X
( n/ T0 B. G3 K7 p2 x  /* Enable ADC1 reset calibaration register */ 9 `" d+ x1 k. @$ i2 Y' U
  ADC_ResetCalibration(ADC1);  //复位ADC1 校准 ; p. J. Q( V4 X) |- W) J
  /* Check the end of ADC1 reset calibration register */
- g4 i7 K: r5 w: f/ \6 H* w% h  L  while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位完成
! n) n5 X; C6 _& n) `( ^7 k. n6 I7 z
  /* Start ADC1 calibaration */   |/ I4 \9 I) [( X6 q: w
  ADC_StartCalibration(ADC1);  //开始ADC1 校准转换 & i  b' R* U) \) v( y; p% x
  /* Check the end of ADC1 calibration */   G% l- Z! q7 D, X
  while(ADC_GetCalibrationStatus(ADC1));  //等待转换完成
$ F2 o: W' v6 ?: G* k   . U  t) j& r, U+ J6 k) l
  ADC_ExternalTrigConvCmd( ADC1, ENABLE); //使能或者失能ADCx的经外部触发启动转换功能
, p( g8 B6 |! r1 {}
- b7 P1 w9 X. S5 Y4 E
1 z, m8 W0 K  k5 V1 kDMA中断服务程序:
  _+ H) ~$ c4 f6 M+ s/******************************************************************************* ( \+ y8 q8 }9 v* r/ U3 x  _7 X
* Function Name  : DMAChannel1_IRQHandler
; u5 l% a8 X+ j% k' c- Q* M% F* Description    : This function handles DMA Stream 1 interrupt request.
3 m3 ?& A# [/ [# `2 u' ^*******************************************************************************/   e7 u) M4 S# `6 A2 J
void DMAChannel1_IRQHandler(void)
7 Q4 y7 |( v7 e9 W+ E# h: [{ " f+ r' `5 ^1 o' I  H- f# x) A% g" d
  DMA_Cmd(DMA_Channel1, DISABLE);  //关闭DMA通道1 - n9 ^8 s# J' ^+ Q, i! _0 B
  for(count=64;count
1.jpg
收藏 1 评论38 发布时间:2009-3-25 18:05

举报

38个回答
xujiantj 回答时间:2019-1-23 13:39:11
不错,谢谢分享
dongxu1234 回答时间:2018-1-31 19:19:36
good the code ?
qinshi1208-3586 回答时间:2009-3-26 09:39:26

RE:我的毕设总结-用STM32的高速AD和USB2.0做简易示波器

不错,不错
sfq2008-104893 回答时间:2009-3-26 10:04:21

RE:我的毕设总结-用STM32的高速AD和USB2.0做简易示波器

不错,不错.不过STM32本身的AD慢了点,建议用外置的AD,如:ADS830
: G; ~7 o9 ~2 S8 d( Q! T呵呵,双踪的呵呵......
sfq2008-104893 回答时间:2009-3-26 10:06:11

RE:我的毕设总结-用STM32的高速AD和USB2.0做简易示波器

还有,我觉得这个做得不错,楼主可以参考一下+ a  i% o4 \/ q4 ?* J/ F
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=2228838&amp;bbs_page_no=1&amp;bbs_id=3043
dacong 回答时间:2009-3-26 12:40:56

回复:我的毕设总结-用STM32的高速AD和USB2.0做简易示波器

学习了!
hzrobin 回答时间:2009-3-26 13:56:24

RE:我的毕设总结-用STM32的高速AD和USB2.0做简易示波器

楼主大人,你怎么转帖人家的文章,把作者的信息给删了呢
dujun168 回答时间:2009-3-26 23:14:21

回复:我的毕设总结-用STM32的高速AD和USB2.0做简易示波器

不错,在校生能有这样的水平很难得!
HansLiu888 回答时间:2009-3-31 16:27:42

RE:我的毕设总结-用STM32的高速AD和USB2.0做简易示波器

very good!
yzl624358 回答时间:2009-4-3 13:34:22

回复:我的毕设总结-用STM32的高速AD和USB2.0做简易示波器

楼主真强,学习下!!!!!!!!!!!!!!!
lucky-92214 回答时间:2009-4-13 19:06:16

RE:我的毕设总结-用STM32的高速AD和USB2.0做简易示波器

very good!
山水-95029 回答时间:2009-4-25 16:08:31

RE:我的毕设总结-用STM32的高速AD和USB2.0做简易示波器

很好
$ Z  x5 A9 |; ~1 L* w不错
Janechao 回答时间:2009-7-1 09:38:19

回复:我的毕设总结-用STM32的高速AD和USB2.0做简易示波器

不错不错,好好参考一下。我是初学STM32呢
avr386 回答时间:2009-8-29 06:25:37

RE:我的毕设总结-用STM32的高速AD和USB2.0做简易示波器

XXXXXXXXXX
ken48172 回答时间:2009-9-30 14:51:41

RE:我的毕设总结-用STM32的高速AD和USB2.0做简易示波器

supercxy 回答时间:2009-10-16 17:16:55

回复:我的毕设总结-用STM32的高速AD和USB2.0做简易示波器


1 @3 |9 A7 k8 r, w* \0 L9 d强烈支持阿5 p  {5 a3 c( }) k* l/ S
最近adc正看不懂呢
123下一页

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版