Skip to content

由 sujingliang 贡献,Ai-Thinker 进行整理

【Ai-WB2评测】ADC采集NTC热敏电阻通过BLE上报温度

通过NTC(负温度系数)热敏电阻采集温度是一种低成本且广泛应用的方案,尤其适合对精度要求不高、预算有限的场景。

NTC热敏电阻的特点

负温度系数:电阻值随温度升高而降低(非线性关系)。

低成本:单价通常仅几元人民币,远低于数字温度传感器(如DS18B20)。

灵敏度高:在低温区电阻变化更显著,适合检测微小温度变化。

非线性响应:需通过公式或查表法进行线性化处理。

用Ai-WB2搭建电路

  • 原理:NTC与固定电阻组成分压电路,ADC读取分压值后转换为电阻,再通过公式计算温度。
  • 固定电阻选择:建议与NTC在目标温度范围内的中值电阻匹配(例如NTC在25℃时为10kΩ,则选10kΩ固定电阻) 这里分压电阻选择了51K,是因为之前错误地以为手头的NTC是50K的,后来发现是150K的,就将错就错了。就是要注意查表法需要按照150K+50K分压计算对应关系。

实际电路:

软件部分

在applications\ble_slave例程基础上修改

1、增加temperature.h处理ADC采集NTC数据

📜 点击展开完整代码
java
#ifndef __TEMPERATURE_H__
#define __TEMPERATURE_H__

//temperature.h

void

adc_temp_init
(
void
)
;

int

get_temp_value
(
void
)
;

int

get_temperature
(
void
)
;

#endif
📜 点击展开完整代码
c
void adc_temp_init(void);//初始化ADC

int get_temp_value(void);//采集ADC数值(0-4095)

int get_temperature(void);//将ADC数值转化为温度

2、temperature.c实现

📜 点击展开完整代码
java
//

#include <stdio.h>
#include <string.h>
#include <FreeRTOS.h>
#include <task.h>
#include <hosal_adc.h>
#include <blog.h>

#define GPIO_ADC_PIN
11

#define ADC_CHANNEL
10

