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

【STM32F769I-DISC1】测评04:使用ADC通道制作的位移采集模块,上传数据到PC端

[复制链接]
〃聪聪哥哥 发布时间:2025-3-14 17:27
今天和大家分享一下使用STM32F769制作的位移采集装置
  Y$ R" R5 z' Z+ s4 K一:STM32F769 ADC 知识分享:
+ y" n) W6 E# }+ i
" S) e+ z& h' I1 n# _STM32F769xx 系列有3个 ADC,这些 ADC 可以独立使用,也可以使用双重/三重模式(提高采样率)。STM32F769 的 ADC 是 12 位逐次逼近型的模拟数字转换器。它有 19 个通道,可测量 16 个外部源、2 个内部源和 Vbat 通道的信号。这些通道的 A/D 转换可以单次、连续、扫描或间断模式执行。ADC 的结果可以左对齐或右对齐方式存储在 16 位数据寄存器中。 模拟看门
3 l+ ~) \/ I9 |3 V狗特性允许应用程序检测输入电压是否超出用户定义的高/低阀值。STM32F769IGT6 包含有3个ADC。STM32F769的 ADC 最大的转换速率为2.4Mhz,也就是转换时间为 0.41us(在 ADCCLK=36M,采样周期为3个 ADC 时钟下得到),不要让 ADC 的时钟超过 36M,否则将导致结果准确度下降。; l8 |3 m( I( n  ~( [  j) @/ x
STM32F769将ADC的转换分为2个通道组:规则通道组和注入通道组。规则通道相当于你正常运行的程序,而注入通道呢,就相当于中断。在你程序正常执行的时候,中断是可以打断你的执行的。同这个类似,注入通道的转换可以打断规则通道的转换, 在注入通道被转换完成之后,规则通道才得以继续转换。; _7 x+ z5 N2 M1 f: p4 t% i7 G

9 d9 m+ J* d+ e1 M6 u- ]9 ^  c* _& B4 P& b2 |: u
ADC 的主要特征:7 m8 l0 l: R6 O& X' g

8 g2 e1 J9 \* O' x" P- J, p可配置 12 位、10 位、8 位或6 位分辨率
' l: g! g7 [7 h0 Z4 G* L3 Y5 y在转换结束、注入转换结束以及发生模拟看门狗或溢出事件时产生中断/ E1 s) R& k2 Z& U6 W" X- C& X9 t
单次和连续转换模式
9 P# N8 F9 O4 j! v  O扫描模式,自动转化通道 0到通道 n数据
9 X1 s8 E5 Q0 y% m) q$ v& S数据对齐以保持内置数据一致性% C+ c/ j, D; Q4 g
可独立设置各通道采样时间6 b6 _& g2 ~! S# s; v
外部触发器选项,可为常规转换和注入转换配置极性
7 p2 u6 I* T4 m不连续采样模式. S* m! @" E' i
双重/三重模式(具有2个或更多 ADC 的器件提供)) w& `, L* a! }; R
双重/三重 ADC 模式下可配置的 DMA 数据存储9 d. D! ]% @8 X8 G
双重/三重交替模式下可配置的转换间延迟9 K+ W3 y- ~( K$ n" a* K8 I
ADC转换类型(参见数据手册)7 K$ ]" [& A& ~" M6 s7 n! B
ADC 电源要求:供电在 2.4V 到 3.6V 下可全速运行,供电低至 1.8V 时为慢速运行
, e3 u- B$ j: F" MADC 输入范围:VREF-≤VIN≤ VREF+) z- ]- M' V! Q* G) n2 L3 [
常规通道转换期间可产生 DMA 请求/ Q4 P/ c! P: I. F: u/ z
, q( Q7 h4 i; G3 z7 L, s

; R* u1 F5 s1 P3 e: V2 Z二:STM32 cube MX 软件的配置如下所示:/ s3 a1 w# |- b: e3 B% a
1.png 2.png & B9 F" w5 D. j) L3 o

( R/ K% ]' ?: T# `$ v( ]三:STM32 cube MX 软件生成代码如下所示:5 G( F9 b1 n' ?
: Z7 o4 `# y# C0 \# v6 G4 w
  1.   hadc1.Instance = ADC1;/ [. h0 T3 ]6 h. g8 @- y% t
  2.   hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;. @% h* ~; b) ~3 w8 ^% n" f
  3.   hadc1.Init.Resolution = ADC_RESOLUTION_12B;/ ^& A9 a6 \# E7 M% K1 y
  4.   hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
    + c4 E' ?; R5 g5 k
  5.   hadc1.Init.ContinuousConvMode = ENABLE;
    ) |! F" A6 ~- n0 Y1 c& z* G0 R% n, _8 ^
  6.   hadc1.Init.DiscontinuousConvMode = DISABLE;- k4 c' j( g: q% O" {, T, g! l! ]& x5 _
  7.   hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
    2 ~, T3 k7 r6 h) N% V' c1 |( _
  8.   hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1;) [; w) d( X7 {& S9 u. D
  9.   hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
      B% Z% v0 ^; x$ y4 q7 ]! {
  10.   hadc1.Init.NbrOfConversion = 1;0 l; j! J3 e) J; e" m
  11.   hadc1.Init.DMAContinuousRequests = ENABLE;+ f' j* R  K, ?1 c0 t+ }
  12.   hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
    . D4 d+ O/ r2 h- V, w* y/ l2 T9 r
  13.   if (HAL_ADC_Init(&hadc1) != HAL_OK)
    - I* T7 u$ a/ Z$ e  y( \) F  h
  14.   {
    ) Y& l5 A- W6 C6 o
  15.     Error_Handler();
    ' z; L; }* j; ^! b5 m1 c" W
  16.   }
复制代码
上述软件代码是软件配置之后,自动生成的功能,然后我下载之后,发现代码进入的 void NMI_Handler(void) 错误,由于我使用的是DMA的方式接收的ADC的数据,所以DMA还在正常运行,也是搞不懂为什么,串口输出也不正常。
, e, c! J% ~1 i然后我查询了下代码,将ADC的初始化修改如下所示代码:  g# O* F4 \4 t" b  F: g
  1.   hadc1.Instance = ADC1;/ ~+ O( k$ {2 `1 R
  2.   hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;& e$ q- {3 s" Y3 s
  3.   hadc1.Init.Resolution = ADC_RESOLUTION_12B;. _# |9 E' [2 e4 C
  4.   hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;' _! o  N5 u2 b9 w% |, r
  5.   hadc1.Init.ContinuousConvMode = ENABLE;0 k3 D! g% @$ ]+ ~+ C7 |
  6.   hadc1.Init.DiscontinuousConvMode = DISABLE;. D& {: M  o" ~6 N% M
  7.   hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;+ U+ {! G6 A8 e4 U9 i
  8.   hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1;/ H4 L" i# Z5 D- l! V$ X+ ?
  9.   hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
    , B  }" [# U3 K+ s* C6 }
  10.   hadc1.Init.NbrOfConversion = 1;! o9 j5 v: y$ v( ~
  11.   hadc1.Init.DMAContinuousRequests = ENABLE;
    * V5 N( K- g# C2 o4 W% H8 o2 r
  12.   hadc1.Init.EOCSelection = DISABLE;1 m/ Z, P6 I7 k$ n
  13.   if (HAL_ADC_Init(&hadc1) != HAL_OK)( t# z* P2 n3 O  H% |& T; @5 F' J
  14.   {: E! c* e9 I' v! K* q
  15.     Error_Handler();
    : k1 I# n6 |3 H2 E
  16.   }
复制代码
下面是ADC 结构体的的变量解释
3 n- T4 k2 G/ Z; h
  1. typedef struct{4 q# o2 E8 d" @
  2. uint32 t ClockPrescaler;//分频系数 2/4/6/8 分频
复制代码
这里发现是 cube MX 软件配置中对下述变量配置不太一样:- Z9 t5 r8 o& w* K5 v
  1. hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV; 
      V8 _" P5 ~5 \3 ]7 z1 D6 V
  2. hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING; 
复制代码
配置好ADC代码后,我们就直接读取ADC的数据就可以了
( V- X5 O% v8 I* o主程序代码如下:* z5 Y, ?6 p+ d1 v. ]2 f" w
  1.   HAL_Delay(200) ;
    / \, E0 ~; R& z$ @$ k. s* ^3 Q- i
  2.                 HAL_GPIO_TogglePin(GPIOJ,GPIO_PIN_13) ;
      g! I0 t: ]/ d) I7 m. X
  3. //                HAL_Delay(200) ;
    4 q1 Z" L" e1 m# N
  4. //                HAL_GPIO_TogglePin(GPIOJ,GPIO_PIN_5) ;2 W! L% l+ R# J4 ~4 N9 M6 u' U
  5. //                HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_4) ;
    2 ?( F5 g+ ]; q9 K' G) p
  6. //                HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_12) ;/ b& E- x4 O1 ]# D. R3 U6 ?$ v
  7.                 if(usart1_flag == 1)
    * J' B& u, h8 V& r. B
  8.                 {
    ( S0 p: C: u1 N2 i5 |2 z  Y
  9.                         usart1_flag = 0 ;3 |! o- ~, R) y# f6 q' ]
  10.                         HAL_UART_Transmit(&huart1,Usart1_DEAL_RX_Buf,usart1_rx_len,100);
    ) p" d% _& `1 Z7 V/ ^5 g& q0 f
  11. //                        printf("Hello STM32! Hello congcong! Hello STM32f769!\r\n");, x; P* |  y3 v6 x+ C8 [: ]) j

  12. % U6 `+ p4 Z. I8 s" |1 p; l
  13.                         printf("Hello STM32! Hello congcong! Hello STM32f769!\r\n" );  Z5 T5 V9 z3 ]2 i
  14.                 }
    7 ^7 c( W$ ~" h3 V$ P

  15. / q% h/ g9 S) c. T) i! k
  16.                 printf("ubADCSample data = %5d\r\n" ,ubADCSample);
复制代码
PC截图如下所示:
# J5 b: p; ?$ r( k0 F" Z 3.png
8 U7 J- [* T' u4 A8 c
! ]+ I, s6 y) o7 X2 k调试感想如下:
) m& ~! M2 r- n8 |+ w8 {) K& R虽然使用STM32 读取了ADC的数据,但是数据飘动还是比较大了,对于工业控制并不是很好,所以这里我推荐以下几种处理方式:
4 H2 E$ ?! g( p) d/ M% Q6 e/ o1:中值滤波方式:
' t' T! ~5 P- b9 R" m/ F; X, O主要是程序在执行的时候,连续采集N次(需要注意下这里下,这里的N必须取值奇数),程序需要按大到小或者从小到达的顺序进行排序,然后取中间数值做为有效值。5 ?1 E, b& t( t8 O% q4 u
  1. int MidValueDeal(int N)
    & M5 c' q9 P9 ]! e# H* m
  2. {      
    & m. W/ P. r8 \$ x+ T% r4 g  b  t
  3.     int value_buf[N];      int i,j,k,temp;      2 a8 X# P5 z1 O- G; p# }
  4.     for( i = 0; i < N; ++i)      : B! D2 q: x) [; E. Y
  5.     {        
    - ?, k  Z/ P6 [- S$ c
  6.      value_buf[i] = HAL_ADC_GetValue(&hadc1);  6 E+ s, F% c6 y0 n/ R, ^( x  B, ~  [" ]
  7.     }
    6 I1 _5 f& d4 ]8 t$ }& B! ~
  8.       for(j = 0 ; j < N-1; ++j)      
    * c, _0 a9 `: i3 N) ]" [# g
  9.       {         
    4 D. P: U# B2 B* D
  10.           for(k = 0; k < N-j-1; ++k)          ( l# f6 [, Q, y
  11.           {              //从小到大排序,冒泡法排序              0 i/ c0 v, Z1 ~4 I
  12.               if(value_buf[k] > value_buf[k+1])              
    * }8 b! R# |, a
  13.               {                ( E/ V1 J# `) V: l' O( O
  14.                   temp = value_buf[k];                6 L1 k+ ]4 N" S$ O3 l' }9 X; f0 v
  15.                   value_buf[k] = value_buf[k+1];               
    / b8 K5 b" ~- k0 \5 Y
  16.                   value_buf[k+1] = temp;              0 w* v$ u' _+ `8 W8 h# G
  17.               }         
    8 r6 ~5 _2 `/ n5 b
  18.           }      2 p5 J& l5 p  i+ D' C6 L% i7 X: S
  19.       }1 O- z1 m* _& |* d% u4 S
  20.       return value_buf[(N-1)/2];" ^! Y: b3 I  T- y0 z2 G3 S
  21.   }
复制代码
2:算术平均数滤波:连续取值N个数据,对所有的数据进行取平均值;
" I4 O  M* X* p! N- [3 i0 `
  1. int AverValueDeal(int N)2 y& Q5 g+ v( h7 ]( t7 x
  2. {    " D% U" _- C- ]# Q: N* r
  3.     int sum = 0;     & o7 B' X. P& I0 n5 j0 m1 L/ ]8 q
  4.     unsinged short i;    . w, o6 k, o& }
  5.     for(i = 0; i < N; ++i)     ' H1 K3 D3 T. a5 E, g5 Z
  6.     {        ; ?+ R& k# Z& N$ X# r+ f
  7.         sum += HAL_ADC_GetValue(&hadc1);      0 ~! g' ]  A9 u% `+ s& z
  8.     }     ; y5 Q1 `6 y9 l8 \& q4 r
  9.     return sum/N;
    4 `* R( i# G& J
  10. }
复制代码
相比之下:STM32F769的硬件上面没有过采样的硬件配置,对于STM32U083单片机,已经支持硬件的过采样功能。当时测试时候发现,经过硬件处理之后,数据稳定性得到提高。# [3 b- O2 `" E6 m
不过即使没有硬件的过采样,我们依然可以使用软件模拟过采样、滤波采样的功能,对数据进行处理。
3 |9 \0 x9 P# R) w- g$ I6 W* R+ {; C8 U9 n
! u* Z6 ]) w  m
最后,大家在调试ADC时候有什么好的建议和想法,麻烦评论区留言。. G* B2 T% n9 B- x! q0 d9 g
5.png
4.png
赞 收藏 评论5 发布时间:2025-3-14 17:27

举报

5个回答
lugl 回答时间:2025-3-15 09:20:02

用标准的基准源进行观察。打印出ADC的值,使用分析软件进行分析评估。

〃聪聪哥哥 回答时间:2025-3-16 12:36:37

lugl 发表于 2025-3-15 09:20
用标准的基准源进行观察。打印出ADC的值,使用分析软件进行分析评估。
...

不知道是不是我配置的问题,这个AD的数据,感觉还没有U083单片机的采集稳定

lugl 回答时间:2025-3-16 19:41:05

〃聪聪哥哥 发表于 2025-3-16 12:36
不知道是不是我配置的问题,这个AD的数据,感觉还没有U083单片机的采集稳定
...

需要进行滤波算法进行处理吧。这么高的主频处理起来应该不难。但是这个12bit的ADC,他的应用场景不是高精度的ADC采集。如果想稳定,最好使用专业的ADC吧。

〃聪聪哥哥 回答时间:2025-3-17 19:45:18

lugl 发表于 2025-3-16 19:41
需要进行滤波算法进行处理吧。这么高的主频处理起来应该不难。但是这个12bit的ADC,他的应用场景不是 ...

[md]嗯,这个正好有个机会研究一下,,感觉不如U0系列的好呢😄

lugl 回答时间:2025-3-18 05:19:04

〃聪聪哥哥 发表于 2025-3-17 19:45
嗯,这个正好有个机会研究一下,,感觉不如U0系列的好呢😄

这个也不能这样说,F769在当年可以说是高档产品了。他还有其他的功能,综合性能比U0要强很多。但是U0的使用的内核比F769要新,在能耗性能比上要比F7xx要好。各有所长。

所属标签

ST中文论坛活动

即日起开启活动话题入口,之后的活动统一都放在此处,欢迎大家的加入!


最新内容

相似技术帖

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