|
使用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- 1upload_protocol = cmsis-dap! l' u1 f+ k" b, @8 `* F
- 2debug_tool = cmsis-dap
复制代码
( g. ?# }! E: {* Y1 a$ t& B# i
5 @5 a) a: R5 D: Z, @9 c7 I- 1build_flags =
a9 |9 l; o2 V( e. S( Z( T - 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. ]; {- 1void adc_setup()
8 F' v0 S# s% d. |$ h! j. S - 2{) `1 n# a5 V# k6 ^: O) K( v
- 3 rcc_periph_clock_enable(RCC_GPIOA);, R3 n# `. f: l6 m& W/ N9 |9 c ~
- 4 rcc_periph_clock_enable(RCC_ADC);4 M0 {/ e2 [5 s0 S) X" _2 h
- 52 ]' G1 |* n* T6 X9 T
- 6 gpio_mode_setup(GPIOA,GPIO_MODE_ANALOG,GPIO_PUPD_NONE,GPIO0);* J' M1 }8 j/ W/ O, d! d ^9 @% k
- 7
5 y _8 t& O6 {: H( W6 \1 k5 V - 8 adc_power_off(ADC1);
6 ]% ^8 b1 M( E2 n" a - 9 adc_set_clk_prescale(ADC1,ADC_CCR_PRESC_DIV2);0 d* V+ i# |5 x7 _
- 10 adc_set_single_conversion_mode(ADC1);
/ A' ~. i7 `5 i& i9 D - 11 adc_set_right_aligned(ADC1);- b/ Y7 c# F) |- u4 o) J; m
- 12 adc_set_sample_time_on_all_channels(ADC1,ADC_SMPTIME_160DOT5);/ w/ m! t u0 Z. F7 x( Z
- 13 uint8_t channel = 0;
* n$ s& Z7 ]& s2 g: s+ B+ x - 14 adc_set_regular_sequence(ADC1,1,&channel);
$ i( |/ J' x1 v+ z9 a5 |! {% A - 15 adc_set_resolution(ADC1,ADC_CFGR1_RES_12_BIT);
( _6 P5 j3 {- B+ d" C - 162 z, H4 I3 n# S5 O0 h# y; Q
- 17 adc_power_on(ADC1);
# Q. }0 o7 p, f+ n; }6 q - 184 S$ r; } Q9 T) X, J/ q$ ]
- 19 delay_ms(10);" c5 k+ K- W5 {( `
- 202 @4 x4 c9 B, y% s: @ B
- 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' ^
- 1uint16_t adc_sample()4 }0 D: P m r# m F! L
- 2{
4 k1 C/ E5 a3 }5 | - 3 adc_start_conversion_regular(ADC1);
9 O+ Z8 k4 T3 `0 K; y - 4 return adc_read_regular(ADC1); C8 d! v" q- ~; ? q
- 5}
复制代码
: ?+ i2 y8 z8 }* ~. m4 a" U" _- `" A2 S5 v4 K
2.3 ADC与NTC的温度转换这里的NTC分压电阻为10K,ADC分辨率为12位,因此ADC采集值为:(NTC电阻 x 4095) ÷ (NTC电阻 + 10K),即可得到如下所示的表格: , d/ V" A6 C! q5 b( q- Q
5 w- d7 }& }% J" x
2 d3 o4 G# K# y2 [5 y. }; O7 @: v在EXCEL中计算出ADC采样数值-温度对应表,为了简单ADC进行取整,就可以得到电阻-55到125摄氏度的ADC对应表: - 1const uint16_t ntcDATA[] = {
- x- [6 R* N7 l6 x9 f7 Z9 k - 24040,4038,4035,4031,4027,4023,4018,4013,4007,4001,3994,3987,3980,3972,3964,3956,; u, z1 e4 o, S* c/ C
- 3* S# O5 C; A; ?% {! D2 I0 J8 T# l% C
- 43947,3937,3928,3917,3907,3896,3884,3872,3860,3847,3833,3819,3804,3789,3773,3757,' [. v* k4 u5 H* S
- 5* X, p% f7 P% M
- 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 J: M- n t/ A9 F* ]- _
- 83360,3329,3297,3264,3230,3195,3160,3123,3086,3048,3010,2970,2930,2889,2848,2806,
2 R% q3 V; ~1 |7 r8 } - 9
% H4 ?4 P& Q d8 [/ t! o - 102763,2720,2676,2633,2588,2544,2499,2454,2408,2363,2317,2272,2226,2181,2136,2091,
4 x6 B+ A& k) B! R - 11
- r( K8 B0 t0 w; @$ N. u& ] - 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
! F" J" b8 r. c: a) Z! T& \6 ] - 141385,1348,1312,1277,1243,1209,1176,1144,1112,1081,1051,1022,993,965,937,910,5 U7 H/ F& V, Y& F
- 15
a$ I/ ?' t5 h - 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: I) b, P. n, i
- 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
+ E9 ]- r/ ~5 _1 V2 p - 20345,335,325,316,307,299,290,282,274,267,259,252,245,239,232,226,
2 d2 {) P4 Y0 o3 P - 21
1 C- A% ^0 f8 Q9 n2 M! o+ [& j; S: I - 22220,214,208,202,197,192,187,182,177,172,168,163,159,155,151,146,
5 B: \$ K( g" T1 Q( N9 ` - 23
8 t3 O+ u$ l: Q/ y3 A0 m - 24143,139,135,132,1296 m2 T" }3 t' T: S, [ V/ C
- 25};
复制代码
2 n0 _1 E, y; D1 P- 1#define TEMP_HEADER_VALUE -55 //the first temp in table
" b" Q8 X n$ r- | - 2
* w2 |5 k0 g7 j9 V - 3#define ITEM_NUM(items) sizeof(items) / sizeof(items[0])
* n- M6 `. P) y - 4
) j3 t& m% m* |9 S - 5/**
7 Z' ^1 ], V: O* L - 6 * @brief search the table, return a midium value if not found
$ j; h) `8 a0 O7 w: {9 r; @/ l - 7 *
7 }/ _/ U1 o4 V1 F7 j6 m3 c5 u - 8 * @param table the data to search2 G8 k F2 X: f9 U- \. v! u
- 9 * @param len the table length$ x! C2 y6 u! x `
- 10 * @param up if data is min to max! D4 c/ U7 u8 c( G
- 11 * @return int32_t -1 -> if not found
* j. }( a3 w" c6 X0 O& h o - 12 */- e; K: s5 v( U0 Y
- 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{/ V# [4 Z; X& f! w# B h* z
- 15 uint16_t bot;+ F( M+ v7 N1 e; w+ [! \' d4 t; y
- 16 uint16_t mid;
+ w* M8 g) @ g( Z - 17 uint16_t check;
3 z6 ~; Z$ U' m9 Y9 Y- {+ d - 18 uint16_t top;: ~3 o' s. M( ^% f: s( z
- 19
5 l6 ^& N7 I* | - 20 if (len == 0) {
3 r7 o# l: `* t( q0 V+ Q+ [6 S! E - 21 return -1;
z) g& Q0 K) B3 _/ Q+ E - 22 }
3 k4 N9 w. X! M s3 T - 239 w, ~5 j& B; _1 O+ t, v
- 24 if (up) {
5 g$ f* W9 {: Z# U7 B- z( N1 B - 25 //the first data will be min
0 L# `# n) l8 R1 c% o, F - 26 if (key < table[0]) {
0 Z& E4 M4 N0 ` - 27 return -1;
* q; j( B+ d s* K - 28 }
" a/ t: w% L, F8 c k# n - 29, k3 r! l( M( O( D7 d) Y
- 30 //bigger then the last data
l. P( t6 z5 q2 X9 a - 31 if (key > table[len - 1]) {* \7 K1 \* ^0 m. {. R- z4 c, X
- 32 return -1;5 ?4 H4 q3 [1 K
- 33 }
0 `9 i0 v+ v6 n - 34 } else {; U5 _$ [0 Q& K9 A
- 35 if (key > table[0]) {% q$ y) J- ], t ~- N; J
- 36 return -1;
. V m" ?& G- ` - 37 }
; m4 p* `0 ]3 a, D8 T7 E$ }: s6 \ - 38
- ~+ v/ K/ }7 U2 |4 A' H# S7 y - 39 if (key < table[len - 1]) {" Z$ ^- w) y, }' ~+ K
- 40 return -1;/ h1 y! _# k. u; V r' n9 |
- 41 }9 j" [( N" |, M7 {1 H- v
- 42 }
' `5 E( q8 n5 Q* V2 z1 h1 T - 43, H- Z# H4 l3 j
- 44 bot = 0;3 {' z8 A5 i7 `! J- d4 \
- 45 top = len - 1;
p/ z; g, O9 I: L; g - 464 e6 W4 ]8 l, k1 V' J: s4 S' I
- 47 if (up) {
5 Y( N' J$ L( p/ p0 L - 48 while (bot < top) {) |% s5 {; ]4 L& A/ |9 V t
- 49 mid = top - (top - bot) / 2;7 {) R$ c& ~2 Q- n( n& L5 y1 J: ^
- 50
4 w1 W9 z7 S! f9 k8 S9 r - 51 if (key < table[mid]) {
8 L. W3 `$ C. D/ H - 52 top = mid - 1; t. b5 y$ L: k; W
- 53 } else {: _! {% I. x8 F4 q& `# m1 d5 s
- 54 bot = mid;
6 [& i/ `' n$ U - 55 }
# i# W+ j5 R2 O5 b - 56 }
9 d. _& ^+ [2 O - 57 } else {: G- T4 V7 l7 T& G1 q( @
- 58 while (bot < top) {4 v* r1 `3 m1 t) i/ A+ K' ]
- 59 mid = top - (top - bot) / 2;
* i1 Y" r- d$ e/ u( d - 607 [/ z }/ r# R! _* k1 X
- 61 if (key > table[mid]) {4 u+ G: }0 M% H
- 62 top = mid - 1;: l4 B; @( H9 h B
- 63 } else {
9 L0 n! o; g. N% N ~+ e- H - 64 bot = mid;
; _" t6 c$ P9 E1 X7 U9 S - 65 }2 p4 ?' p* y0 s, N4 l
- 66 }
! H: V& x2 b4 G0 L - 67 }' A1 u+ H3 ^" _4 _) n6 T
- 68
: V# d8 |$ R# N - 69 if (key == table[top]) {3 Y! ^; F- x/ ] S, A% [0 V- ~
- 70 return top;5 y, q4 q# U1 }( s0 h
- 71 }
+ c0 q! a1 ^# |5 o9 { - 72" ?: C* T1 l9 r& j: E4 k
- 73 //not equal the data in table* I* }0 y: \4 q6 g
- 74 if (up) {
8 @# Y/ z1 Y6 C& ]$ y - 75 if (key > table[top]) {1 Y& \* v1 M) ~ k
- 76 return top;
" p! j0 ?( `' k - 77 }
2 r4 v, h' M8 n1 M2 d$ n7 I; i/ v4 J+ Y - 78 } else {- V* o3 v3 S# G; y; K& [
- 79 if (key < table[top]) {, F8 L' m$ x5 S1 R# r7 a$ W4 K
- 80 return top;
1 [3 Y; ?) V7 i, C9 N3 l& V - 81 }
/ Y0 F7 [& s. L/ q. c7 k; h1 t - 82 }
1 N/ ^: A2 b' m; t' N( D - 83
+ ]2 S: q4 G! u3 P' s. X - 84 return -1;. W: M3 f( l/ L+ ~' O6 W
- 85}
复制代码
: }% v3 ?$ |7 C1 M! {
4 r$ U; S: V4 C$ u2 L+ Y f然后根据索引得到温度:
3 s4 F" {8 T" h5 @6 {- E
- 1//get temperature , x10
! s V, A; G7 Q5 b$ s - 2int16_t ntc2tem(uint16_t adc)
9 p/ r& G; s! r* t/ I - 3{
3 k# z* d2 \5 Y T - 4 int32_t index = 0;
9 \& p: P: V- p6 ?: S! } - 5 int16_t temperature = 0;, ~7 I- E9 l2 y, o& o
- 6# d7 P5 x/ V! n( j j( X0 ~: `
- 7 index = bsearch_ret_mid(ntcDATA, ITEM_NUM(ntcDATA),false,adc);
( T v/ F" N2 C6 C$ Q$ [ - 8& Z) P2 L3 [/ r9 s& [" D& O2 }) X
- 9 //max, the first value: G [, `* l2 N! T7 p& [# ?
- 10 if(index==0){: T4 X4 O; u; ?& N; F
- 11 temperature = TEMP_HEADER_VALUE*10;# T0 V2 L1 @- @! L
- 12 } t ^2 X2 Q% {1 _: h
- 13 //min, the last value+ G, J+ F5 `, _8 M& Z( C# b
- 14 else if(index>= ITEM_NUM(ntcDATA)){
7 v/ T, ]' U5 s! L- F( } - 15 temperature = 10*(TEMP_HEADER_VALUE + ITEM_NUM(ntcDATA));/ G! z1 p6 w7 F# _* `" i
- 16 }* S7 H* a' ~! D. I
- 17 else{; f2 P F" n# z! n6 k1 U
- 18 //just get integer number* h% p9 J' ]6 c, n. Q, \. R) O8 N
- 19 // temperature = TEMP_HEADER_VALUE + index;
- K0 \0 m+ Z! h; ^# ~$ T) b - 20" \4 f6 K0 n# i- X- I
- 21 //get approximation data
+ T( \- G6 {$ C# ]2 N - 22 temperature = TEMP_HEADER_VALUE + index;
% J: k) ]9 E- |! I5 ? - 23
- J* G/ h% z$ B) X - 24 //at middle0 Z4 i) m' v8 T( r
- 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 }
# y2 }( J" p- v* i - 272 t2 ]$ r5 T& s, j% c' H; L$ x
- 28 return temperature;
$ D0 {/ r& I' E# ` - 29
( I6 G- O* t) u$ n U- L' Y - 30}
复制代码 " {: E4 ^# ^% g+ x6 m' |; b/ O
7 X3 Q3 y' t7 U6 h5 m/ t& F5 I
表格中的温度是1度进行变化的,如果需要稍微精确的,这里在1度中间的值近似看做线性进行计算; 这里为了减小计算误差,先对其扩大十倍计算,显示时候再转为小数: - 1uint16_t adc = adc_sample();# G" q( ?% q$ V$ V' Z9 c3 Q
- 2
: j+ Z( r+ v2 M7 v; I ^ - 3int16_t temp_int = ntc2tem(adc);
& Z3 {" @9 S8 U0 ?) l! _$ s" L( G - 4float temp = temp_int/10.0;* h& u; a$ v2 U8 E& I; x
- 5- G6 H( W1 K- G, _7 n' d# h0 L8 |
- 6printf("adc: %d, temp: %.1f\r\n",adc, temp);
复制代码
7 F5 y1 L' W+ c' X# [3 P- ?% Z w3 连接硬件并测试& y: Z, ?0 N4 }1 O( X1 v
3.1 连接硬件按照如下图,将NTC和10K电阻连接到PA0脚:
0 q: K4 t) `+ \4 N) Z0 y7 L# w" i) [+ u9 t- d
3.2 测试打开串口,当手放在NTC上可以看到温度变化: ( H5 ?% e9 s" Y
$ V3 |0 b/ r4 `
I6 E9 f5 J$ h7 _ |