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

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

[复制链接]
〃聪聪哥哥 发布时间:2025-3-14 17:27
今天和大家分享一下使用STM32F769制作的位移采集装置
6 A% ]( Q; t8 h一:STM32F769 ADC 知识分享:
6 E0 Q5 X: W& X# ]+ z- C$ a1 K. }$ S8 i
STM32F769xx 系列有3个 ADC,这些 ADC 可以独立使用,也可以使用双重/三重模式(提高采样率)。STM32F769 的 ADC 是 12 位逐次逼近型的模拟数字转换器。它有 19 个通道,可测量 16 个外部源、2 个内部源和 Vbat 通道的信号。这些通道的 A/D 转换可以单次、连续、扫描或间断模式执行。ADC 的结果可以左对齐或右对齐方式存储在 16 位数据寄存器中。 模拟看门) L3 s1 w$ c/ A- a% v. s
狗特性允许应用程序检测输入电压是否超出用户定义的高/低阀值。STM32F769IGT6 包含有3个ADC。STM32F769的 ADC 最大的转换速率为2.4Mhz,也就是转换时间为 0.41us(在 ADCCLK=36M,采样周期为3个 ADC 时钟下得到),不要让 ADC 的时钟超过 36M,否则将导致结果准确度下降。
3 p0 V( n5 }9 m' ]5 FSTM32F769将ADC的转换分为2个通道组:规则通道组和注入通道组。规则通道相当于你正常运行的程序,而注入通道呢,就相当于中断。在你程序正常执行的时候,中断是可以打断你的执行的。同这个类似,注入通道的转换可以打断规则通道的转换, 在注入通道被转换完成之后,规则通道才得以继续转换。# B5 `! o( Q' H
6 w4 [- y$ G8 K. q) V! M4 T8 }/ \

# n! c8 W0 _, [. K' t  HADC 的主要特征:: T  h1 D! X# Y+ Z' S

