外观
四、代码介绍
总体概述
项目使用STM32F103C8T6作为主控芯片,代码使用HAL库、STM32Cubemx进行图形化配置+STM32CubeMx进行编译,用户仅需关注逻辑代码实现即可。
该项目代码并不复杂,使用功能仅有SPI、ADC、GPIO输入输出三个模块;处理的重点在屏幕数据的显示、ADC数据采集与校准、电压、电阻等数据的计算;
电压数据计算&显示
屏幕驱动不做介绍,移植厂商给的驱动即可。重点关注电压数据显示与计算,将两个通道的电压值读取出来、此外,还需要读取1.65V以及内部参考电压vref电压值进行辅助计算;如果某一个通道电压值有较大波动,则代表此时输入在该通道上,后续根据分压电阻值,反推输入电压即可;需注意,由于运放本身的输入失调电压、输入偏置电流以及电阻精度等影响,需要进行校准,校准的操作是:在没有外部输入的情况下,将红表笔连接到GND,使用一个万用表测量+1.65测试点和对应ADC引脚的测试点,看电压差为多少,在实际计算中,需要先减去这一部分误差否则会有较大误差;
C
/*
* Function Content: show volatge value;
* notic offset_vol need manual measurement,
* The output voltage value of the follower when unloaded
* Function Parameter: lcd_interface *lcd_t,uint16_t *adc_buf,uint8_t range
* Return Value: null
* notice: offset_val is vol input connect to GND offset val,
* No remove of levitate noise!!!
*/
static void show_volatge_page(lcd_interface *lcd_t,uint16_t *adc_buf,uint8_t *range)
{
char show_data[32];
uint16_t vol_color;
float vol1_val = 0.0f,vol2_val = 0.0f,ref165_vol = 0.0f,offset_val=0.0f,filter_vol = 0.0f;
uint16_t vin_vol = 0;
uint8_t sign = 0;
if(adc_dma_done != 1){
return;
}
vol1_sum = vol1_sum >> 6;
vol2_sum = vol2_sum >> 6;
ref_165_sum = ref_165_sum >> 6;
vref_sum = vref_sum >> 6;
vol1_val = vol1_sum * 1.0f / vref_sum * 1.21f;
vol2_val = vol2_sum * 1.0f / vref_sum * 1.21f;
ref165_vol = ref_165_sum * 1.0f / vref_sum * 1.21f;
reset_adc_gather(adc_buf);
lcd_showString(lcd_t,12,2,(uint8_t *)"Mode:Vol",WHITE, BLACK, 16, 0);
if(((old_vol1_val + 0.1f) <= vol1_val) || ((old_vol1_val - 0.1f) >= vol1_val)){
old_vol1_val = vol1_val;
*range = VOL_RANGE_0_5;
}else if(((old_vol2_val + 0.1f) <= vol2_val) || ((old_vol2_val - 0.1f) >= vol2_val)){
old_vol2_val = vol2_val;
*range = VOL_RANGE_5_15;
}
if(*range == VOL_RANGE_0_5){
offset_val = 0.005f;
lcd_showString(lcd_t,100,2,(uint8_t *)"0--5V",
LGRAY, BLACK, 16, 0);
if(vol1_val >= ref165_vol){
filter_vol = (vol1_val - ref165_vol - offset_val) * 13.3f / 3.3f * 1000;
sign = 1;
}else{
filter_vol = (ref165_vol - vol1_val + offset_val) * 13.3f / 3.3f * 1000;
sign = 0;
}
}
else{
offset_val = 0.005f;
lcd_showString(lcd_t,100,2,(uint8_t *)"0-15V",LGRAY, BLACK, 16, 0);
if(vol2_val >= ref165_vol){
filter_vol = (vol2_val - ref165_vol - offset_val) * 11.0f * 1000;
sign = 1;
}else{
filter_vol = (ref165_vol - vol2_val + offset_val) * 11.0f * 1000;
sign = 0;
}
}
vin_vol = Moving_Average(filter_vol);
if (vin_vol < 5000) {
vol_color = GREEN;
} else if (vin_vol < 10000) {
vol_color = YELLOW;
} else {
vol_color = RED;
}
if(sign == 0){
lcd_showString(lcd_t,8,48,(uint8_t *)"-", LGRAY, BLACK, 32, 0);
}else{
lcd_showString(lcd_t,8,48,(uint8_t *)"+", LGRAY, BLACK, 32, 0);
}
snprintf(show_data,sizeof(show_data),"%2d.%03d",vin_vol/1000, vin_vol%1000);
lcd_showString(lcd_t,24,48,(uint8_t *)show_data,
vol_color, BLACK, 32, 0);
lcd_showString(lcd_t,120,48,(uint8_t *)"V",LGRAY, BLACK, 32, 0);
lcd_showString(lcd_t,0,110,
(uint8_t *)"0-5V<---sw--->5V-15V",DARKGRAY, BLACK, 16, 0);
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
电阻数据计算&显示
屏幕驱动不做介绍,移植厂商给的驱动即可。重点关注电阻数据显示与计算,将两个通道的电压值读取出来、此外,还需要读取2.30V、1.65V以及内部参考电压vref电压值进行辅助计算;如果某一个通道电压值有较大波动,则代表此时输入在该通道上,如果是大电阻测量,后续根据分压电阻值,反推输入电阻即可,如果是恒流源测电阻,则已知电流&负载电压,反推负载电阻即可;若需要更加准确的测量,可以使用高精度电阻进行测量后校准,目前代码中没有进行;
C
static void show_resistance_page(lcd_interface *lcd_t,uint16_t *adc_buf,uint8_t *range)
{
char show_data[32];
uint16_t res_color = 0;
uint32_t resistance = 0;
float ref165_vol = 0,res1_in = 0,res2_in,ref230_vol = 0;
float current_val = 0;
if(adc_dma_done != 1){
return;
}
ref_165_sum = ref_165_sum >> 6;
ref_230_sum = ref_230_sum >> 6;
res_in1_sum = res_in1_sum >> 6;
res_in2_sum = res_in2_sum >> 6;
vref_sum = vref_sum >> 6;
ref165_vol = ref_165_sum * 1.0f / vref_sum * 1.21f;
res1_in = res_in1_sum * 1.0f / vref_sum * 1.21f;
res2_in = res_in2_sum * 1.0f / vref_sum * 1.21f;
ref230_vol = ref_230_sum * 1.0f / vref_sum * 1.21f;
reset_adc_gather(adc_buf);
current_val = (ref165_vol * 2.0f - ref230_vol) / 1000.0f;
lcd_showString(lcd_t,12,2,(uint8_t *)"Mode:Res",WHITE, BLACK, 16, 0);
if(res1_in < 3.30f){
*range = RES_RANGE_0_1;
}else{
*range = RES_RANGE_1_100;
}
if(*range == RES_RANGE_0_1){
lcd_showString(lcd_t,100,2,(uint8_t *)"0K---1K",LGRAY, BLACK, 16, 0);
resistance = (res1_in / current_val) + 0.5f;
res_color = WHITE;
if(resistance > 1000 && resistance<= 3000){
HAL_GPIO_WritePin(BEEP_GPIO_Port, BEEP_Pin, GPIO_PIN_SET);
HAL_Delay(50);
HAL_GPIO_WritePin(BEEP_GPIO_Port, BEEP_Pin, GPIO_PIN_RESET);
}
else if(resistance > 3000)
{
resistance = 0;
HAL_GPIO_WritePin(BEEP_GPIO_Port, BEEP_Pin, GPIO_PIN_RESET);
}
}else{
lcd_showString(lcd_t,100,2,(uint8_t *)"1K-100K",
LGRAY, BLACK, 16, 0);
resistance = (10000.0f) * (res2_in / ((ref165_vol * 2.0f) - res2_in))+0.5f;
if (resistance < 47000) {
res_color = ORANGE;
} else {
res_color = YELLOW;
}
if((resistance > 100000) && (resistance <= 150000)){
HAL_GPIO_WritePin(BEEP_GPIO_Port, BEEP_Pin, GPIO_PIN_SET);
HAL_Delay(50);
HAL_GPIO_WritePin(BEEP_GPIO_Port, BEEP_Pin, GPIO_PIN_RESET);
}
else if(resistance > 150000){
resistance = 0;
HAL_GPIO_WritePin(BEEP_GPIO_Port, BEEP_Pin, GPIO_PIN_RESET);
}
}
resistance = Moving_Average_res(resistance);
if (resistance < 1000) {
snprintf(show_data, sizeof(show_data),
"%6ld", resistance);
} else {
snprintf(show_data, sizeof(show_data),
"%3ld.%02ld",
resistance / 1000,
(resistance % 1000) / 10);
}
lcd_showString(lcd_t,24,48,(uint8_t *)show_data,
res_color, BLACK, 32, 0);
if (resistance < 1000) {
lcd_showString(lcd_t,120,48,(uint8_t *)"R",LGRAY, BLACK, 32, 0);
}else {
lcd_showString(lcd_t,120,48,(uint8_t *)"K",LGRAY, BLACK, 32, 0);
}
lcd_showString(lcd_t,0,110,
(uint8_t *)"1k-100K<--sw-->0R-1K",DARKGRAY, BLACK, 16, 0);
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
蜂鸣档数据计算&显示
屏幕驱动不做介绍,移植厂商给的驱动即可。蜂鸣档/二极管档其实就是使用恒流源测电阻电路,当测量得到负载电阻值小于一个阈值时,认为其是通路;二极管当则是直接测量电压即可得到二极管压降;
C
static void show_beep_page(lcd_interface *lcd_t,uint16_t *adc_buf,uint8_t *range)
{
char show_data[32];
uint16_t res_color = 0;
uint32_t resistance = 0;
float ref165_vol = 0,res1_in = 0,ref230_vol = 0;
float current_val = 0;
if(adc_dma_done != 1){
return;
}
ref_165_sum = ref_165_sum >> 6;
ref_230_sum = ref_230_sum >> 6;
res_in1_sum = res_in1_sum >> 6;
res_in2_sum = res_in2_sum >> 6;
vref_sum = vref_sum >> 6;
ref165_vol = ref_165_sum * 1.0f / vref_sum * 1.21f;
res1_in = res_in1_sum * 1.0f / vref_sum * 1.21f;
//res2_in = res_in2_sum * 1.0f / vref_sum * 1.21f;
ref230_vol = ref_230_sum * 1.0f / vref_sum * 1.21f;
reset_adc_gather(adc_buf);
current_val = (ref165_vol * 2.0f - ref230_vol) / 1000.0f;
lcd_showString(lcd_t,12,2,(uint8_t *)"Mode:Buz",WHITE, BLACK, 16, 0);
if(res1_in < 3.30f){
*range = RES_RANGE_0_1;
}else{
*range = RES_RANGE_1_100;
}
if(*range == RES_RANGE_0_1){
resistance = res1_in / current_val;
res_color = WHITE;
if(resistance > 1000){
resistance = 9999;
}
}else{
resistance = 9999;
}
resistance = Moving_Average_res(resistance);
if(resistance <= 15){
snprintf(show_data, sizeof(show_data),"%6ld", resistance);
lcd_showString(lcd_t,24,48,(uint8_t *)show_data,res_color, BLACK, 32, 0);
lcd_showString(lcd_t,120,48,(uint8_t *)"R",LGRAY, BLACK, 32, 0);
HAL_GPIO_WritePin(BEEP_GPIO_Port, BEEP_Pin, GPIO_PIN_SET);
}
else if (resistance <= 1000) {
snprintf(show_data, sizeof(show_data),"%6ld", resistance);
lcd_showString(lcd_t,24,48,(uint8_t *)show_data,res_color, BLACK, 32, 0);
lcd_showString(lcd_t,120,48,(uint8_t *)"R",
LGRAY, BLACK, 32, 0);
HAL_GPIO_WritePin(BEEP_GPIO_Port, BEEP_Pin, GPIO_PIN_RESET);
}
else{
resistance = 0;
snprintf(show_data, sizeof(show_data),
"%6ld", resistance);
lcd_showString(lcd_t,24,48,(uint8_t *)show_data,res_color, BLACK, 32, 0);
lcd_showString(lcd_t,88,48,(uint8_t *)"OL.",LGRAY, BLACK, 32, 0);
HAL_GPIO_WritePin(BEEP_GPIO_Port, BEEP_Pin, GPIO_PIN_RESET);
}
lcd_showString(lcd_t,0,110,
(uint8_t *)"1k-100K<--sw-->0R-1K",DARKGRAY, BLACK, 16, 0);
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
滤波
考虑到外部噪声、以及测量时的不稳定因素会导致数据突变,这里加入滑动平均滤波对数据进行处理;
C
#define FILTER_N 16
#define FILTER_RES_N 16
static uint16_t filter_buf[FILTER_N] = {0};
static uint32_t filter_sum = 0;
static uint8_t filter_index = 0;
static uint32_t filter_buf_res[FILTER_RES_N] = {0};
static uint32_t filter_sum_res = 0;
static uint8_t filter_index_res = 0;
uint16_t Moving_Average(uint16_t new_value)
{
filter_sum -= filter_buf[filter_index]; // Subtract the old value
filter_buf[filter_index] = new_value; // Store new value
filter_sum += new_value; // Add new values
filter_index++;
if(filter_index >= FILTER_N)
filter_index = 0;
return filter_sum / FILTER_N;
}
uint32_t Moving_Average_res(uint32_t new_value)
{
filter_sum_res -= filter_buf_res[filter_index_res]; // Subtract the old value
filter_buf_res[filter_index_res] = new_value; // Store new value
filter_sum_res += new_value; // Add new values
filter_index_res++;
if(filter_index_res >= FILTER_RES_N)
filter_index_res = 0;
return filter_sum_res / FILTER_RES_N;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40