炎炎夏日需要一个清凉的地 - 自制水冷系统(十一 指尖的思绪之程序篇)

前段时间接手了一个项目,所以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段地址。修改后暂未发现程序中其他变量被覆写的问题。

调试中的效果图

 

贴出第一次写51代码^^。只是软硬结合的这种模式属于第一个。

----------------

DoubleCooling.c
  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 }
LEDDisplay.c
  1 #include <STC12C5A60S2.h>
  2 
  3 #include "LEDDisplay.h"
  4 #include "Temperature.h"
  5 #include "Pins.h"
  6 
  7 
  8 #define Delay_REF    12           //设置每一个点显示的时间长度(1~20)
  9 #define LED_PWDDEFAULT    9      // LED的调光值 1~9
 10 
 11 #define DT_P2M0SET        0x00  // 0000 0000
 12 #define DT_P2M1SET        0x00     // 0000 0000
 13 #define DT_P0M0SET        0xf0    // 1111 0000
 14 #define DT_P0M1SET        0x00  // 0000 0000
 15 
 16 
 17 // 数码管
 18 // 12 ~ 9
 19 sbit    DT_COM1            = P0 ^ 4;
 20 sbit    DT_COM2            = P0 ^ 5;
 21 sbit    DT_COM3            = P0 ^ 6;
 22 sbit    DT_COM4            = P0 ^ 7;
 23 // 8 ~ 1
 24 sbit    DT_DpyA            = P2 ^ 0;
 25 sbit    DT_DpyB            = P2 ^ 1;
 26 sbit    DT_DpyC            = P2 ^ 2;
 27 sbit    DT_DpyD            = P2 ^ 3;
 28 sbit    DT_DpyE            = P2 ^ 4;
 29 sbit    DT_DpyF            = P2 ^ 5;
 30 sbit    DT_DpyG            = P2 ^ 6;
 31 sbit    DT_DpyDP        = P2 ^ 7;
 32 sfr   DT_Dpy      = 0xA0;   // P2
 33 
 34 
 35 void Delay (unsigned int);
 36 void Dis_Off (void);
 37 void displayHH1 (unsigned char);
 38 void displayHH2 (unsigned char);
 39 void displayHH3 (unsigned char);
 40 void displayHH4 (unsigned char);
 41 
 42 
 43 
 44 data unsigned char Led_PWM;   // 调光 1 ~ 9
 45 
 46 unsigned char code NumData[]={
 47   //0, 1, 2, 3, 4, 5, 6, 7, 8, 9, (None) E, R     
 48     0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f, 0x00, 0x79, 0x77 
 49 };
 50 unsigned int Sec = 0;
 51 
 52 
 53 void InitView(void){
 54     P0M0 = DT_P0M0SET;
 55     P0M1 = DT_P0M1SET;
 56     P2M0 = DT_P2M0SET;
 57     P2M1 = DT_P2M1SET;
 58     //Dis_Off(); 
 59     Led_PWM = LED_PWDDEFAULT;
 60 }
 61 
 62 void DisplayTemperature(unsigned int t){
 63   // 无效温度显示 ERR 字样
 64   if (t != VAL_ERRTEMPERATURE){
 65         displayHH4(NumData[t / 1000]);
 66     displayHH3(NumData[t / 100 % 10] + 0x80);
 67     displayHH2(NumData[t / 10 % 10]);
 68     displayHH1(NumData[t % 10]);
 69   }
 70   else {
 71         // 无效温度显示 ERR 字样
 72     //displayHH4(NumData[10]);
 73     displayHH3(NumData[11]);
 74     displayHH2(NumData[12]);
 75     displayHH1(NumData[12]);
 76   }
 77 }
 78 
 79 
 80 
 81 void Delay (unsigned int count){ 
 82     unsigned int i;
 83     while( count-- != 0){
 84         for(i = 0; i < Delay_REF; i++); 
 85     }                      
 86 }
 87 
 88 void Dis_Off (void){
 89   DT_COM1      = 0;
 90   DT_COM2      = 0;    
 91   DT_COM3      = 0;
 92   DT_COM4   = 0;
 93 
 94     DT_Dpy    = 0xFF;
 95     /*
 96   DT_DpyA      = 1;
 97   DT_DpyB      = 1;
 98   DT_DpyC      = 1;
 99   DT_DpyD      = 1;
100   DT_DpyE      = 1;
101   DT_DpyF      = 1;
102   DT_DpyG      = 1;
103   DT_DpyG  = 1;
104 */
105     Delay(10-Led_PWM); 
106 }
107 
108 void displayHH1 (unsigned char d){ 
109     if(d & 0x01){
110         DT_COM1 = 1;DT_DpyA = 0;}    Delay(Led_PWM);    Dis_Off();
111 
112     if(d & 0x02){
113         DT_COM1 = 1;DT_DpyB = 0;}    Delay(Led_PWM);    Dis_Off();
114 
115     if(d & 0x04){
116         DT_COM1 = 1;DT_DpyC = 0;}    Delay(Led_PWM);    Dis_Off();
117 
118     if(d & 0x08){
119         DT_COM1 = 1;DT_DpyD = 0;}Delay(Led_PWM);Dis_Off();
120 
121     if(d & 0x10){
122         DT_COM1 = 1;DT_DpyE = 0;}Delay(Led_PWM);Dis_Off();
123 
124     if(d & 0x20){
125         DT_COM1 = 1;DT_DpyF = 0;}Delay(Led_PWM);Dis_Off();
126 
127     if(d & 0x40){
128         DT_COM1 = 1;DT_DpyG = 0;}Delay(Led_PWM);Dis_Off();
129 
130     if(d & 0x80){
131         DT_COM1 = 1;DT_DpyDP = 0;}Delay(Led_PWM);Dis_Off();
132 } 
133 
134 void displayHH2 (unsigned char d){
135     if(d & 0x01){
136         DT_COM2 = 1;DT_DpyA = 0;}Delay(Led_PWM);Dis_Off();
137 
138     if(d & 0x02){
139         DT_COM2 = 1;DT_DpyB = 0;}Delay(Led_PWM);Dis_Off();
140 
141     if(d & 0x04){
142         DT_COM2 = 1;DT_DpyC = 0;}Delay(Led_PWM);Dis_Off();
143 
144     if(d & 0x08){
145         DT_COM2 = 1;DT_DpyD = 0;}Delay(Led_PWM);Dis_Off();
146 
147     if(d & 0x10){
148         DT_COM2 = 1;DT_DpyE = 0;}Delay(Led_PWM);Dis_Off();
149 
150     if(d & 0x20){
151         DT_COM2 = 1;DT_DpyF = 0;}Delay(Led_PWM);Dis_Off();
152 
153     if(d & 0x40){
154         DT_COM2 = 1;DT_DpyG = 0;}Delay(Led_PWM);Dis_Off();
155 
156     if(d & 0x80){
157         DT_COM2 = 1;DT_DpyDP = 0;}Delay(Led_PWM);Dis_Off();
158 } 
159 
160 void displayHH3 (unsigned char d){
161     if(d & 0x01){
162         DT_COM3 = 1;DT_DpyA = 0;}Delay(Led_PWM);Dis_Off();
163 
164     if(d & 0x02){
165         DT_COM3 = 1;DT_DpyB = 0;}Delay(Led_PWM);Dis_Off();
166 
167     if(d & 0x04){
168         DT_COM3 = 1;DT_DpyC = 0;}Delay(Led_PWM);Dis_Off();
169 
170     if(d & 0x08){
171         DT_COM3 = 1;DT_DpyD = 0;}Delay(Led_PWM);Dis_Off();
172 
173     if(d & 0x10){
174         DT_COM3 = 1;DT_DpyE = 0;}Delay(Led_PWM);Dis_Off();
175 
176     if(d & 0x20){
177         DT_COM3 = 1;DT_DpyF = 0;}Delay(Led_PWM);Dis_Off();
178 
179     if(d & 0x40){
180         DT_COM3 = 1;DT_DpyG = 0;}Delay(Led_PWM);Dis_Off();
181 
182     if(d & 0x80){
183         DT_COM3 = 1;DT_DpyDP = 0;}Delay(Led_PWM);Dis_Off();
184 } 
185 
186 void displayHH4 (unsigned char d){
187     if(d & 0x01){
188         DT_COM4 = 1;DT_DpyA = 0;}Delay(Led_PWM);Dis_Off();
189 
190     if(d & 0x02){
191         DT_COM4 = 1;DT_DpyB = 0;}Delay(Led_PWM);Dis_Off();
192 
193     if(d & 0x04){
194         DT_COM4 = 1;DT_DpyC = 0;}Delay(Led_PWM);Dis_Off();
195 
196     if(d & 0x08){
197         DT_COM4 = 1;DT_DpyD = 0;}Delay(Led_PWM);Dis_Off();
198 
199     if(d & 0x10){
200         DT_COM4 = 1;DT_DpyE = 0;}Delay(Led_PWM);Dis_Off();
201 
202     if(d & 0x20){
203         DT_COM4 = 1;DT_DpyF = 0;}Delay(Led_PWM);Dis_Off();
204 
205     if(d & 0x40){
206         DT_COM4 = 1;DT_DpyG = 0;}Delay(Led_PWM);Dis_Off();
207 
208     if(d & 0x80){
209         DT_COM4 = 1;DT_DpyDP = 0;}Delay(Led_PWM);Dis_Off();
210 } 
PilotLamp.c
 1 #include <STC12C5A60S2.h>
 2 
 3 #include "PilotLamp.h"
 4 
 5 // LED 指示灯
 6 sbit    Lamp_Work          = P0 ^ 1;  // 继电器工作状态亮
 7 sbit    Lamp_Auto          = P0 ^ 2;  // 温控模式
 8 sbit    Lamp_Hand            = P0 ^ 3;  // 手控模式
 9 
