炎炎夏日需要一个清凉的地 - 自制水冷系统(十一 指尖的思绪之程序篇)
前段時間接手了一個項目,所以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
總結
以上是生活随笔為你收集整理的炎炎夏日需要一个清凉的地 - 自制水冷系统(十一 指尖的思绪之程序篇)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Revit工作时处理CAD图层的5种方法
- 下一篇: 阿里java编程规范试题_阿里java编