const unsigned
int
 tempTable[][
2
] = {
 {-
30
,
114
},
 {-
29
,
121
},
 {-
28
,
128
},
 {-
27
,
136
},
 {-
26
,
144
},
 {-
25
,
153
},
 {-
24
,
162
},
 {-
23
,
172
},
 {-
22
,
182
},
 {-
21
,
192
},
 {-
20
,
203
},
 {-
19
,
215
},
 {-
18
,
227
},
 {-
17
,
240
},
 {-
16
,
253
},
 {-
15
,
267
},
 {-
14
,
281
},
 {-
13
,
296
},
 {-
12
,
312
},
 {-
11
,
328
},
 {-
10
,
345
},
 {-
9
,
362
},
 {-
8
,
381
},
 {-
7
,
400
},
 {-
6
,
419
},
 {-
5
,
440
},
 {-
4
,
461
},
 {-
3
,
483
},
 {-
2
,
505
},
 {-
1
,
529
},
 {
0
,
553
},
 {
1
,
577
},
 {
2
,
603
},
 {
3
,
629
},
 {
4
,
656
},
 {
5
,
684
},
 {
6
,
713
},
 {
7
,
742
},
 {
8
,
772
},
 {
9
,
803
},
 {
10
,
835
},
 {
11
,
867
},
 {
12
,
900
},
 {
13
,
934
},
 {
14
,
968
},
 {
15
,
1003
},
 {
16
,
1039
},
 {
17
,
1075
},
 {
18
,
1112
},
 {
19
,
1149
},
 {
20
,
1187
},
 {
21
,
1225
},
 {
22
,
1264
},
 {
23
,
1304
},
 {
24
,
1343
},
 {
25
,
1383
},
 {
26
,
1424
},
 {
27
,
1465
},
 {
28
,
1506
},
 {
29
,
1547
},
 {
30
,
1588
},
 {
31
,
1630
},
 {
32
,
1672
},
 {
33
,
1713
},
 {
34
,
1755
},
 {
35
,
1797
},
 {
36
,
1839
},
 {
37
,
1881
},
 {
38
,
1922
},
 {
39
,
1964
},
 {
40
,
2005
},
 {
41
,
2047
},
 {
42
,
2088
},
 {
43
,
2128
},
 {
44
,
2169
},
 {
45
,
2209
},
 {
46
,
2249
},
 {
47
,
2288
},
 {
48
,
2327
},
 {
49
,
2366
},
 {
50
,
2404
},
 {
51
,
2442
},
 {
52
,
2479
},
 {
53
,
2516
},
 {
54
,
2552
},
 {
55
,
2588
},
 {
56
,
2623
},
 {
57
,
2658
},
 {
58
,
2692
},
 {
59
,
2726
},
 {
60
,
2759
},
 {
61
,
2791
},
 {
62
,
2823
},
 {
63
,
2854
},
 {
64
,
2885
},
 {
65
,
2915
},
 {
66
,
2945
},
 {
67
,
2973
},
 {
68
,
3002
},
 {
69
,
3029
},
 {
70
,
3056
},
 {
71
,
3083
},
 {
72
,
3109
},
 {
73
,
3134
},
 {
74
,
3159
},
 {
75
,
3183
},
 {
76
,
3207
},
 {
77
,
3230
},
 {
78
,
3252
},
 {
79
,
3274
},
 {
80
,
3296
},
 {
81
,
3317
},
 {
82
,
3337
},
 {
83
,
3357
},
 {
84
,
3376
},
 {
85
,
3395
},
 {
86
,
3414
},
 {
87
,
3432
},
 {
88
,
3449
},
 {
89
,
3466
},
 {
90
,
3483
},
 {
91
,
3499
},
 {
92
,
3515
},
 {
93
,
3530
},
 {
94
,
3545
},
 {
95
,
3559
},
 {
96
,
3573
},
 {
97
,
3587
},
 {
98
,
3600
},
 {
99
,
3613
},
 {
100
,
3626
},
 {
101
,
3638
},
 {
102
,
3650
},
 {
103
,
3662
},
 {
104
,
3673
},
 {
105
,
3684
},
 {
106
,
3695
},
 {
107
,
3705
},
 {
108
,
3715
},
 {
109
,
3725
},
 {
110
,
3735
},
 {
111
,
3744
},
 {
112
,
3753
},
 {
113
,
3762
},
 {
114
,
3771
},
 {
115
,
3779
},
 {
116
,
3787
},
 {
117
,
3795
},
 {
118
,
3802
},
 {
119
,
3810
},
 {
120
,
3817
},
 {
121
,
3824
},
 {
122
,
3831
},
 {
123
,
3838
},
 {
124
,
3844
},
 {
125
,
3850
},
 {
126
,
3856
},
 {
127
,
3862
},
 {
128
,
3868
},
 {
129
,
3874
},
 {
130
,
3879
},
 {
131
,
3885
},
 {
132
,
3890
},
 {
133
,
3895
},
 {
134
,
3900
},
 {
135
,
3904
},
 {
136
,
3909
},
 {
137
,
3914
},
 {
138
,
3918
},
 {
139
,
3922
},
 {
140
,
3926
},
 {
141
,
3930
},
 {
142
,
3934
},
 {
143
,
3938
},
 {
144
,
3942
},
 {
145
,
3946
},
 {
146
,
3949
},
 {
147
,
3952
},
 {
148
,
3956
},
 {
149
,
3959
},
 {
150
,
3962
},
 {
151
,
3965
},
 {
152
,
3968
},
 {
153
,
3971
},
 {
154
,
3974
},
 {
155
,
3977
},
 {
156
,
3980
},
 {
157
,
3982
},
 {
158
,
3985
},
 {
159
,
3987
},
 {
160
,
3990
},
 {
161
,
3992
},
 {
162
,
3994
},
 {
163
,
3997
},
 {
164
,
3999
},
 {
165
,
4001
},
 {
166
,
4003
},
 {
167
,
4005
},
 {
168
,
4007
},
 {
169
,
4009
},
 {
170
,
4011
},
 {
171
,
4013
},
 {
172
,
4015
},
 {
173
,
4016
},
 {
174
,
4018
},
 {
175
,
4020
},
 {
176
,
4021
},
 {
177
,
4023
},
 {
178
,
4024
},
 {
179
,
4026
},
 {
180
,
4027
},
 {
181
,
4029
},
 {
182
,
4030
},
 {
183
,
4032
},
 {
184
,
4033
},
 {
185
,
4034
},
 {
186
,
4035
},
 {
187
,
4037
},
 {
188
,
4038
},
 {
189
,
4039
},
 {
190
,
4040
},
 {
191
,
4041
},
 {
192
,
4043
},
 {
193
,
4044
},
 {
194
,
4045
},
 {
195
,
4046
},
 {
196
,
4047
},
 {
197
,
4048
},
 {
198
,
4049
},
 {
199
,
4050
},
 {
200
,
4050
},
 {
201
,
4051
},
 {
202
,
4052
},
 {
203
,
4053
},
 {
204
,
4054
},
 {
205
,
4055
},
 {
206
,
4055
},
 {
207
,
4056
},
 {
208
,
4057
},
 {
209
,
4058
},
 {
210
,
4058
},
 {
211
,
4059
},
 {
212
,
4060
},
 {
213
,
4061
},
 {
214
,
4061
},
 {
215
,
4062
},
 {
216
,
4062
},
 {
217
,
4063
},
 {
218
,
4064
},
 {
219
,
4064
},
 {
220
,
4065
},
 {
221
,
4065
},
 {
222
,
4066
},
 {
223
,
4067
},
 {
224
,
4067
},
 {
225
,
4068
},
 {
226
,
4068
},
 {
227
,
4069
},
 {
228
,
4069
},
 {
229
,
4070
},
 {
230
,
4070
},
 {
231
,
4070
},
 {
232
,
4071
},
 {
233
,
4071
},
 {
234
,
4072
},
 {
235
,
4072
},
 {
236
,
4073
},
 {
237
,
4073
},
 {
238
,
4073
},
 {
239
,
4074
},
 {
240
,
4074
},
 };

