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

STM32G0-Platformio+libopencm3-NTC温度采集

[复制链接]
STMCU小助手 发布时间:2023-2-22 17:09
使用Platformio平台的libopencm3开发框架来开发STM32G0,以下使用ADC进行NTC温度采集。

+ a# \1 G9 t/ x7 @* Q( I
1 新建项目
  • 建立ntc_temp项目

    . J% Q! p. u# }1 I1 q3 k$ S$ d0 W( k
在PIO的Home页面新建项目,项目名称ntc_temp,选择开发板为 MonkeyPi_STM32_G070RB,开发框架选择libopencm3;

( N& f9 J; Q6 a) A
  • 项目建立完成后在src目录下新建main.c主程序文件;
  • 修改下载和调试方式,这里开发板使用的是DAPLink仿真器,因此修改platformio.ini文件如下:
    ) F3 z- B$ z' P
  1. 1upload_protocol = cmsis-dap! l' u1 f+ k" b, @8 `* F
  2. 2debug_tool = cmsis-dap
复制代码

( g. ?# }! E: {* Y1 a$ t& B# i
5 @5 a) a: R5 D: Z, @9 c7 I
  • 为了能使用printf的浮点功能,可以加入如下配置:

    1 Z4 y$ B9 J. C, C! h3 f$ {
  1. 1build_flags =
      a9 |9 l; o2 V( e. S( Z( T
  2. 2    -Wl,-u,_printf_float
复制代码
, d1 ?3 B+ Y+ d% g1 e) g
; g1 g5 M/ C1 ]5 N
2 编写程序2.1 ADC设置
: Q8 j$ z2 i( b. ]; {
  1. 1void adc_setup()
    8 F' v0 S# s% d. |$ h! j. S
  2. 2{) `1 n# a5 V# k6 ^: O) K( v
  3. 3    rcc_periph_clock_enable(RCC_GPIOA);, R3 n# `. f: l6 m& W/ N9 |9 c  ~
  4. 4    rcc_periph_clock_enable(RCC_ADC);4 M0 {/ e2 [5 s0 S) X" _2 h
  5. 52 ]' G1 |* n* T6 X9 T
  6. 6    gpio_mode_setup(GPIOA,GPIO_MODE_ANALOG,GPIO_PUPD_NONE,GPIO0);* J' M1 }8 j/ W/ O, d! d  ^9 @% k
  7. 7
    5 y  _8 t& O6 {: H( W6 \1 k5 V
  8. 8    adc_power_off(ADC1);
    6 ]% ^8 b1 M( E2 n" a
  9. 9    adc_set_clk_prescale(ADC1,ADC_CCR_PRESC_DIV2);0 d* V+ i# |5 x7 _
  10. 10    adc_set_single_conversion_mode(ADC1);
    / A' ~. i7 `5 i& i9 D
  11. 11    adc_set_right_aligned(ADC1);- b/ Y7 c# F) |- u4 o) J; m
  12. 12    adc_set_sample_time_on_all_channels(ADC1,ADC_SMPTIME_160DOT5);/ w/ m! t  u0 Z. F7 x( Z
  13. 13    uint8_t channel = 0;
    * n$ s& Z7 ]& s2 g: s+ B+ x
  14. 14    adc_set_regular_sequence(ADC1,1,&channel);
    $ i( |/ J' x1 v+ z9 a5 |! {% A
  15. 15    adc_set_resolution(ADC1,ADC_CFGR1_RES_12_BIT);
    ( _6 P5 j3 {- B+ d" C
  16. 162 z, H4 I3 n# S5 O0 h# y; Q
  17. 17    adc_power_on(ADC1);
    # Q. }0 o7 p, f+ n; }6 q
  18. 184 S$ r; }  Q9 T) X, J/ q$ ]
  19. 19    delay_ms(10);" c5 k+ K- W5 {( `
  20. 202 @4 x4 c9 B, y% s: @  B
  21. 21}
复制代码

* R1 C/ j& \; @- q0 n5 O: l( j6 s
ADC设置按照之前文章介绍的方法设置PA0为ADC输入;
2 |/ R; G( E  z1 L( W8 R. S& E
2.2 ADC读取( d( X4 ^+ G9 y. S' ^
  1. 1uint16_t adc_sample()4 }0 D: P  m  r# m  F! L
  2. 2{
    4 k1 C/ E5 a3 }5 |
  3. 3    adc_start_conversion_regular(ADC1);
    9 O+ Z8 k4 T3 `0 K; y
  4. 4    return adc_read_regular(ADC1);  C8 d! v" q- ~; ?  q
  5. 5}
复制代码

: ?+ i2 y8 z8 }* ~. m4 a" U" _- `" A2 S5 v4 K
2.3 ADC与NTC的温度转换
  • 首先根据所选的NTC规格的温度-电阻对应表得到其ADC值的关系表:
    , P2 C- _4 b4 I6 q
这里的NTC分压电阻为10K,ADC分辨率为12位,因此ADC采集值为:(NTC电阻 x 4095) ÷ (NTC电阻 + 10K),即可得到如下所示的表格:
, d/ V" A6 C! q5 b( q- Q
微信图片_20230222170852.png
5 w- d7 }& }% J" x

2 d3 o4 G# K# y2 [5 y. }; O7 @: v
在EXCEL中计算出ADC采样数值-温度对应表,为了简单ADC进行取整,就可以得到电阻-55到125摄氏度的ADC对应表:
  1. 1const uint16_t ntcDATA[] = {
    - x- [6 R* N7 l6 x9 f7 Z9 k
  2. 24040,4038,4035,4031,4027,4023,4018,4013,4007,4001,3994,3987,3980,3972,3964,3956,; u, z1 e4 o, S* c/ C
  3. 3* S# O5 C; A; ?% {! D2 I0 J8 T# l% C
  4. 43947,3937,3928,3917,3907,3896,3884,3872,3860,3847,3833,3819,3804,3789,3773,3757,' [. v* k4 u5 H* S
  5. 5* X, p% f7 P% M
  6. 63740,3722,3703,3684,3664,3644,3622,3600,3577,3553,3528,3502,3475,3448,3419,3390,
    8 i5 w5 }3 v6 H* ^% f! z
  7. 7  J: M- n  t/ A9 F* ]- _
  8. 83360,3329,3297,3264,3230,3195,3160,3123,3086,3048,3010,2970,2930,2889,2848,2806,
    2 R% q3 V; ~1 |7 r8 }
  9. 9
    % H4 ?4 P& Q  d8 [/ t! o
  10. 102763,2720,2676,2633,2588,2544,2499,2454,2408,2363,2317,2272,2226,2181,2136,2091,
    4 x6 B+ A& k) B! R
  11. 11
    - r( K8 B0 t0 w; @$ N. u& ]
  12. 122048,2001,1957,1913,1869,1826,1783,1741,1699,1658,1617,1576,1537,1498,1459,1422,2 _5 r2 M+ E1 o9 @3 q3 M
  13. 13
    ! F" J" b8 r. c: a) Z! T& \6 ]
  14. 141385,1348,1312,1277,1243,1209,1176,1144,1112,1081,1051,1022,993,965,937,910,5 U7 H/ F& V, Y& F
  15. 15
      a$ I/ ?' t5 h
  16. 16884,859,834,810,786,764,741,720,699,679,659,639,621,602,585,568," M: W; T+ Z! v1 l: o' A
  17. 17: I) b, P. n, i
  18. 18551,535,519,504,490,475,461,448,435,422,410,398,387,376,365,355,
    % I" F6 T1 }3 K3 U5 z/ x
  19. 19
    + E9 ]- r/ ~5 _1 V2 p
  20. 20345,335,325,316,307,299,290,282,274,267,259,252,245,239,232,226,
    2 d2 {) P4 Y0 o3 P
  21. 21
    1 C- A% ^0 f8 Q9 n2 M! o+ [& j; S: I
  22. 22220,214,208,202,197,192,187,182,177,172,168,163,159,155,151,146,
    5 B: \$ K( g" T1 Q( N9 `
  23. 23
    8 t3 O+ u$ l: Q/ y3 A0 m
  24. 24143,139,135,132,1296 m2 T" }3 t' T: S, [  V/ C
  25. 25};
复制代码

2 n0 _1 E, y; D1 P
  • 然后根据表格获取温度,即每个ADC对应的索引即为温度值,如4040为索引0,对应第一个温度-55℃;
  • 表格中数据是有序的,因此这里可以使用二分法查找,对于两个数中间值则取其相近的那个值:
      B) J* o1 I+ b+ u! V0 U4 Z
  1. 1#define TEMP_HEADER_VALUE   -55 //the first temp in table
    " b" Q8 X  n$ r- |
  2. 2
    * w2 |5 k0 g7 j9 V
  3. 3#define ITEM_NUM(items) sizeof(items) / sizeof(items[0])
    * n- M6 `. P) y
  4. 4
    ) j3 t& m% m* |9 S
  5. 5/**
    7 Z' ^1 ], V: O* L
  6. 6 * @brief search the table, return a midium value if not found
    $ j; h) `8 a0 O7 w: {9 r; @/ l
  7. 7 *
    7 }/ _/ U1 o4 V1 F7 j6 m3 c5 u
  8. 8 * @param table  the data to search2 G8 k  F2 X: f9 U- \. v! u
  9. 9 * @param len    the table length$ x! C2 y6 u! x  `
  10. 10 * @param up    if data is min to max! D4 c/ U7 u8 c( G
  11. 11 * @return int32_t -1 -> if not found
    * j. }( a3 w" c6 X0 O& h  o
  12. 12 */- e; K: s5 v( U0 Y
  13. 13int32_t bsearch_ret_mid(const uint16_t *table, uint16_t len, bool up, uint16_t key)
    : l' v: {7 l& V/ f; S- G
  14. 14{/ V# [4 Z; X& f! w# B  h* z
  15. 15    uint16_t bot;+ F( M+ v7 N1 e; w+ [! \' d4 t; y
  16. 16    uint16_t mid;
    + w* M8 g) @  g( Z
  17. 17    uint16_t check;
    3 z6 ~; Z$ U' m9 Y9 Y- {+ d
  18. 18    uint16_t top;: ~3 o' s. M( ^% f: s( z
  19. 19
    5 l6 ^& N7 I* |
  20. 20    if (len == 0) {
    3 r7 o# l: `* t( q0 V+ Q+ [6 S! E
  21. 21        return -1;
      z) g& Q0 K) B3 _/ Q+ E
  22. 22    }
    3 k4 N9 w. X! M  s3 T
  23. 239 w, ~5 j& B; _1 O+ t, v
  24. 24    if (up) {
    5 g$ f* W9 {: Z# U7 B- z( N1 B
  25. 25        //the first data will be min
    0 L# `# n) l8 R1 c% o, F
  26. 26        if (key < table[0]) {
    0 Z& E4 M4 N0 `
  27. 27            return -1;
    * q; j( B+ d  s* K
  28. 28        }
    " a/ t: w% L, F8 c  k# n
  29. 29, k3 r! l( M( O( D7 d) Y
  30. 30        //bigger then the last data
      l. P( t6 z5 q2 X9 a
  31. 31        if (key > table[len - 1]) {* \7 K1 \* ^0 m. {. R- z4 c, X
  32. 32            return -1;5 ?4 H4 q3 [1 K
  33. 33        }
    0 `9 i0 v+ v6 n
  34. 34    } else {; U5 _$ [0 Q& K9 A
  35. 35        if (key > table[0]) {% q$ y) J- ], t  ~- N; J
  36. 36            return -1;
    . V  m" ?& G- `
  37. 37        }
    ; m4 p* `0 ]3 a, D8 T7 E$ }: s6 \
  38. 38
    - ~+ v/ K/ }7 U2 |4 A' H# S7 y
  39. 39        if (key < table[len - 1]) {" Z$ ^- w) y, }' ~+ K
  40. 40            return -1;/ h1 y! _# k. u; V  r' n9 |
  41. 41        }9 j" [( N" |, M7 {1 H- v
  42. 42    }
    ' `5 E( q8 n5 Q* V2 z1 h1 T
  43. 43, H- Z# H4 l3 j
  44. 44    bot = 0;3 {' z8 A5 i7 `! J- d4 \
  45. 45    top = len - 1;
      p/ z; g, O9 I: L; g
  46. 464 e6 W4 ]8 l, k1 V' J: s4 S' I
  47. 47    if (up) {
    5 Y( N' J$ L( p/ p0 L
  48. 48        while (bot < top) {) |% s5 {; ]4 L& A/ |9 V  t
  49. 49            mid = top - (top - bot) / 2;7 {) R$ c& ~2 Q- n( n& L5 y1 J: ^
  50. 50
    4 w1 W9 z7 S! f9 k8 S9 r
  51. 51            if (key < table[mid]) {
    8 L. W3 `$ C. D/ H
  52. 52                top = mid - 1;  t. b5 y$ L: k; W
  53. 53            } else {: _! {% I. x8 F4 q& `# m1 d5 s
  54. 54                bot = mid;
    6 [& i/ `' n$ U
  55. 55            }
    # i# W+ j5 R2 O5 b
  56. 56        }
    9 d. _& ^+ [2 O
  57. 57    } else {: G- T4 V7 l7 T& G1 q( @
  58. 58        while (bot < top) {4 v* r1 `3 m1 t) i/ A+ K' ]
  59. 59            mid = top - (top - bot) / 2;
    * i1 Y" r- d$ e/ u( d
  60. 607 [/ z  }/ r# R! _* k1 X
  61. 61            if (key > table[mid]) {4 u+ G: }0 M% H
  62. 62                top = mid - 1;: l4 B; @( H9 h  B
  63. 63            } else {
    9 L0 n! o; g. N% N  ~+ e- H
  64. 64                bot = mid;
    ; _" t6 c$ P9 E1 X7 U9 S
  65. 65            }2 p4 ?' p* y0 s, N4 l
  66. 66        }
    ! H: V& x2 b4 G0 L
  67. 67    }' A1 u+ H3 ^" _4 _) n6 T
  68. 68
    : V# d8 |$ R# N
  69. 69    if (key == table[top]) {3 Y! ^; F- x/ ]  S, A% [0 V- ~
  70. 70        return top;5 y, q4 q# U1 }( s0 h
  71. 71    }
    + c0 q! a1 ^# |5 o9 {
  72. 72" ?: C* T1 l9 r& j: E4 k
  73. 73    //not equal the data in table* I* }0 y: \4 q6 g
  74. 74    if (up) {
    8 @# Y/ z1 Y6 C& ]$ y
  75. 75        if (key > table[top]) {1 Y& \* v1 M) ~  k
  76. 76            return top;
    " p! j0 ?( `' k
  77. 77        }
    2 r4 v, h' M8 n1 M2 d$ n7 I; i/ v4 J+ Y
  78. 78    } else {- V* o3 v3 S# G; y; K& [
  79. 79        if (key < table[top]) {, F8 L' m$ x5 S1 R# r7 a$ W4 K
  80. 80            return top;
    1 [3 Y; ?) V7 i, C9 N3 l& V
  81. 81        }
    / Y0 F7 [& s. L/ q. c7 k; h1 t
  82. 82    }
    1 N/ ^: A2 b' m; t' N( D
  83. 83
    + ]2 S: q4 G! u3 P' s. X
  84. 84    return -1;. W: M3 f( l/ L+ ~' O6 W
  85. 85}
复制代码

: }% v3 ?$ |7 C1 M! {
4 r$ U; S: V4 C$ u2 L+ Y  f
  • 然后根据索引得到温度:

    3 s4 F" {8 T" h5 @6 {- E
  1. 1//get temperature , x10
    ! s  V, A; G7 Q5 b$ s
  2. 2int16_t ntc2tem(uint16_t adc)
    9 p/ r& G; s! r* t/ I
  3. 3{
    3 k# z* d2 \5 Y  T
  4. 4    int32_t  index = 0;
    9 \& p: P: V- p6 ?: S! }
  5. 5    int16_t temperature = 0;, ~7 I- E9 l2 y, o& o
  6. 6# d7 P5 x/ V! n( j  j( X0 ~: `
  7. 7    index = bsearch_ret_mid(ntcDATA, ITEM_NUM(ntcDATA),false,adc);
    ( T  v/ F" N2 C6 C$ Q$ [
  8. 8& Z) P2 L3 [/ r9 s& [" D& O2 }) X
  9. 9    //max, the first value: G  [, `* l2 N! T7 p& [# ?
  10. 10    if(index==0){: T4 X4 O; u; ?& N; F
  11. 11        temperature = TEMP_HEADER_VALUE*10;# T0 V2 L1 @- @! L
  12. 12    }  t  ^2 X2 Q% {1 _: h
  13. 13    //min, the last value+ G, J+ F5 `, _8 M& Z( C# b
  14. 14    else if(index>= ITEM_NUM(ntcDATA)){
    7 v/ T, ]' U5 s! L- F( }
  15. 15        temperature = 10*(TEMP_HEADER_VALUE + ITEM_NUM(ntcDATA));/ G! z1 p6 w7 F# _* `" i
  16. 16    }* S7 H* a' ~! D. I
  17. 17    else{; f2 P  F" n# z! n6 k1 U
  18. 18        //just get integer number* h% p9 J' ]6 c, n. Q, \. R) O8 N
  19. 19        // temperature = TEMP_HEADER_VALUE + index;
    - K0 \0 m+ Z! h; ^# ~$ T) b
  20. 20" \4 f6 K0 n# i- X- I
  21. 21        //get approximation data
    + T( \- G6 {$ C# ]2 N
  22. 22        temperature = TEMP_HEADER_VALUE + index;
    % J: k) ]9 E- |! I5 ?
  23. 23
    - J* G/ h% z$ B) X
  24. 24        //at middle0 Z4 i) m' v8 T( r
  25. 25        temperature = (temperature+1)*10 - 10.0 * (adc-ntcDATA[index+1])/(ntcDATA[index]-ntcDATA[index+1]);, b* p' H4 y9 B8 n3 A( g0 F
  26. 26    }
    # y2 }( J" p- v* i
  27. 272 t2 ]$ r5 T& s, j% c' H; L$ x
  28. 28    return temperature;
    $ D0 {/ r& I' E# `
  29. 29
    ( I6 G- O* t) u$ n  U- L' Y
  30. 30}
复制代码
" {: E4 ^# ^% g+ x6 m' |; b/ O
7 X3 Q3 y' t7 U6 h5 m/ t& F5 I
表格中的温度是1度进行变化的,如果需要稍微精确的,这里在1度中间的值近似看做线性进行计算;
这里为了减小计算误差,先对其扩大十倍计算,显示时候再转为小数:
  1. 1uint16_t adc = adc_sample();# G" q( ?% q$ V$ V' Z9 c3 Q
  2. 2
    : j+ Z( r+ v2 M7 v; I  ^
  3. 3int16_t temp_int = ntc2tem(adc);
    & Z3 {" @9 S8 U0 ?) l! _$ s" L( G
  4. 4float temp = temp_int/10.0;* h& u; a$ v2 U8 E& I; x
  5. 5- G6 H( W1 K- G, _7 n' d# h0 L8 |
  6. 6printf("adc: %d, temp: %.1f\r\n",adc, temp);
复制代码

7 F5 y1 L' W+ c' X# [3 P- ?% Z  w
3 连接硬件并测试& y: Z, ?0 N4 }1 O( X1 v
3.1 连接硬件
按照如下图,将NTC和10K电阻连接到PA0脚:
微信图片_20230222170842.png

0 q: K4 t) `+ \4 N) Z
0 y7 L# w" i) [+ u9 t- d
3.2 测试
打开串口,当手放在NTC上可以看到温度变化:
微信图片_20230222170837.png
( H5 ?% e9 s" Y
转载自:MakerInChina.cn
$ V3 |0 b/ r4 `

  I6 E9 f5 J$ h7 _
赞 收藏 评论0 发布时间:2023-2-22 17:09

举报

0个回答

所属标签

相似技术帖

官网相关资源

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