中科因仑“3+1”工程特种兵精英论坛
标题:
炎炎夏日需要一个清凉的地 - 自制水冷系统
[打印本页]
作者:
XJzy
时间:
2015-9-26 21:52
标题:
炎炎夏日需要一个清凉的地 - 自制水冷系统
前段时间接手了一个项目,所以DIY的进程有些停滞。实际编写的程序并没有多长时间,得益于Keil这个强大的IDE。能在第一次做51开发的时候,如此顺利的完成代码。
不多说废话了,说明下代码的具体思路。具体思路根据(六 控制系统原理图)进行拆分。分为温度显示部分、指示灯、温度获取和继电器操控部分。
LEDDisplay.c --- 温度显示模块
PilotLamp.c --- 指示灯控制模块
Temperature.c
12b20Temperature.asm --- 温度读取模块
Relays.c --- 继电器控制部分
系统主要控制的指数
1、读取温度的间隔时间
2、在调整温度的时候显示制冷控制温度时间。
3、当达到制冷温度设定值时,关闭或开启控制器一个缓冲量。防止在阀值的时候出现上下跳变问题。
4、控制调整温度的调节范围和调节量
开发中的主要阻力还是来至于温控IC。18B20的时序操作非常严格。如果要自己写调试太耗时间。因此直接从前辈取材,汇编是控制时序是最精确的,在网上找到的很多代码基本也是以汇编为主。我的代码是从杜洋老师已调整好读写时序的汇编代码改编而来。做了些小改动,把温度的精度提高到0.06°C。
另外一个让人抓狂的问题,没能找到根源解决。汇编和C混合开发中,变量的存储地址出现混乱。主程序部分的变量被汇编中的地址操作覆写,导致变量值被冲掉。不知道动了哪根筋,原来木问题后来才有这个问题。 -_-!!哭啊~~ 只能用一个方式规避这个问题,把被覆写变量的地址改为bdata段地址。修改后暂未发现程序中其他变量被覆写的问题。
主控
PCB设计
电路
板
调试的效果图
详细的系统小弟就不贴了,可以直接看发在PCB版中的内容。
贴出第一次写51代码^^。小弟有一点开发经验,只是软硬结合的这种模式属于第一个。
--------------------------------
1
#include <STC12C5A60S2.h>
2
3
#include
"
Pins.h
"
4
#include
"
LEDDisplay.h
"
5
#include
"
Temperature.h
"
6
#include
"
Relays.h
"
7
#include
"
PilotLamp.h
"
8
9
#define
uchar unsigned char
10
#define
uint unsigned int
11
12
//
获取温度的时间间隔
13
#define
TEMPGETCOUNT 5000
//
温度读取间隔, 500ms 读一次温度,即1秒读2次温度。
14
#define
CHANGINGCOUNT 20000
//
温度调控状态时会显示调控温度值,最长显示时间。
15
#define
CRITICALCOUNTDOWN 5
//
温度下临界跳变阀值
16
#define
CRITICALCOUNTUP 5
//
温度上临界跳变阀值
17
#define
CRITICALCOUNTERR 3
//
温度错误,3次关闭
18
#define
DEFAULTCRITICALTEMP 2500
//
默认跳变温度 25°C
19
#define
VALIDTEMPERATURE_MAX 3000
//
最大有效温度 30°C
20
#define
VALIDTEMPERATURE_MIN 2000
//
最小有效温度 20°C
21
#define
TEMPERATURESPET 50
//
0.5 °C 温度调整步长
22
23
24
#define
COOL_POWERALL 0xFF
//
全力运行
25
#define
COOL_MALAISE 0x00
//
萎靡~~~~~ 哇咔咔~~~
26
27
#define
KEYPRESS_LONG 200
//
按键长按计数,如一只按住不放
28
#define
KEYPRESS_SHORT 15
//
短按计数
29
30
31
#define
FOSC 1843200L
32
#define
T1MS (65536-FOSC/12/1000)
//
计时器工作频率 12T状态
33
34
35
uint
CriticalTempVal;
//
临界温度,跳变温度
36
uint
RealTempVal;
//
当前温度,获取一定次数时都
37
uint
ChangeCount;
//
临界切换计数
38
39
uchar RelayVal;
//
继电器状态控制位 从右到左 0x03(0000 0011) 那么第一第二个继电器打开。
40
//
指示灯状态
41
//
第一位 继电器工作状态,灯亮工作状态,灯灭停止制冷
42
//
第二位 是否为自动模式
43
//
第三位 温控器故障
44
//
0000 0111
45
uchar DirectLamp;
46
uchar bdata WorkStatus;
47
sbit InCritical = WorkStatus ^
0
;
//
临界状态
48
sbit InWorking = WorkStatus ^
1
;
//
工作状态
49
sbit InAuto = WorkStatus ^
2
;
//
自动模式
50
sbit InHandOn = WorkStatus ^
3
;
//
手动打开状态
51
sbit CanReadTemp = WorkStatus ^
4
;
//
是否允许读取温度
52
sbit InInitTemp = WorkStatus ^
5
;
//
温度读取是否在初始状态,解决第一次读取出现85°C的问题
53
sbit InChangingTemp = WorkStatus ^
6
;
//
在温度调整中
54
55
56
//
温度读取时间间隔,减少18B20的读取次数,
57
//
目的是为数码管能获得比较高的刷新频率,提高显示亮度。
58
//
每次读取会有固定占用时间,能看出每次读取会有变暗的闪烁情况。
59
uint
TempTimerSpace;
60
61
uint
TempChangingStatusSpace;
//
温度调控状态中
62
63
void
Init(
void
);
64
bit CanUpdateTemp(
void
);
65
void
UpdateTemperature(
void
);
66
void
ReadTemperature(
void
);
67
void
UpdateStatus(
void
);
68
void
InitTimer(
void
);
69
void
SearchKeys(
void
);
70
71
unsigned
int
GetCriticalTemperature(
void
);
72
//
void SaveCriticalTemperature(unsigned int);
73
74
75
//
按键
76
//
18 K3 17 K4 16 K5
77
sbit Key_Mode = P1 ^
1
;
78
sbit Key_CTDown = P1 ^
0
;
79
sbit Key_CTUp = P0 ^
0
;
80
81
//
enum KeyType (TNone=0, KTMode=1, KTCTDown=2, KTCTUp=4);
82
83
uchar KeyCount;
84
uchar KeyTypeVal;
85
86
#define
KEYTYPE_NONE 0
//
没有按键使用
87
#define
KEYTYPE_MODE 1
//
按下模式切换状态
88
#define
KEYTYPE_CTDOWN 2
//
按下温度切换状态
89
#define
KEYTYPE_CTUP 4
//
按下温度切换状态
90
91
92
void
main()
93
{
94
Init();
95
while
(
1
){
96
if
(CanReadTemp)
97
ReadTemperature();
98
99
SearchKeys();
100
UpdateStatus();
101
UpdateRelays(RelayVal);
102
103
if
(!
InChangingTemp)
104
DisplayTemperature(RealTempVal);
105
else
106
DisplayTemperature(CriticalTempVal);
107
108
DisplayPilotLamp(DirectLamp);
109
}
110
}
111
112
void
Init(
void
){
113
WorkStatus =
0x00
;
114
InAuto =
1
;
//
默认自动模式
115
116
KeyCount =
0
;
117
KeyTypeVal =
KEYTYPE_NONE;
118
RealTempVal =
DEFAULTCRITICALTEMP;
119
CriticalTempVal =
GetCriticalTemperature();
120
121
InitTimer();
122
InitPilotLamp();
123
InitView();
124
InitTemperature();
125
InitRealys();
126
}
127
128
void
SearchKeys(
void
){
129
//
模式切换
130
if
(Key_Mode ==
0
){
131
KeyTypeVal =
KEYTYPE_MODE;
132
KeyCount++
;
133
}
134
135
//
温控温度
136
if
(Key_CTDown ==
0
) {
137
KeyTypeVal =
KEYTYPE_CTDOWN;
138
KeyCount ++
;
139
140
//
长按状态
141
if
(KeyCount >
KEYPRESS_LONG) {
142
KeyCount =
0
;
143
if
(CriticalTempVal >
VALIDTEMPERATURE_MIN) {
144
TempChangingStatusSpace =
CHANGINGCOUNT;
145
CriticalTempVal -=
TEMPERATURESPET;
146
}
147
}
148
}
149
150
//
温控温度
151
if
(Key_CTUp ==
0
) {
152
KeyTypeVal =
KEYTYPE_CTUP;
153
KeyCount ++
;
154
155
//
长按状态
156
if
(KeyCount >
KEYPRESS_LONG) {
157
KeyCount =
0
;
158
if
(CriticalTempVal <
VALIDTEMPERATURE_MAX){
159
TempChangingStatusSpace =
CHANGINGCOUNT;
160
CriticalTempVal +=
TEMPERATURESPET;
161
}
162
}
163
}
164
165
if
(KeyCount >
KEYPRESS_SHORT){
166
if
(Key_Mode ==
1
&& KeyTypeVal ==
KEYTYPE_MODE){
167
KeyTypeVal =
KEYTYPE_NONE;
168
KeyCount =
0
;
169
if
(InAuto){
170
InAuto =
0
;
171
InHandOn =
1
;
172
}
173
else
{
174
if
(InHandOn)
175
InHandOn =
0
;
176
else
177
InAuto =
1
;
178
}
179
}
180
181
if
(Key_CTDown ==
1
&& KeyTypeVal ==
KEYTYPE_CTDOWN){
182
KeyTypeVal =
KEYTYPE_NONE;
183
KeyCount =
0
;
184
if
(CriticalTempVal >
VALIDTEMPERATURE_MIN) {
185
CriticalTempVal -=
TEMPERATURESPET;
186
TempChangingStatusSpace =
CHANGINGCOUNT;
187
}
188
}
189
190
if
(Key_CTUp ==
1
&& KeyTypeVal ==
KEYTYPE_CTUP){
191
KeyTypeVal =
KEYTYPE_NONE;
192
KeyCount =
0
;
193
if
(CriticalTempVal <
VALIDTEMPERATURE_MAX) {
194
TempChangingStatusSpace =
CHANGINGCOUNT;
195
CriticalTempVal +=
TEMPERATURESPET;
196
}
197
}
198
}
199
}
200
201
202
void
ReadTemperature(
void
){
203
unsigned
int
Val;
204
205
Val =
GetTemperature();
206
207
//
18B20有个特殊问题,第一次读取会出现 85°C
208
if
(InInitTemp && Val ==
8500
){
209
CanReadTemp =
1
;
210
return
;
211
}
212
213
RealTempVal =
Val;
214
CanReadTemp =
0
;
215
InInitTemp =
0
;
216
//
217
//
对于临界温度,需要特殊处理。
218
//
防止温控在临界时频繁跳变,当在临界一侧温度超缓冲量时才允许跳转模式。
219
//
当温控探头无效时优先处理
220
//
221
//
如果温控探头被拔出,再次插入的时候会出现 85°C的错误情况
222
//
只要温度读取错误,那么就认为温控探头是被拔出状态。
223
//
224
if
(RealTempVal ==
VAL_ERRTEMPERATURE){
225
InInitTemp =
1
;
226
if
(InCritical)
227
ChangeCount--
;
228
else
{
229
InCritical =
1
;
230
ChangeCount =
CRITICALCOUNTERR;
231
}
232
}
233
else
if
(InWorking) {
234
if
(RealTempVal <
CriticalTempVal){
235
if
(InCritical)
236
ChangeCount--
;
237
else
{
238
InCritical =
1
;
239
ChangeCount =
CRITICALCOUNTDOWN;
240
}
241
}
242
else
{
243
InCritical =
0
;
244
ChangeCount =
0
;
245
}
246
}
247
else
{
248
if
(RealTempVal >
CriticalTempVal){
249
if
(InCritical)
250
ChangeCount --
;
251
else
{
252
InCritical =
1
;
253
ChangeCount =
CRITICALCOUNTUP;
254
}
255
}
256
else
{
257
InCritical =
0
;
258
ChangeCount =
0
;
259
}
260
}
261
262
}
263
264
265
void
InitTimer(
void
){
266
//
使用定时器1作为时间计数
267
TMOD =
0x01
;
268
TL0 =
T1MS;
269
TH0 = T1MS >>
8
;
270
TR0 =
1
;
271
ET0 =
1
;
272
EA =
1
;
273
274
CanReadTemp =
0
;
275
TempTimerSpace = TEMPGETCOUNT;
//
第一次温度读取
276
InInitTemp =
1
;
//
温度处于初始状态,解决85°C问题
277
TempChangingStatusSpace =
0
;
//
不在调温状态
278
}
279
280
281
void
UpdateStatus(
void
){
282
//
283
//
温控临界跳变, 缓冲计数为零时跳变
284
//
285
//
286
if
(InCritical && !
ChangeCount){
287
InCritical =
0
;
288
if
((RealTempVal != VAL_ERRTEMPERATURE) && (RealTempVal >
CriticalTempVal))
289
InWorking =
1
;
290
else
291
InWorking =
0
;
292
}
293
294
//
是否在调温状态
295
if
(TempChangingStatusSpace)
296
InChangingTemp =
1
;
297
else
298
InChangingTemp =
0
;
299
300
//
301
//
温控状态和手工状态
302
//
温控状态时根据是否工作状态判断,手动模式下通过是否强行开启判断继电器模式
303
//
304
if
((InAuto && InWorking) || (!InAuto &&
InHandOn))
305
RelayVal =
COOL_POWERALL;
306
else
307
RelayVal =
COOL_MALAISE;
308
309
//
工作状态信息更新
310
311
if
(RelayVal >
0
)
312
DirectLamp =
1
;
313
else
314
DirectLamp =
0
;
315
316
if
(InAuto)
317
DirectLamp |=
0x02
;
318
}
319
320
321
unsigned
int
GetCriticalTemperature(
void
){
322
//
todo : 这里的值需要从EEPROM中获取
323
return
(DEFAULTCRITICALTEMP);
324
}
325
/*
326
void SaveCriticalTemperature(unsigned int Val){
327
//todo : 保存临界温度到EEPROM,防止停电丢失数据
328
}
329
*/
330
331
void
time0(
void
) interrupt
1
{
332
//
时钟
333
TL0 =
T1MS;
334
TH0 = T1MS >>
8
;
335
TempTimerSpace--
;
336
if
(!
TempTimerSpace){
337
CanReadTemp =
1
;
338
TempTimerSpace =
TEMPGETCOUNT;
339
}
340
341
if
(TempChangingStatusSpace)
342
TempChangingStatusSpace--
;
343
}
欢迎光临 中科因仑“3+1”工程特种兵精英论坛 (http://bbs.enlern.com/)
Powered by Discuz! X3.4