外观
综合案例
思维导图
数控直流电源的综合案例相对来说是比较简单的,总体可分为两个部分,显示UI与逻辑功能,UI的显示主要围绕电压、电流的设置以及实际输出的电压、电流显示;逻辑控制针对输出电压值、保护电流值、开关状态以及实际电压电流值来进行。
功能实现
在前面的各案例中,已经带大家过了非常多遍工程,以及相关外设代码的编写,综合案例就不再进行重复性的操作了,把重点放在实际代码中去。在综合案例中,设置的参数有输出电压值、保护电流值、开关状态、实际电压值、实际电流值等等,这些参数可以考虑使用一个结构体来进行汇总,否则单个变量是非常杂乱的。
显示UI设置
静态UI主要是显示标题、文本等不需要频繁更新的内容,稍微麻烦的点是需要计算坐标点,使显示文本尽量居中美观;这里没有使用汉字。
静态UI函数
C
/*
函数内容:默认显示UI
*/
void defaultShowUI(void)
{
char Data[16]={0};
OLED_DrawLine(0,20,128,20,1);
OLED_DrawLine(0,40,128,40,1);
OLED_DrawLine(65,0,65,40,1);
OLED_ShowString(0,1,(uint8_t *)"Set Vol:",16,1);
switch(systemparam.setVolValue)
{
case VOL_1V8:
OLED_ShowString(80,1,(uint8_t *)" 1.8V",16,1);
break;
case VOL_3V3:
OLED_ShowString(80,1,(uint8_t *)" 3.3V",16,1);
break;
case VOL_5V0:
OLED_ShowString(80,1,(uint8_t *)" 5.0V",16,1);
break;
case VOL_9V0:
OLED_ShowString(80,1,(uint8_t *)" 9.0V",16,1);
break;
case VOL_12V:
OLED_ShowString(80,1,(uint8_t *)"12.0V",16,1);
break;
default:
OLED_ShowString(80,1,(uint8_t *)" 5.0V",16,1);
break;
}
OLED_ShowString(0,21,(uint8_t *)"Set Cur:",16,1);
sprintf(Data,"%4dmA",systemparam.protectValue);
OLED_ShowString(72,21,(uint8_t *)Data,16,1);
OLED_ShowString(28,41,(uint8_t *)"Power OFF",16,0);
OLED_Refresh();
}
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
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
除了静态UI外,当按键按下时,我们需要知道当前设置的参数位置,此时可以通过反色显示与正常显示来进行,当设置按键按下时,将对应的位置设置为反色显示,其余为正常显示,通过这种方式,可以实现光标移动的效果。
设置正反显函数
C
void setShowUI(uint8_t page, uint8_t mode,uint8_t isRefresh)
{
char Data[16]={0};
switch(page)
{
case POWER_PAGE:
if(systemparam.isOpen == DISABLE){
OLED_ShowString(28,41,(uint8_t *)"Power OFF",16,mode);
}
else{
OLED_ShowString(28,41,(uint8_t *)"Power ON ",16,mode);
}
break;
case VOL_PAGE:
switch(systemparam.setVolValue)
{
case VOL_1V8:
OLED_ShowString(80,1,(uint8_t *)"1.8V ",16,mode);
break;
case VOL_3V3:
OLED_ShowString(80,1,(uint8_t *)"3.3V ",16,mode);
break;
case VOL_5V0:
OLED_ShowString(80,1,(uint8_t *)"5.0V ",16,mode);
break;
case VOL_9V0:
OLED_ShowString(80,1,(uint8_t *)"9.0V ",16,mode);
break;
case VOL_12V:
OLED_ShowString(80,1,(uint8_t *)"12.0V",16,mode);
break;
default:
OLED_ShowString(80,1,(uint8_t *)"5.0V ",16,mode);
break;
}
break;
case CUR_PAGE:
sprintf(Data,"%4dmA",systemparam.protectValue);
OLED_ShowString(72,21,(uint8_t *)Data,16,mode);
break;
}
if(isRefresh == ENABLE){
OLED_Refresh();
}
}
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
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
最后还有一个动态UI,当开关打开时,此时屏幕应该每隔一段时间刷新实际输出的电压与电流值
动态UI函数
C
void CurrentShowUI(float volValue,uint16_t curValue)
{
char Data[16]={0};
OLED_ShowString(0,1,(uint8_t *)"Now Vol:",16,1);
sprintf(Data," %.1fV",volValue);
OLED_ShowString(80,1,(uint8_t *)Data,16,1);
OLED_ShowString(0,21,(uint8_t *)"Now Cur:",16,1);
sprintf(Data,"%4dmA",curValue);
OLED_ShowString(72,21,(uint8_t *)Data,16,1);
OLED_ShowString(28,41,(uint8_t *)"Power ON ",16,0);
OLED_Refresh();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
逻辑功能
数控直流电源有三个按键,我的设想是一个设置按键,另外两个是确认按键,当按下设置按键时,切换到电压、电流、以及开关设置区域,当按下确认按键时,进行电压、电流向上向下设置,如果是处于开关设置区域,则打开或关闭开关。这些操作均是在按键处理函数中完善。
按键处理函数
C
void KeyHandle(uint8_t keyValue)
{
switch(keyValue)
{
case SW1PRESS:
{
if(systemparam.isOpen == DISABLE){
setShowUI(systemparam.currentPage,normal_display,DISABLE);
switch(systemparam.currentPage)
{
case POWER_PAGE:
systemparam.currentPage = VOL_PAGE;
break;
case VOL_PAGE:
systemparam.currentPage = CUR_PAGE;
break;
case CUR_PAGE:
systemparam.currentPage = POWER_PAGE;
break;
default:
systemparam.currentPage = POWER_PAGE;
break;
}
setShowUI(systemparam.currentPage,reverse_display,ENABLE);
}
}
break;
case SW2PRESS:
{
switch(systemparam.currentPage)
{
case POWER_PAGE:
{
if(systemparam.isOpen == DISABLE){
OpenPowerSwitch(systemparam.setVolValue);
systemparam.isOpen = ENABLE;
CurrentShowUI(systemparam.volValue,systemparam.curValue);
}
else
{
ClosePowerSwitch();
systemparam.isOpen = DISABLE;
defaultShowUI();
}
}
break;
case VOL_PAGE:
{
switch(systemparam.setVolValue)
{
case VOL_1V8:
{
systemparam.setVolValue = VOL_3V3;
}
break;
case VOL_3V3:
{
systemparam.setVolValue = VOL_5V0;
}
break;
case VOL_5V0:
{
systemparam.setVolValue = VOL_9V0;
}
break;
case VOL_9V0:
{
systemparam.setVolValue = VOL_12V;
}
break;
case VOL_12V:
{
systemparam.setVolValue = VOL_1V8;
}
break;
default:
{
systemparam.setVolValue = VOL_5V0;
}
break;
}
setShowUI(systemparam.currentPage,reverse_display,ENABLE);
}
break;
case CUR_PAGE:
{
if(systemparam.protectValue <= 1400){
systemparam.protectValue = systemparam.protectValue + 100;
setShowUI(systemparam.currentPage,reverse_display,ENABLE);
}
}
break;
}
}
break;
case SW3PRESS:
{
switch(systemparam.currentPage)
{
case POWER_PAGE:
{
if(systemparam.isOpen == DISABLE){
OpenPowerSwitch(systemparam.setVolValue);
systemparam.isOpen = ENABLE;
CurrentShowUI(systemparam.volValue,systemparam.curValue);
}
else
{
ClosePowerSwitch();
systemparam.isOpen = DISABLE;
defaultShowUI();
}
}
break;
case VOL_PAGE:
{
switch(systemparam.setVolValue)
{
case VOL_1V8:
{
systemparam.setVolValue = VOL_12V;
}
break;
case VOL_3V3:
{
systemparam.setVolValue = VOL_1V8;
}
break;
case VOL_5V0:
{
systemparam.setVolValue = VOL_3V3;
}
break;
case VOL_9V0:
{
systemparam.setVolValue = VOL_5V0;
}
break;
case VOL_12V:
{
systemparam.setVolValue = VOL_9V0;
}
break;
default:
{
systemparam.setVolValue = VOL_5V0;
}
break;
}
setShowUI(systemparam.currentPage,reverse_display,ENABLE);
}
break;
case CUR_PAGE:
{
if(systemparam.protectValue >= 200){
systemparam.protectValue = systemparam.protectValue - 100;
setShowUI(systemparam.currentPage,reverse_display,ENABLE);
}
}
break;
}
}
break;
default:
break;
}
}
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
在主函数中,对按键进行扫描以及处理,若电源开关没有打开,则不去刷新页面,若打开,则每隔一段时间进行刷新,这里考虑到会有抖动,可以考虑进行滤波操作,比如取100个数,然后掐头去尾,对剩余的数进行平均值计算,这样得出的值比较准确。
有一个点需要注意,当读取的值超过设定的阈值后,应该立刻断开,而不是等待平均值计算,这样才能更好的进行响应,当然你也可以加入一个变量,比如超过了多少次就断开,防止电压电流抖动引起关断。
主函数函数
C
int main(void)
{
/* USER CODE BEGIN 1 */
uint8_t i = 0;
uint8_t keyValue = 0; //ɨ�谴��ֵ
uint16_t count = 0; //����ֵ
uint16_t protectVolValue = 0;//������ѹֵ
uint32_t tempValue = 0; //��ʱ��ȡadc����
float tempVolValue = 0; //��ʱ��ѹ����ֵ
float tempCurValue = 0; //��ʱ��������ֵ
float curCalibrationValue[100] = {0}; //����Уֵ
float volCalibrationValue[100] = {0}; //��ѹУֵ
float volTempCalibrationValue = 0,curTempCalibrationValue = 0; //��ʱ��ѹ����У��
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ADC_Init();
MX_I2C1_Init();
/* USER CODE BEGIN 2 */
HAL_ADCEx_Calibration_Start(&hadc); //����ADCУ
/* ϵͳ������ʼ�� */
systemparam.currentPage = POWER_PAGE; //Ĭ��ѡ���ڵ�Դ
systemparam.isOpen = DISABLE; //Ĭ�ϲ���
systemparam.setVolValue = VOL_5V0; //Ĭ�������ѹΪ5V
systemparam.protectValue = 500; //Ĭ������������500mA
systemparam.curValue = 0; //Ĭ�ϵ�ǰ����ֵΪ0
systemparam.volValue = 0; //Ĭ�ϵ�ǰ��ѹֵΪ0
OLED_Init();
defaultShowUI();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
keyValue = keyScanf();
KeyHandle(keyValue);
if(systemparam.isOpen == ENABLE)
{
tempValue = getAdcValue();
tempCurValue = (tempValue * 3.36f)/4095.0f;
tempCurValue = (tempCurValue / 100.0f / 0.01f * 1000);
curCalibrationValue[count] = tempCurValue;
tempValue = getAdcValue();
tempVolValue = (tempValue * 3.36f)/4095.0f;
tempVolValue = (13.3f * tempVolValue)/3.3f;
volCalibrationValue[count] = tempVolValue;
count++;
HAL_ADC_Stop(&hadc);
switch(systemparam.setVolValue)
{
case VOL_1V8:
protectVolValue = 1;
break;
case VOL_3V3:
protectVolValue = 2;
break;
case VOL_5V0:
protectVolValue = 4;
break;
case VOL_9V0:
protectVolValue = 8;
break;
case VOL_12V:
protectVolValue = 11;
break;
}
if((tempCurValue > systemparam.protectValue) || (tempVolValue < protectVolValue))
{
ClosePowerSwitch();
systemparam.isOpen = DISABLE;
defaultShowUI();
}
if(count >= 100){
bubble_sort(curCalibrationValue,100);
bubble_sort(volCalibrationValue,100);
for(i=10;i<90;i++)
{
volTempCalibrationValue = volTempCalibrationValue + volCalibrationValue[i];
curTempCalibrationValue = curTempCalibrationValue + curCalibrationValue[i];
}
systemparam.curValue = (uint16_t)(curTempCalibrationValue / 80.0f);
systemparam.volValue = volTempCalibrationValue / 80.0f;
CurrentShowUI(systemparam.volValue,systemparam.curValue);
count = 0;
volTempCalibrationValue = 0;
curTempCalibrationValue = 0;
memset(curCalibrationValue,0,100);
memset(volCalibrationValue,0,100);
}
}
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123