10 
11 void InitPilotLamp(void){
12 }
13 
14 void DisplayPilotLamp(unsigned char Val){
15 // 指示灯状态 
16 // 第一位 继电器工作状态,灯亮工作状态,灯灭停止制冷          
17 // 第二位 是否为自动模式
18 // 第三位 温控器故障
19     if (Val & 0x01)
20         Lamp_Work    = 1;
21     else 
22         Lamp_Work    = 0;
23     
24     if (Val & 0x02)
25         Lamp_Auto     = 1;
26     else
27         Lamp_Auto     = 0;
28         
29     Lamp_Hand     = ~Lamp_Auto;
30         
31 }
Relays.c
 1 #include <STC12C5A60S2.h>
 2 
 3 #include "Relays.h"
 4 #include "Pins.h"
 5 
 6 
 7 sbit    RelayCool1  = P1 ^ 3;
 8 sbit    RelayCool2  = P1 ^ 4;
 9 
10 
11 void InitRealys(void){}
12 
13 void UpdateRelays(unsigned char Val){
14 // 例:值 0x03 (0000 0011)
15 //     开启第一、第二 继电器  
16     if (Val){
17         RelayCool1 = 0;
18       RelayCool2 = 0;
19     }
20     else {
21         RelayCool1 = 1;
22         RelayCool2 = 1;
23     }
24 }
18b20Temperature.asm
  1 DSSP  SEGMENT  CODE    ;程序段
  2 
  3 PUBLIC  GetTemperature      ;入口地址,跳转到DL标号处执行汇编程序  GetTemperature
  4 
  5 RSEG  DSSP              ;程序段
  6 
  7 IN           EQU     0CBH  ; P5.3 引脚地址
  8 FLAG1     EQU   05H   ;DS18B20器件存在标志
  9 TTL       EQU   07H   ;温度读出值(高位在TTL-1中,低位在TTL中)
 10 ;TTL_H     EQU   06H   ;温度读出值(高位在TTL-1中,低位在TTL中)
 11 
 12 
 13 ; 这是DS18B20复位初始化子程序
 14 INIT_1820:
 15     SETB IN
 16     NOP
 17     CLR IN
 18     ;主机发出延时537微秒的复位低脉冲
 19     MOV R1,#18;#3
 20 TSR1:
 21     MOV R0,#107
 22     DJNZ R0,$
 23     DJNZ R1,TSR1
 24     SETB IN;然后拉高数据线
 25     NOP
 26     NOP
 27     NOP
 28     NOP;12倍
 29     NOP
 30     NOP
 31     NOP
 32     NOP
 33     NOP
 34     NOP
 35     NOP
 36     NOP
 37     NOP
 38     NOP
 39     NOP
 40     NOP
 41     NOP
 42     NOP
 43     NOP
 44     NOP
 45     NOP
 46     NOP
 47     NOP
 48     NOP
 49     NOP
 50     NOP
 51     NOP
 52     NOP
 53     NOP
 54     NOP
 55     NOP
 56     NOP
 57     NOP
 58     NOP
 59     NOP
 60     NOP
 61     NOP
 62     NOP
 63     NOP
 64     MOV R0,#0DEH;#25H
 65 TSR2:
 66     JNB IN,TSR3;等待DS18B20回应
 67     DJNZ R0,TSR2
 68     LJMP TSR4 ; 延时
 69 TSR3:
 70     SETB FLAG1 ; 置标志位,表示DS1820存在
 71     LJMP TSR5
 72 TSR4:
 73     CLR FLAG1 ; 清标志位,表示DS1820不存在
 74     LJMP TSR7
 75 TSR5:
 76     MOV R7,#6
 77 TSR6:
 78     MOV R0,#117
 79     DJNZ R0,$ ; 时序要求延时一段时间 */
 80     DJNZ R7,TSR6 ; 时序要求延时一段时间 */
 81 TSR7:
 82     SETB IN
 83     RET
 84 
 85 GetTemperature:  
 86 DS1820PRO:
 87     ;这里通过调用显示子程序实现延时一段时间,等待AD转换结束,12位的话750微秒
 88     SETB IN
 89     LCALL INIT_1820;先复位DS18B20
 90     JB FLAG1,TSS2
 91     jmp BCD33 ; 判断DS1820是否存在?若DS18B20不存在则返回
 92 TSS2:
 93     MOV A,#0CCH     ; 跳过ROM匹配
 94     LCALL WRITE_1820
 95     MOV A,#44H         ; 发出温度转换命令
 96     LCALL WRITE_1820
 97     CALL  DL1MS 
 98     SETB IN
 99     LCALL INIT_1820    ;准备读温度前先复位