4 x: z+ l0 L4 L可配置 12 位、10 位、8 位或6 位分辨率
6 Z+ }) v5 e8 r& A: U" b5 W6 Q1 i在转换结束、注入转换结束以及发生模拟看门狗或溢出事件时产生中断" [! {! V2 U0 M1 u
单次和连续转换模式
1 p% N! E/ G" i, w, ~6 y扫描模式,自动转化通道 0到通道 n数据8 t& k8 s) \% q& l3 W- }
数据对齐以保持内置数据一致性7 p. f/ }& K- c1 k. x; l
可独立设置各通道采样时间5 a* z: i' j" i! e* |
外部触发器选项,可为常规转换和注入转换配置极性6 _" V" R  Y& k& @
不连续采样模式& S' N* E4 R0 |* t2 G
双重/三重模式(具有2个或更多 ADC 的器件提供)2 p# N# A6 O' c: Y* ^
双重/三重 ADC 模式下可配置的 DMA 数据存储
- @' Z  {$ F8 C2 y9 `3 g双重/三重交替模式下可配置的转换间延迟# }/ a: H. r, f9 ?/ ~
ADC转换类型(参见数据手册)  k$ I& C1 C6 K$ d1 t! E2 G; h
ADC 电源要求:供电在 2.4V 到 3.6V 下可全速运行,供电低至 1.8V 时为慢速运行
' Q* Z- j" H% T7 A7 FADC 输入范围:VREF-≤VIN≤ VREF+- W' g8 {' r1 B. p* d1 y% y- E
常规通道转换期间可产生 DMA 请求
! g/ Q/ u6 @  k! h; G
' L7 z0 w7 H0 S7 w9 K8 ^9 H
9 _" I/ G& a, i' i二:STM32 cube MX 软件的配置如下所示:5 i+ @4 \4 d! n9 d% [4 D
1.png 2.png
8 {( ?* g" h. [- @2 k
5 J8 E: s$ s! G! Y( ~  Y, O* m$ g! i三:STM32 cube MX 软件生成代码如下所示:% q! U: ?1 z, r& _0 w7 E7 o
! r+ a, l+ C# \4 ?  \
  1.   hadc1.Instance = ADC1;
    & j; q. `: ~: V" S8 n- g
  2.   hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
    $ G# `6 O7 G2 j2 Z0 I9 ~( j
  3.   hadc1.Init.Resolution = ADC_RESOLUTION_12B;
    7 W$ Q/ F$ H- I
  4.   hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
    ; y4 P4 U* d# k" k% z& k0 M: c
  5.   hadc1.Init.ContinuousConvMode = ENABLE;2 l# M9 R5 f5 |2 k% j2 ^; Z
  6.   hadc1.Init.DiscontinuousConvMode = DISABLE;5 V7 q. {! m+ K' D0 b
  7.   hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
    5 |) G4 C6 J% v* w
  8.   hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1;! f$ N  z* K# E3 J# e. R) N
  9.   hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;6 b' w: q. h, H& {# ]" _
  10.   hadc1.Init.NbrOfConversion = 1;8 C3 ^8 Z( X4 D3 y. j7 ^. N5 {
  11.   hadc1.Init.DMAContinuousRequests = ENABLE;1 z# G: z  q9 H7 D) t
  12.   hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
    3 S' y. h' }6 v
  13.   if (HAL_ADC_Init(&hadc1) != HAL_OK)$ N! X1 C2 ~9 {/ c7 V8 a
  14.   {. \5 F( E: s" c1 z; d( p
  15.     Error_Handler();
    1 O  k, y3 j! i: x
  16.   }
复制代码
上述软件代码是软件配置之后,自动生成的功能,然后我下载之后,发现代码进入的 void NMI_Handler(void) 错误,由于我使用的是DMA的方式接收的ADC的数据,所以DMA还在正常运行,也是搞不懂为什么,串口输出也不正常。7 D: y6 A; X- A, B
然后我查询了下代码,将ADC的初始化修改如下所示代码:7 z1 Q+ E7 k- L/ h
  1.   hadc1.Instance = ADC1;+ d' n/ R* \7 n  F1 e
  2.   hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;% `3 f3 v" e( s, i. w( Q" O
  3.   hadc1.Init.Resolution = ADC_RESOLUTION_12B;
    % M4 f1 X) K: p) {
  4.   hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;7 K+ A- z2 \9 S8 x( c2 m
  5.   hadc1.Init.ContinuousConvMode = ENABLE;' p* D$ ?1 i- q
  6.   hadc1.Init.DiscontinuousConvMode = DISABLE;5 E* b! t3 h! c- `9 k, `$ `/ t2 m
  7.   hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;; k/ C' x7 Y  {- Q* t
  8.   hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1;+ e) W2 r! J. n; U$ X/ U( W
  9.   hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;! g: D1 m  T3 ]) G( G
  10.   hadc1.Init.NbrOfConversion = 1;# L! y# Y" ^5 n  P7 h1 T9 N
  11.   hadc1.Init.DMAContinuousRequests = ENABLE;
    + W" ]8 N$ f+ \$ U  M( y+ _4 N
  12.   hadc1.Init.EOCSelection = DISABLE;
    & ?; U  z1 r7 U" R3 T' G( z& }
  13.   if (HAL_ADC_Init(&hadc1) != HAL_OK)
    0 q# T/ g) a/ `
  14.   {7 `+ o' {1 B9 ~+ [
  15.     Error_Handler();
    - W4 j- `7 q6 c. E+ m2 N
  16.   }
复制代码
下面是ADC 结构体的的变量解释, _" B# A( `, u. n
  1. typedef struct{- Y+ B% ]/ z  N/ F& F
  2. uint32 t ClockPrescaler;//分频系数 2/4/6/8 分频
复制代码
这里发现是 cube MX 软件配置中对下述变量配置不太一样:
% h" E( \% h5 h) j
  1. hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV; , g' i" g0 z. T' A
  2. hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING; 
复制代码
配置好ADC代码后,我们就直接读取ADC的数据就可以了
) z6 p8 a6 }6 q主程序代码如下:; X8 f% ^& d) b0 ^0 S
  1.   HAL_Delay(200) ;4 w9 z1 P# l, T
  2.                 HAL_GPIO_TogglePin(GPIOJ,GPIO_PIN_13) ;7 S( [5 y! n6 u, x* J
  3. //                HAL_Delay(200) ;8 |$ Y4 }. b) v
  4. //                HAL_GPIO_TogglePin(GPIOJ,GPIO_PIN_5) ;
    / b/ `0 Y4 S9 k5 T! N+ f
  5. //                HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_4) ;
    . r% `* _7 {' d! Q& L4 K
  6. //                HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_12) ;9 [8 [- B3 n  X  z
  7.                 if(usart1_flag == 1)
    6 p/ X6 ?* \# f  e7 C/ s* [
  8.                 {
    - \5 i8 q# V: y- t1 e/ ?8 B7 V
  9.                         usart1_flag = 0 ;0 w/ p+ A4 w& L- r1 \+ f
  10.                         HAL_UART_Transmit(&huart1,Usart1_DEAL_RX_Buf,usart1_rx_len,100);
    ; g6 U2 p) a8 }# J( R) X1 n
  11. //                        printf("Hello STM32! Hello congcong! Hello STM32f769!\r\n");
    . G9 Q' A) K4 R% i* ]- O( n' g  P
  12. 7 e  g$ d( g% G0 n1 g+ g& ~$ |
  13.                         printf("Hello STM32! Hello congcong! Hello STM32f769!\r\n" );
    + q2 r. Q+ x/ n
  14.                 }8 S* G# L# C( [5 }( k. _4 B  Q. q
  15. 5 v$ f. d+ a! Y$ q3 x) i1 M
  16.                 printf("ubADCSample data = %5d\r\n" ,ubADCSample);
复制代码
PC截图如下所示:
. Q  _$ a% F5 U1 Y. @' G& r 3.png " u6 g3 s5 a" y5 J2 G. v

3 z( j" J3 r0 U6 A7 P- t, m* U: E; D调试感想如下:
  B3 }# E( U2 A; F; c" M1 E虽然使用STM32 读取了ADC的数据,但是数据飘动还是比较大了,对于工业控制并不是很好,所以这里我推荐以下几种处理方式:
7 t' h9 o8 c& w; x: T2 z7 ^1:中值滤波方式:
! o5 H' }  s- n! Q( W主要是程序在执行的时候,连续采集N次(需要注意下这里下,这里的N必须取值奇数),程序需要按大到小或者从小到达的顺序进行排序,然后取中间数值做为有效值。
: g3 T9 R8 B7 w: Z( b3 [
  1. int MidValueDeal(int N)
    9 b% M1 |# B2 S3 H$ _! |+ g+ Q
  2. {      
    $ o; C' z, ~# |4 W7 U8 S
  3.     int value_buf[N];      int i,j,k,temp;      - p) `" t! l% d9 e4 C
  4.     for( i = 0; i < N; ++i)        g) Y: m5 k3 G+ ?$ A* D# e
  5.     {        / {. }# S7 j% _
  6.      value_buf[i] = HAL_ADC_GetValue(&hadc1);  ' `% n- ]$ W1 H0 w! F3 N. D
  7.     }( j3 U/ h  E" @- V* H( ?
  8.       for(j = 0 ; j < N-1; ++j)        x  `- r  v' n8 w- }* ~% R- ^6 c3 Z
  9.       {          * d! j0 t7 Z$ \8 D6 p; W
  10.           for(k = 0; k < N-j-1; ++k)          " L  r; p8 h$ Q
  11.           {              //从小到大排序,冒泡法排序              - J1 o0 z& p3 G5 M
  12.               if(value_buf[k] > value_buf[k+1])              
    + w, F  a2 Z) L* Y6 g# P7 O
  13.               {                6 }; E4 M8 g- o7 m4 H" H
  14.                   temp = value_buf[k];               
    ' y% B- J' m/ d) D
  15.                   value_buf[k] = value_buf[k+1];               
    3 S, ~/ |, a6 N, Z$ C* C
  16.                   value_buf[k+1] = temp;              
    , N6 K. A: a+ s
  17.               }          ' V! m* |1 l! T5 Q; E5 [! T/ i( J
  18.           }      
    6 v, A$ A) @  |; F
  19.       }
    4 y- D3 c8 @+ u9 C7 R1 n# K
  20.       return value_buf[(N-1)/2];# W: I/ d: C9 j- m9 o
  21.   }
复制代码
2:算术平均数滤波:连续取值N个数据,对所有的数据进行取平均值;  i1 N4 Y5 T' J4 n0 z+ Q
  1. int AverValueDeal(int N)
    + j0 C' F# \" Q: ]" V3 Y2 D: p
  2. {   
    " n/ _/ _- x1 Q1 k( s3 f0 ^) C
  3.     int sum = 0;     + a7 `7 e7 f3 g# U6 \  v; D
  4.     unsinged short i;   
    * o) ^7 U. n) L2 i
  5.     for(i = 0; i < N; ++i)     
    ; Q# H2 T6 F3 ^4 P$ F
  6.     {        3 ]* F8 j0 O3 [5 |4 z2 M
  7.         sum += HAL_ADC_GetValue(&hadc1);      
    8 Z2 Y  k- T5 n) J" \2 ?' F2 J/ _
  8.     }     
    6 N" j, G) w2 O) G% k* Q
  9.     return sum/N;
    5 u$ K% v# R5 u: K
  10. }
复制代码
相比之下:STM32F769的硬件上面没有过采样的硬件配置,对于STM32U083单片机,已经支持硬件的过采样功能。当时测试时候发现,经过硬件处理之后,数据稳定性得到提高。7 i) {6 T* s4 |
不过即使没有硬件的过采样,我们依然可以使用软件模拟过采样、滤波采样的功能,对数据进行处理。
( \2 N/ l# E) A; z- Z9 W" ]$ h1 b  ^0 |8 f8 s' k

, h9 y# V/ `) D2 i4 {/ x最后,大家在调试ADC时候有什么好的建议和想法,麻烦评论区留言。
4 `6 a0 K$ `$ u' @& ~3 ?5 l
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分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版