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

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

[复制链接]
北京小王儿 发布时间:2009-3-25 18:05
今天是3月9号,再过3个月就要大学毕业了,最近工作找得郁闷。干脆躲回实验室,总结下我的毕业设计,算是把自己的大学画个句号吧。 * x/ j5 |: T" k4 a7 q
% L( u: ?4 G: j. m- p4 k) T; |
1 概述 3 o; X* U' n9 F7 ~8 o. f6 X
毕业设计的题目是“基于STM32的简易示波器设备驱动的研究”,就是利用STM32的AD采集波形数据,然后通过它内置的USB2.0把数据传到PC上面显示出来。框图如下。

5 g$ W4 o9 ?( l1 T
, y' Y3 r5 b; u# q. g题目一共是两个人做,我和我搭档耗子。他做信号处理,采集部分。我做USB在PC下的驱动开发,以及上位机界面的显示。USB固件那部分我们是一起完成的。
; ]$ }$ C' r7 }0 n* m% ^  这个课题从08年10月开始,到12月圣诞前夕基本完成。最后基本实现了波形的显示,实测最大可以测量的频率是200KHZ,
( d  e* T& _- @8 W+ {6 f. d' Y效果图如下:

- w# W* q5 G0 V( t. }$ d6 I. @6 [7 w2 H+ l7 \! k+ I

5 f) [8 Q, G/ p8 |& m" I9 P1 E, c; l
<font color="#000000">方波的图形好像不是很漂亮会有上升沿老是有尖刺,还需要作软件做处理。没截出来,
( ?- b0 X" R8 R& d; w3 V
' Z, o7 F- F+ R* S1 o# {/ K  最后能出数据离不开很多前辈的经验。有些地方是借鉴了他们的东西。现在先列出来。 ( i6 _% ?  P) l4 b8 F8 S
第一个是21IC上面alien2006原帖地址。他也是做了一个简易示波器,但是用的是以太网传输。采集部分我很多借鉴了他的方案。 8 w& H  Z# s3 `) C% h- A) C  c/ B
第二个是电脑圈圈,他对USB的理解令我钦佩。我能搞出驱动,他提供的源码包非常重要,有些代码也是直接在他的基础上修改的。
- V! s& B+ v: `# h" J7 B4 j
0 L/ `# t3 F0 ^2 整体方案
$ O( x/ I+ @4 S: X# s& `  先说下一次完整的采集,比如外面进来的波形是正弦波,波形电压有正负,STM32单片机的AD只能采集0~3.6V的电压,所以要对信号进行 处理。也就是需要一个模拟前端电路,把电压抬上去。接着就是采集了,STM32的AD可以用外设进行触发,这里用定时器进行触发。每过一个单位时间AD开 启一次,采集一个点,这样采集的频率只要调整这个单位时间也就是定时器就可以控制了。采集了一桢数据,比如200个点。DMA中断被触发,开启USB,把 数据发送到上位机,然后显示出来。 $ V$ W1 \: k( u) w+ ^) z
  整个过程大体就是这样了,还有一个很重要的环节补充下。熟悉示波器的人都知道示波器有个触发概念。像刚才这样显示的话,比如前一帧数据是波 峰开始显示,后一帧是波谷开始。这样显示出来的波形就是乱的,于是为了解决这个问题,就需要做触发,也就是保证每次采集的起始电位相同。我们的采用的是用 外中断的形式,外面波形数据先不采集,先让它通过一个比较器,比如比较器的基准电压是1V,也就是每次都和1V比较,低于1V输出低电平,高于1V输出高 电平。当数据电压大于1V的时候,比较器输出高电平,高电平接到单片机外中断口,这样外中断就被触发。然后开始采集,这样就能保证每帧数据的起始点都相 同。
3 {1 G7 p8 z: S. L" o8 |1 Y& W  这个方案是大体方案,后来做了下修改。就是让AD一直在采集。外中断触发了后开启的是DMA,AD一直开着,只是控制DMA什么时候去取。从哪里开始取,取多少个点。下位机部分不再详说,贴下主要的程序,大侠们随便看看,多多指教。 ' k, P& v) m9 F( y3 c
定时器设置代码如下: ! G1 _9 u) S4 w  X/ ~
/*******************************************************************************
7 \% r# o/ A" w4 z. ?- `* Function Name  : TIM_Configuration
  a* A7 r5 s5 V9 D2 K/ {* Description    : Configure the TIM2.
2 S5 J, |8 V* i+ I5 e4 z5 A" q% L*******************************************************************************/ 4 o8 }# ?+ W2 B/ D! O  _
void TIM2_Configuration(void)
; S1 P! ~; w9 o6 v5 {( G+ D{ # Q0 i# I$ j: M% f4 T7 e: S8 [
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
( ?5 `8 j/ M$ ~0 h( t  TIM_OCInitTypeDef  TIM_OCInitStructure;
2 C; p3 O* p+ O( Q   
, V+ B; z5 s6 m5 z; V& _  TIM_DeInit(TIM2); //TIM2初始化 " m0 m) F+ F7 y# C( H
     
; S6 p, y( M1 d% Q  /* Time base configuration */ . b3 v7 i) n/ z6 w* p5 I, i
  TIM_TimeBaseStructure.TIM_Period = 18; //设置了下一个更新事件装入活动的自动重装载寄存器周期的值
9 ]# x8 C( k! {  TIM_TimeBaseStructure.TIM_Prescaler = 0; //设置了用来作为TIMx时钟频率除数的预分频值 $ W$ T4 `  M, g/ ?
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;  //设置了时钟分割
" |- N( Q( \# i; \  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //选择了计数器模式向上计数 1 j8 F6 o. @- m4 h7 u' J& D
4 E5 X, b$ g. @) S6 \  X
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);  //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx 5 H& A. M* D9 n3 L. p" d$ c& a3 z
9 ^& G# u" [9 C$ \9 v$ C6 H( o
  /* Prescaler configuration */
% d3 P; g: A/ {/ k# a//  TIM_PrescalerConfig(TIM2, 1, TIM_PSCReloadMode_Update); //设置TIMx重载次数 预分频值在更新事件装入 9 h2 q. |9 H* D
  : m  G1 W( m+ }. C. w9 f4 r5 w
  /* TIM_OCMode_Toggle Mode configuration: Channel2 */
1 R! k+ N; B. Q  H/ |  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;           
, L1 ^7 \2 h4 K" U: w2 a  TIM_OCInitStructure.TIM_Channel = TIM_Channel_2;           4 u% ^6 ]3 `  }* w: R
  TIM_OCInitStructure.TIM_Pulse = 9;   
; g  P8 E. Z. e! f- o  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;  //TIM输出比较极性低 $ s& N; V4 O$ n1 n( d
     % m" e6 G) d' A" Y
  TIM_OCInit(TIM2, &TIM_OCInitStructure);
2 D  a; L- ^- S& R8 p' ~   7 ]' `/ r9 }; h0 E& z
  TIM_ARRPreloadConfig(TIM2, ENABLE); //使能或者失能TIMx在ARR上的自动装载寄存器
5 K( I+ V" N, u  R3 S+ |( F   * ]# e& s7 _3 g5 A) h* i- F2 ?
  /* TIM2 enable counter */
  K+ ^* N) x! D  TIM_Cmd(TIM2, ENABLE); //使能TIMx外设 7 i) ~0 I' [% |# m. i7 p' C
}
& ?6 N* F5 Y, ]! f6 t: ]  gAD以及DMA设置代码:
+ e! @: P" _& t7 h! W4 J/******************************************************************************* ; ~6 x- Z/ C% N, H  b
* Function Name  : ADC_Configuration & H# N6 o2 ]" Y: I& B2 ?9 ~) l
* Description    : Configure the ADC1.
: c6 }5 d9 `; n) L' E' {& W*******************************************************************************/
* _/ `/ w) S& Q# F/ V9 [void ADC_Configuration(void)
9 o% Q8 l3 y8 s  x{
! @5 R0 ?* Q3 Q" @6 c! U  /* DMA channel1 configuration ----------------------------------------------*/
9 E" S6 k  X8 P  DMA_DeInit(DMA_Channel1); //复位DMA_Channel1 8 [1 C7 ~# f2 j/ M1 b$ u
  DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; //外围设备地址
: Z7 k6 m: e: T! v+ e* x, M  DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_Data[0]; //memory 地址
1 K8 U( t4 @! `# D  c& e" U  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //外围设备做为源 ; n$ ^: `1 z! C
  DMA_InitStructure.DMA_BufferSize = 1024;  //数据单元尺寸 2 @2 a9 N% F4 m7 S" ^5 a0 M
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  //外围地址是否自动增长 disable不增长
* v" w3 ~0 U( m  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //memory 是否自动增长 1 J1 v# m+ e/ i! @. U
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //外围设备寄存器尺寸16位 . P/ C3 ]5 u5 f  L+ g
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;  //memory尺寸16位
8 f' X" q/ K0 j* B) o  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;  //DMA 循环模式
. ]' J6 k1 _. [- B  DMA_InitStructure.DMA_Priority = DMA_Priority_High;  //DMA 通道优先级
( P5 q! N$ y7 N9 U% Z8 z$ p7 r  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //memory- to-memory转换 5 P/ N5 ]  g8 E. o7 X3 h" r
  DMA_Init(DMA_Channel1, &DMA_InitStructure);  //初始化DMA通道1 5 F9 Z, ?! O( u( c2 l* F
: R! `+ U* t: y( R/ \6 w
  /* DMA IT enable */ 9 I2 Z! J" o6 q* U
  DMA_ITConfig(DMA_Channel1, DMA_IT_TC, ENABLE); //使能DMA传输完成中断
0 L7 U" V* }  J5 n  
( c9 k' R5 u' d  D  /* ADC1 configuration ------------------------------------------------------*/                                                      4 j# {/ \3 v/ i& O+ I
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;  //ADC 工作模式 ADC1 ADC2 单独工作     # @1 H& j7 K# y8 c" r" g1 d
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;  //多通道扫描模式 7 ?* _1 L- V/ G; v" m. J
  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //是否启用连续转换模式 $ H  M  @1 I* p& i4 X; _/ T
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2;  //触发方式
- A# V( p& d  N6 @' O9 O3 |  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;   //数据右对齐 2 M0 E4 g' Q6 k' d
  ADC_InitStructure.ADC_NbrOfChannel = 1;  //ADC规则转换通道数量
7 p9 Z) r0 Q8 }  ADC_Init(ADC1, &ADC_InitStructure); 3 N$ G- L: \0 T: @1 i  H9 i
3 @. f* d7 u. w' X6 M; P2 O
  /* ADC1 regular channel10 configuration */ //配置转换规则
7 |" W4 ^! o4 X2 l, f8 h  ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_1Cycles5); ; ]: w* k& ?, r- F
   / w  o5 j  ?( m2 R5 l! `
  /* Enable ADC1 DMA */ + m" E$ M/ D' n8 }: [0 R
  ADC_DMACmd(ADC1, ENABLE);   S+ [# l7 E, p
7 Z8 g8 }5 c8 E4 N( k/ v4 e
  /* Enable ADC1 */
+ _% L, v5 C" j' r7 f; f  ADC_Cmd(ADC1, ENABLE);
4 B( m9 Z7 R( z  H3 l8 q  i. x" T+ a( T$ j  t/ o
  /* Enable ADC1 reset calibaration register */ 0 v8 i9 j! J& v1 F' @1 u1 o
  ADC_ResetCalibration(ADC1);  //复位ADC1 校准
) k4 A, l' N. g' g0 q% Y# i  /* Check the end of ADC1 reset calibration register */
$ ~. J3 h3 V( ^" K' l% Q! F! n  while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位完成 + T# g1 k& _$ `/ W/ M5 s

6 q8 z+ Q9 o  M# x0 K3 P  /* Start ADC1 calibaration */
; @) E/ x# j! |/ ]) ?  ADC_StartCalibration(ADC1);  //开始ADC1 校准转换 3 o) i* U3 W9 C5 |5 M0 w
  /* Check the end of ADC1 calibration */ 5 U4 H& S( z5 D: F% ]
  while(ADC_GetCalibrationStatus(ADC1));  //等待转换完成
; E" X& A6 ]- U+ o" t, X   9 j' m" E; a# H3 Z3 R& S
  ADC_ExternalTrigConvCmd( ADC1, ENABLE); //使能或者失能ADCx的经外部触发启动转换功能 6 G- k1 d9 Z9 P* [
} 9 G) k2 c" b9 J1 ]. j

! b& l. C% u; K1 G) dDMA中断服务程序: ' `) h, ?" n2 Q! G; V1 Q
/*******************************************************************************
0 c5 i% [, j- G* Function Name  : DMAChannel1_IRQHandler + s8 R4 C+ W1 A! C2 [2 G* I( T
* Description    : This function handles DMA Stream 1 interrupt request. 1 s) L0 x& \: b; j) B9 z& ]
*******************************************************************************/
2 ]0 B; Z2 d( S8 J+ Q9 D- Rvoid DMAChannel1_IRQHandler(void)
# `* x% l) o) ~( X{
0 Z7 O9 K* Y: n. z6 X, S5 |  DMA_Cmd(DMA_Channel1, DISABLE);  //关闭DMA通道1 9 f6 B- R$ a/ c% c0 H$ z+ D; G
  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( v4 F; A4 T3 D( N$ `! K; l! z
呵呵,双踪的呵呵......
sfq2008-104893 回答时间:2009-3-26 10:06:11

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

还有,我觉得这个做得不错,楼主可以参考一下3 o* N. B) c6 d$ V: G8 G6 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做简易示波器

很好
& h. W" j' Y) h不错
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 d/ e0 d: s, J$ J; w
强烈支持阿
3 b* n: g& q# e最近adc正看不懂呢
123下一页

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版