100     MOV A,#0CCH     ; 跳过ROM匹配
101     LCALL WRITE_1820
102     MOV A,#0BEH     ; 发出读温度命令
103     LCALL WRITE_1820
104     LCALL READ_18200; 将读出的温度数据保存到35H/36H 
105     
106 
107 BCD33: 
108     JB FLAG1,BCD44
109     mov R6, #080H
110     mov R7,#00H
111     JMP TORET
112     
113 BCD44:
114 
115       ;温度转换程序:精确到:0.06 ;
116       ; 小数温度查表获取。
117       MOV    DPTR,#TABB
118     MOV A, TTL
119       ANL A,#0FH
120       MOVC A,@A+DPTR
121       MOV R3, A;
122       ; 整数温度转换
123       MOV A,TTL
124     MOV B,TTL-1
125     MOV C,B.0
126     RRC A
127     MOV C,B.1
128     RRC A
129     MOV C,B.2
130     RRC A
131     MOV C,B.3
132     RRC A
133       ; 拼接整数位和小数位温度  整数*100 + 小数位值
134       MOV B, #100
135       MUL AB
136     MOV    R4,B         ;保存积的高8位
137     ADD    A,R3         ;
138     MOV    R7,A
139     CLR    A
140     ADDC A,R4         ;加上进位,
141     MOV    R6,A    
142 
143 
144 TORET:
145     RET
146     
147     
148 ;--------------------------------写DS18B20的子程序(有具体的时序要求)
149 WRITE_1820:
150     MOV R2,#8;一共8位数据
151     CLR C
152 WR1:
153     CLR IN
154     MOV R3,#36;#6
155     DJNZ R3,$
156     RRC A
157     MOV IN,C
158     MOV R3,#192;#23
159     DJNZ R3,$
160     SETB IN
161     NOP
162     NOP
163     NOP
164     NOP
165     NOP
166     NOP
167     NOP
168     NOP
169     NOP
170     NOP
171     NOP
172     NOP
173     DJNZ R2,WR1
174     SETB IN
175     RET
176 
177 ;-----------------------------读DS18B20的程序,从DS18B20中读出两个字节的温度数据 
178 READ_18200:
179     MOV R4,#2 ; 将温度高位和低位从DS18B20中读出
180     MOV R1,#TTL ; 低位存入29H(TEMPER_L),高位存入28H(TEMPER_H)
181 RE00:
182     MOV R2,#8;数据一共有8位
183 RE01:
184     CLR C
185     SETB IN
186     NOP
187     NOP
188     NOP
189     NOP
190     NOP
191     NOP
192     NOP
193     NOP
194     NOP
195     NOP
196     NOP
197     NOP
198     NOP
199     NOP
200     NOP
201     NOP
202     NOP
203     NOP
204     NOP
205     NOP
206     NOP
207     NOP
208     NOP
209     NOP
210     NOP
211     NOP
212     CLR IN
213     NOP
214     NOP
215     NOP
216     NOP
217     NOP
218     NOP
219     NOP
220     NOP
221     NOP
222     NOP
223     NOP
224     NOP
225     NOP
226     NOP
227     NOP
228     NOP
229     NOP
230     NOP
231     NOP
232     NOP
233     NOP
234     NOP
235     NOP
236     NOP
237     NOP
238     NOP
239     NOP
240     NOP
241     NOP
242     NOP
243     NOP
244     NOP
245     NOP
246     NOP
247     NOP
248     NOP
249     NOP
250     NOP
251     NOP
252     SETB IN
253     MOV R3,#54;#9
254 RE10: 
255     DJNZ R3,RE10
256     MOV C,IN
257     MOV R3,#138;#23
258 RE20: 
259     DJNZ R3,RE20
260     RRC A
261     DJNZ R2,RE01
262     MOV @R1,A
263     DEC R1
264     DJNZ R4,RE00
265     RET
266 
267 DL1MS:
268     MOV R7,#6
269 DL1MS2:
270     MOV R6,#255
271      DJNZ R6,$
272      DJNZ R7,DL1MS2
273     RET 
274     
275 TABB:   
276     ; 小数位温度0~F的查表值,18B20的最小温控精度 0.0625, 只保留两位小数
277     
278     DB    00H, 06H, 0CH, 12H, 19H, 1FH, 25H, 2BH, 32H  
279     DB  56H, 3EH, 44H, 4BH, 51H, 57H, 5DH 
280     
281 
282 END

 

 

 

 

 

 