hosal_adc_dev_t

adc0

=
 {
    .cb = NULL,
    .config = {
        .mode = HOSAL_ADC_ONE_SHOT,
        .pin = GPIO_ADC_PIN,
        .sampling_freq =
340
,
    },
    .dma_chan =
0
,
    .p_arg = NULL,
    .port =
0
,
};

void

adc_temp_init
(
void
)

{
    hosal_adc_init(&adc0);
    hosal_adc_add_channel(&adc0, ADC_CHANNEL);
}

int

get_temp_value
(
void
)

{

int

ret

=
 hosal_adc_value_get(&adc0, ADC_CHANNEL,
100
);
    blog_info(
"ADC = %ld \r\n"
, ret);

return
 ret;

}

int

get_temperature
(
void
)

{

int
 adc_value;
    const unsigned
int

tableSize

=
 sizeof(tempTable) / sizeof(tempTable[
0
]);
    unsigned
int
 i;

    adc_value=get_temp_value();

// 边界检查(注意与采样NTC时方向相反)

if
(adc_value <= tempTable[
0
][
1
]) {

return
 tempTable[
0
][
0
];
// 低于最低温度-30℃

    }

if
(adc_value >= tempTable[tableSize-
1
][
1
]) {

return
 tempTable[tableSize-
1
][
0
];
// 高于最高温度50℃

    }

// 查表(ADC值随温度升高而增大)

for
(i =
0
; i < tableSize-
1
; i++) {

if
(adc_value >= tempTable[i][
1
] && adc_value < tempTable[i+
1
][
1
]) {

// 线性插值计算温度

return
 tempTable[i][
0
] + (
int
)((
float
)(tempTable[i+
1
][
0
] - tempTable[i][
0
]) *
                   (
float
)(adc_value - tempTable[i][
1
]) /
                   (
float
)(tempTable[i+
1
][
1
] - tempTable[i][
1
]));
        }
    }

return

0xFFFF
;
// 错误代码(正常情况不会执行到这里)

}

3、main.c修改

📜 点击展开完整代码
java
void

main
()

{
    bl_sys_init();

    adc_temp_init();
    pwm_led_init();

    puts(
"[OS] proc_main_entry task...\r\n"
);
    xTaskCreate(TaskUart,
"TaskUart"
,
2048
, NULL,
15
, NULL);
    xTaskCreate(TaskTemp,
"TempAdc"
,
1024
, NULL,
15
, NULL);
    xTaskCreate(proc_main_entry, (
char
 *)
"main_entry"
,
1024
, NULL,
15
, NULL);
}

增加adc_temp_init();//ADC初始化

RTOS建立一个新的TASK,用于处理温度采集:

xTaskCreate(TaskTemp, "TempAdc", 1024, NULL, 15, NULL);

4、TaskTemp任务

📜 点击展开完整代码
java
void

TaskTemp
(
void
 *param)

{

int
 tempval;
    uint8_t data[
5
] = {
0x4e
,
0x4f
,
0x60
,
0x01
,
0x00
};

while
 (
1
)
    {
        tempval=get_temperature();
        data[
4
]=(uint8_t)tempval;
        UUID1_SendNotify(strlen((
char
 *)data), data);
        vTaskDelay(
1000
);
    }

}

通过get_temperature()采集到温度数据

调用UUID1_SendNotify函数发送数据到已订阅UUID1的BLE主机设备(手机)

数据格式为

固定数据头固定数据头标识(表示后面是温度)未知温度值
0x4e0x4f0x600x010x00

手机运行APP(友商软件,非安信可)

搜索BLE

连接后可以看到上报的温度数据

Released under the MIT License. Build Time 2026-09-11 14:52:23