转载于:https://www.cnblogs.com/gleam/archive/2012/08/10/2631516.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/434354.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

wordpress 后台慢_建站经验-wordpress用户注册收不到验证邮件

背景我的一个博客http://axuretop.com&#xff0c;已经在后台开放注册了&#xff0c;注册用户默认为“订阅者”。一旦发布新的文章&#xff0c;会订阅邮件给用户。后台有300多个订阅用户&#xff0c;但是发现评论文章的很少&#xff0c;严重怀疑他们无法订阅我的文章&#xff0…

ai字体行间距怎么调整_字体基础知识(一)

本期教程主要讲解字体基础知识&#xff1a;字体、字号、字形、字重、行高、行距、字间距、字偶间距。本文所用软件为Microsoft PowerPoint 2013。1 字体文字的风格样式&#xff0c;就是我们平时常说的黑体、宋体、楷体、Segoe UI Black、Courier New、Consolas。如下图所示&…

免费的crm系统部署在自己的服务器,crm系统本地部署与云端部署的区别

CRM系统的部署方式通常有三种模式&#xff0c;分别是&#xff1a;本地部署、云端部署、公有云部署等三种模式。通常企业在选择的部署方式是本地部署与云端部署。那么他们部署方式得区别是什么?本地部署CRM系统本地部署的CRM软件&#xff1a;是意味着保存在企业自身的服务器中。…

gitee怎么仓库间传文件_实现一个简单的基于码云(Gitee) 的 Storage

实现一个简单的基于码云(Gitee) 的 StorageIntro上次在 asp.net core 从单机到集群 一文中提到存储还不支持分布式&#xff0c;并立了一个 flag基于 github 或者 开源中国的码云实现一个 storage于是这两天就来填坑了。。实现了一个简单的基于开源中国的码云的 storage准备工作…

载波聚合或双连接的方式进行_智能电表常用远程抄表方式,您想知道吗?--老兵聊电之...

智能电表的远程抄表方式有多种方式&#xff0c;但老王更喜欢以下几种抄表方式&#xff0c;希望您能接受。一、智能电表的工作原理1.智能电表主要是由电子元器件构成&#xff0c;其工作原理是先通过对用户供电电压和电流的实时采样&#xff0c;再采用专用的电能表集成电路&#…

搞个服务器安装黑群晖系统,牛人闲置电脑大改造!超低成本组建家用黑群晖NAS...

一、前言&#xff1a;大家好&#xff0c;俺又来了。这篇原创很早就在构思怎么写了&#xff0c;因为确实作为一个数码爱好者来说&#xff0c;当得知有 群晖 威联通 这种NAS 的东西存在的时候&#xff0c;就忍不住想体验体验。但是奈何自己的资金不够&#xff0c;想一想&#xff…

立体旋转查看图片

声明&#xff1a;如果程序有问题&#xff0c;请各位大虾多多指点&#xff0c;谢谢。 基于psoft.js制作的一款立体旋转查看图片应用 1.可以通过鼠标滑动来操作图片的旋转&#xff0c;可以向右&#xff0c;向左拖动 a。向左滑动 b。向右滑动 c。向左转到一下 2.代码实现&#xff…

asterisk架构

从架构的角度看来&#xff0c;Asterisk是由许多不同的模块组成的。在设计基于Asterisk的系统时&#xff0c;这种模块化的特性&#xff0c;提供了几乎无限的灵活必。作为Asterisk系统管理员&#xff0c;你拥有选择加载模块的权利。你所加载的每一个模块&#xff0c;都提供了不同…

esp虚拟服务器,esp8266接入云服务器

esp8266接入云服务器 内容精选换一换公有云平台提供的云监控&#xff0c;可以对云耀云服务器的运行状态进行日常监控。您可以通过管理控制台&#xff0c;直观地查看云耀云服务器的各项监控指标。云耀云服务器正常运行。关机、故障、删除状态的云耀云服务器&#xff0c;无法在云…

c++ primer 第六版 pdf_A3N630 塑壳断路器如何更换.pdf

太阳能单晶炉专用配套变压器&#xff0c;是我公司研发的生产太阳能单晶硅的单晶炉设备专用变压器&#xff0c;本产品作为太阳能单晶炉设备的配套产品&#xff0c;它将电网电源的三相380V电压转换成较低的三相交流50V电压&#xff0c;为加热提供电源&#xff0c;以得到设备加热所…

datareader对象直接转化为int_Integer、new Integer() 和 int 比较的面试题

作者&#xff1a;chenxiangxiang来源&#xff1a;https://www.cnblogs.com/cxxjohnson/p/10504840.html基本概念的区分&#xff1a;1、Integer 是 int 的包装类&#xff0c;int 则是 java 的一种基本数据类型2、Integer 变量必须实例化后才能使用&#xff0c;而int变量不需要3、…

个人推荐的SIP software Phone

开源免费的LinPhone&#xff0c;国内很多人基于他继续二次开发 http://www.linphone.org/ Zoiper 有免费的&#xff0c;有收费的&#xff0c;有SDK&#xff0c;支持SIP/IAX(没有NAT问题) 官方下载的免费版本里面就支持中文&#xff01; 免费版本支持&#xff1a;for Window…

_Linux中功能强大的截图工具 - Flameshot

Flameshot 是一款功能强大但易于使用的屏幕截图软件&#xff0c;中文名称火焰截图。Flameshot 简单易用并有一个 CLI 版本&#xff0c;所以你也可以从命令行来进行截图。Flameshot 是一个Linux发行版中完全免费且开源的截图工具。通常Linux发行版中会默认自带一个截图工具&…

jquery动画 -- 1.加载指示器

该系列文章是我阅读《jQuery 1.4 Animation Techniques》后的总结&#xff0c;有兴趣的朋友可以去看原版书籍。 动画效果对于丰富网站的交互体验起到了不可或缺的作用&#xff0c;他可以让你的站点更酷&#xff0c;更吸引人。 什么时候使用动画&#xff1a; 1.当显示或隐藏页面…

centos7 安装redis_Redis6安装(上) - 单机单实例

首先下载新版的redis6并且上传到centos7&#xff1a;安装redis需要gcc的环境&#xff0c;和以往老版本不同&#xff0c;这里的gcc需要高一点的版本。 yum install gcc-c随后升级gcc版本 yum -y install centos-release-scl yum -y install devtoolset-9-gcc devtoolset-9-gcc-c…

手机输入法带拼音声调_word中拼音横向设置

前言在word编辑文字的时候&#xff0c;可以加注拼音&#xff0c;这对于陌生文字辨别读音非常有帮助&#xff0c;但是插入的拼音都是在文字上方的&#xff0c;那如果我们想要横向插入拼音的话&#xff0c;应该怎么操作呢&#xff1f;今天小编就给大家分享&#xff0c;在word中拼…

怎么在安卓布局里设置滚动字体_Get新技能|如何在手机上设置文字版拼音?

首先明确一点&#xff1a;安卓手机里的汉字带上拼音&#xff0c;是需要安装拼音字体&#xff0c;而不是拼音输入法。大部分安卓手机里的汉字带上拼音&#xff0c;可按如下步骤操作&#xff1a;注&#xff1a;视频后小总结1.对于大部分现在的手机来说&#xff0c;已经提供了换字…

HTTP、TCP、UDP、Socket (转)

先来一个讲TCP、UDP和HTTP关系的1、TCP/IP是个协议组&#xff0c;可分为三个层次&#xff1a;网络层、传输层和应用层。在网络层有IP协议、ICMP协议、ARP协议、RARP协议和BOOTP协议。在传输层中有TCP协议与UDP协议。在应用层有FTP、HTTP、TELNET、SMTP、DNS等协议。因此&#x…

windows 禁用ipv6服务_39.Dism++ Windows系统简洁优化

Dism的特点Dism无需任何Dism组件&#xff0c;即可兼容高低版本所有系统&#xff01;而微软Dism则需要3个版本。Dism是Dism的交集&#xff0c;提供完全的图形化操作&#xff0c;几乎支持Dism的所有功能以及大量Dism原本所不支持的功能。管理更新、驱动、功能、Appx、可选功能、服…

windows功能_有 20 多种功能的 Windows 原生日历替代软件

Win 10 出来这么久了&#xff0c;不知道还有多少在用 XP 或者 Win 7 的朋友呢&#xff1f;今天小美要推荐的软件&#xff0c;是专门针对 Win 10 的&#xff0c;没有升级系统的小伙伴可能就无法使用了~这是一款用来替换 Windows 10 任务栏原生时间日历的软件&#xff0c;名字叫「…