單片機練習 - DS18B20溫度轉(zhuǎn)換與顯示
最近都在學習和寫單片機的程序, 今天有空又模仿DS18B20溫度測量顯示實驗寫了一個與DS18B20基于單總線通信的程序.
DS18B20 數(shù)字溫度傳感器(參考:智能溫度傳感器DS18B20的原理與應(yīng)用)是DALLAS 公司生產(chǎn)的1-Wire,即單總線器件,具有線路簡單,體積小的特點。因此用它來組成一個測溫系統(tǒng),具有線路簡單,在一根通信線,可以掛很多這樣的數(shù)字溫度計。DS18B20 產(chǎn)品的特點:
(1)、只要求一個I/O 口即可實現(xiàn)通信。
(2)、在DS18B20 中的每個器件上都有獨一無二的序列號。
(3)、實際應(yīng)用中不需要外部任何元器件即可實現(xiàn)測溫。
(4)、測量溫度范圍在-55 到+125℃之間; 在-10 ~ +85℃范圍內(nèi)誤差為±5℃;
(5)、數(shù)字溫度計的分辨率用戶可以從9 位到12 位選擇。將12位的溫度值轉(zhuǎn)換為數(shù)字量所需時間不超過750ms;
(6)、內(nèi)部有溫度上、下限告警設(shè)置。
DS18B20引腳分布圖
DS18B20 詳細引腳功能描述:
1、GND 地信號;
2、DQ數(shù)據(jù)輸入出引腳。開漏單總線接口引腳。當被用在寄生電源下,此引腳可以向器件提供電源;漏極開路, 常太下高電平. 通常要求外接一個約5kΩ的上拉電阻.
3、VDD可選擇的VDD 引腳。電壓范圍:3~5.5V; 當工作于寄生電源時,此引腳必須接地。
DS18B20存儲器結(jié)構(gòu)圖
暫存儲器的頭兩個字節(jié)為測得溫度信息的低位和高位字節(jié);
第3, 4字節(jié)是TH和TL的易失性拷貝, 在每次電復位時都會被刷新;
第5字節(jié)是配置寄存器的易失性拷貝, 同樣在電復位時被刷新;
第9字節(jié)是前面8個字節(jié)的CRC檢驗值.
配置寄存器的命令內(nèi)容如下:
0R1R011111
MSB LSB
R0和R1是溫度值分辨率位, 按下表進行配置.默認出廠設(shè)置是R1R0 = 11, 即12位.
溫度值分辨率配置表
R1R0分辨率最大轉(zhuǎn)換時間(ms)
009bit93.75(tconv/8)
0110bit183.50(tconv/4)
1011bit375(tconv/2)
1112bit750 (tconv)
4種分辨率對應(yīng)的溫度分辨率為0.5℃, 0.25℃, 0.125℃, 0.0625℃(即最低一位代表的溫度值)
12位分辨率時的兩個溫度字節(jié)的具體格式如下:
低字節(jié):
2^32^22^12^02^-12^-22^-32^-4
高字節(jié):
SSSSS2^62^52^4
其中高字節(jié)前5位都是符號位S, 若分辨率低于12位時, 相應(yīng)地使最低為0, 如: 當分辨率為10位時, 低字節(jié)為:
2^32^22^12^02^-12^-200
, 高字節(jié)不變....
一些溫度與轉(zhuǎn)換后輸出的數(shù)字參照如下:
溫度數(shù)字輸出換成16進制
+125℃00000111 11010000 07D0H
+85℃00000101 010100000550H
+25.0625℃00000001 100100010191H
+10.125℃00000000 1010001000A2H
+0.5℃00000000 000010000008H
0℃00000000 000000000000H
-0.5℃11111111 11111000FFF8H
-10.125℃11111111 01011110FFE5H
-25.0625℃11111110 01101111FF6FH
-55℃11111100 10010000FC90H
由上表可看出, 當輸出是負溫度時, 使用補碼表示, 方便計算機運算(若是用C語言, 直接將結(jié)果賦值給一個int變量即可).
DS18B20 的使用方法:
由于DS18B20 采用的是1-Wire 總線協(xié)議方式,即在一根數(shù)據(jù)線實現(xiàn)數(shù)據(jù)的雙向傳輸,而對單片機來說,我們必須采用軟件的方法來模擬單總線的協(xié)議時序來完成對DS18B20芯片的訪問。
由于DS18B20是在一根I/O線上讀寫數(shù)據(jù),因此,對讀寫的數(shù)據(jù)位有著嚴格的時序要求。
DS18B20有嚴格的通信協(xié)議來保證各位數(shù)據(jù)傳輸?shù)恼_性和完整性。
該協(xié)議定義了幾種信號的時序:初始化時序(dsInit()實現(xiàn))、讀時序(readByte())、寫時序(writeByte())。
所有時序都是將主機作為主設(shè)備,單總線器件作為從設(shè)備。而每一次命令和數(shù)據(jù)的傳輸都是從主機主動啟動寫時序開始,如果要求單總線器件回送數(shù)據(jù),在進行寫命令后,主機需啟動讀時序完成數(shù)據(jù)接收。數(shù)據(jù)和命令的傳輸都是低位在先。
DS18B20與單片機連接電路圖:
利用軟件模擬DS18B20的單線協(xié)議和命令:主機操作DS18B20必須遵循下面的順序
1. 初始化
單線總線上的所有操作都是從初始化開始的. 過程如下:
1)請求: 主機通過拉低單線480us以上, 產(chǎn)生復位脈沖, 然后釋放該線, 進入Rx接收模式. 主機釋放總線時, 會產(chǎn)生一個上升沿脈沖.
DQ : 1 -> 0(480us+) -> 1
2)響應(yīng): DS18B20檢測到該上升沿后, 延時15~60us, 通過拉低總線60~240us來產(chǎn)生應(yīng)答脈沖.
DQ: 1(15~60us) -> 0(60~240us)
3)接收響應(yīng): 主機接收到從機的應(yīng)答脈沖后, 說明有單線器件在線. 至此, 初始化完成.
DQ: 0
2. ROM操作命令
當主機檢測到應(yīng)答脈沖, 便可發(fā)起ROM操作命令. 共有5類ROM操作命令, 如下表
命令類型 命令字節(jié)功能
Read Rom 讀ROM 33H讀取激光ROM中的64位,只能用于總線上單個DS18B20器件情況, 多掛時會發(fā)生數(shù)據(jù)沖突
Match Rom匹配ROM55H此命令后跟64位ROM序列號,尋址多掛總線上的對應(yīng)DS18B20.只有序列號完全匹配的DS18B20才能響應(yīng)后面的內(nèi)存操作命令,其他不匹配的將等待復位脈沖.可用于單掛或多掛兩種情況.
Skip Rom 跳過ROMCCH可無須提供64位ROM序列號即可運行內(nèi)存操作命令, 只能用于單掛.
Search Rom搜索ROMF0H通過一個排除法過程, 識別出總線上所有器件的ROM序列號
Alarm Search告警搜索ECH命令流程與Search Rom相同, 但DS18B20只有最近的一次溫度測量時滿足了告警觸發(fā)條件的, 才會響應(yīng)此命令.
3. 內(nèi)存操作命令
在成功執(zhí)行ROM操作命令后, 才可使用內(nèi)存操作命令. 共有6種內(nèi)存操作命令:
命令類型命令字節(jié)功能
Write Scratchpad
寫暫存器4EH寫暫存器中地址2~地址4的3個字節(jié)(TH,TL和配置寄存器)在發(fā)起復位脈沖之前,3個字節(jié)都必須要寫.
Read Scratchpad
讀暫存器BEH讀取暫存器內(nèi)容,從字節(jié)0~一直到字節(jié)8, 共9個字節(jié),主機可隨時發(fā)起復位脈沖,停止此操作,通常我們只需讀前5個字節(jié).
Copy Scratchpad
復制暫存器48H將暫存器中的內(nèi)容復制進EERAM, 以便將溫度告警觸發(fā)字節(jié)存入非易失內(nèi)存. 如果此命令后主機產(chǎn)生讀時隙, 那么只要器件還在進行復制都會輸出0, 復制完成后輸出1.
Convert T
溫度轉(zhuǎn)換44H開始溫度轉(zhuǎn)換操作. 若在此命令后主機產(chǎn)生時隙, 那么只要器件還在進行溫度轉(zhuǎn)換就會輸出0, 轉(zhuǎn)換完成后輸出1.
Recall E2
重調(diào)E2暫存器B8H將存儲在EERAM中的溫度告警觸發(fā)值和配置寄存器值重新拷貝到暫存器中,此操作在DS18B20加電時自動產(chǎn)生.
Read Power Supply
讀供電方式B4H主機發(fā)起此命令后每個讀數(shù)時隙內(nèi),DS18B20會發(fā)信號通知它的供電方式:0寄生電源, 1外部供電.
4. 數(shù)據(jù)處理
DS18B20要求有嚴格的時序來保證數(shù)據(jù)的完整性. 在單線DQ上, 有復位脈沖, 應(yīng)答脈沖, 寫0, 寫1, 讀0, 讀1這6種信號類型. 除了應(yīng)答脈沖外, 其它都由主機產(chǎn)生. 數(shù)據(jù)位的讀和寫是通過讀、寫時隙實現(xiàn)的.
1) 寫時隙: 當主機將數(shù)據(jù)線從高電平拉至低電平時, 產(chǎn)生寫時隙.所有寫時隙都必須在60us以上, 各寫時隙間必須保證1us的恢復時間.
寫"1" : 主機將數(shù)據(jù)線DQ先拉低, 然后釋放15us后, 將數(shù)據(jù)線DQ拉高;
寫"0" : 主機將DQ拉低并至少保持60us以上.
2)讀時隙: 當主機將數(shù)據(jù)線DQ從高電平拉至低電平時, 產(chǎn)生讀時隙. 所有讀時隙最短必須持續(xù)60us, 各讀時隙間必須保證1us的恢復時間.
讀: 主機將DQ拉低至少1us,. 此時主機馬上將DQ拉高, 然后就可以延時15us后, 讀取DQ即可.
源代碼: (測量范圍: 0 ~ 99度)
DS18B20
1
#include
2
//通過DS18B20測試當前環(huán)境溫度, 并通過數(shù)碼管顯示當前溫度值
3
sbit wela = P2^7; //數(shù)碼管位選
4
sbit dula = P2^6; //數(shù)碼管段選
5
sbit ds = P2^2;
6
//0-F數(shù)碼管的編碼(共陰極)
7
unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,
8
0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
9
//0-9數(shù)碼管的編碼(共陰極), 帶小數(shù)點
10
unsigned char code tableWidthDot[]={0xbf, 0x86, 0xdb, 0xcf, 0xe6, 0xed, 0xfd,
11
0x87, 0xff, 0xef};
12
13
//延時函數(shù), 例i=10,則大概延時10ms.
14
void delay(unsigned char i)
15
{
16
unsigned char j, k;
17
for(j = i; j > 0; j--)
18
{
19
for(k = 125; k > 0; k--);
20
}
21
}
22
23
//初始化DS18B20
24
//讓DS18B20一段相對長時間低電平, 然后一段相對非常短時間高電平, 即可啟動
25
void dsInit()
26
{
27
//一定要使用unsigned int型, 一個i++指令的時間, 作為與DS18B20通信的小時間間隔
28
//以下都是一樣使用unsigned int型
29
unsigned int i;
30
ds = 0;
31
i = 103;
32
while(i>0) i--;
33
ds = 1;
34
i = 4;
35
while(i>0) i--;
36
}
37
38
//向DS18B20讀取一位數(shù)據(jù)
39
//讀一位, 讓DS18B20一小周期低電平, 然后兩小周期高電平,
40
//之后DS18B20則會輸出持續(xù)一段時間的一位數(shù)據(jù)
41
bit readBit()
42
{
43
unsigned int i;
44
bit b;
45
ds = 0;
46
i++;
47
ds = 1;
48
i++; i++;
49
b = ds;
50
i = 8;
51
while(i>0) i--;
52
return b;
53
}
54
55
//讀取一字節(jié)數(shù)據(jù), 通過調(diào)用readBit()來實現(xiàn)
56
unsigned char readByte()
57
{
58
unsigned int i;
59
unsigned char j, dat;
60
dat = 0;
61
for(i=0; i<8; i++)
62
{
63
j = readBit();
64
//最先讀出的是最低位數(shù)據(jù)
65
dat = (j << 7) | (dat >> 1);
66
}
67
return dat;
68
}
69
70
//向DS18B20寫入一字節(jié)數(shù)據(jù)
71
void writeByte(unsigned char dat)
72
{
73
unsigned int i;
74
unsigned char j;
75
bit b;
76
for(j = 0; j < 8; j++)
77
{
78
b = dat & 0x01;
79
dat >>= 1;
80
//寫"1", 讓低電平持續(xù)2個小延時, 高電平持續(xù)8個小延時
81
if(b)
82
{
83
ds = 0;
84
i++; i++;
85
ds = 1;
86
i = 8; while(i>0) i--;
87
}
88
else //寫"0", 讓低電平持續(xù)8個小延時, 高電平持續(xù)2個小延時
89
{
90
ds = 0;
91
i = 8; while(i>0) i--;
92
ds = 1;
93
i++; i++;
94
}
95
}
96
}
97
98
//向DS18B20發(fā)送溫度轉(zhuǎn)換命令
99
void sendChangeCmd()
100
{
101
dsInit(); //初始化DS18B20
102
delay(1); //延時1ms
103
writeByte(0xcc); //寫入跳過序列號命令字
104
writeByte(0x44); //寫入溫度轉(zhuǎn)換命令字
105
}
106
107
//向DS18B20發(fā)送讀取數(shù)據(jù)命令
108
void sendReadCmd()
109
{
110
dsInit();
111
delay(1);
112
writeByte(0xcc); //寫入跳過序列號命令字
113
writeByte(0xbe); //寫入讀取數(shù)據(jù)令字
114
}
115
116
//獲取當前溫度值
117
unsigned int getTmpValue()
118
{
119
unsigned int value; //存放溫度數(shù)值
120
float t;
121
unsigned char low, high;
122
sendReadCmd();
123
//連續(xù)讀取兩個字節(jié)數(shù)據(jù)
124
low = readByte();
125
high = readByte();
126
//將高低兩個字節(jié)合成一個整形變量
127
value = high;
128
value <<= 8;
129
value |= low;
130
//DS18B20的精確度為0.0625度, 即讀回數(shù)據(jù)的最低位代表0.0625度
131
t = value * 0.0625;
132
//將它放大10倍, 使顯示時可顯示小數(shù)點后一位, 并對小數(shù)點后第二2進行4舍5入
133
//如t=11.0625, 進行計數(shù)后, 得到value = 111, 即11.1 度
134
value = t * 10 + 0.5;
135
return value;
136
}
137
138
//顯示當前溫度值, 精確到小數(shù)點后一位
139
void display(unsigned int v)
140
{
141
unsigned char count;
142
unsigned char datas[] = {0, 0, 0};
143
datas[0] = v / 100;
144
datas[1] = v % 100 / 10;
145
datas[2] = v % 10;
146
for(count = 0; count < 3; count++)
147
{
148
//片選
149
wela = 0;
150
P0 = ((0xfe << count) | (0xfe >> (8 - count))); //選擇第(count + 1) 個數(shù)碼管
151
wela = 1; //打開鎖存, 給它一個下降沿量
152
wela = 0;
153
//段選
154
dula = 0;
155
if(count != 1)
156
{
157
P0 = table[datas[count]]; //顯示數(shù)字
158
}
159
else
160
{
161
P0 = tableWidthDot[datas[count]]; //顯示帶小數(shù)點數(shù)字
162
}
163
dula = 1; //打開鎖存, 給它一個下降沿量
164
dula = 0;
165
delay(5); //延時5ms, 即亮5ms
166
167
//清除段先, 讓數(shù)碼管滅, 去除對下一位的影響, 去掉高位對低位重影
168
//若想知道影響效果如何, 可自行去掉此段代碼
169
//因為數(shù)碼管是共陰極的, 所有滅的代碼為: 00H
170
dula = 0;
171
P0 = 0x00; //顯示數(shù)字
172
dula = 1; //打開鎖存, 給它一個下降沿量
173
dula = 0;
174
}
175
}
176
177
void main()
178
{
179
unsigned char i;
180
unsigned int value;
181
while(1)
182
{
183
//啟動溫度轉(zhuǎn)換
184
sendChangeCmd();
185
value = getTmpValue();
186
//顯示3次
187
for(i = 0; i < 3; i++)
188
{
189
display(value);
190
}
191
}
192
}
顯示效果:
流程圖:
改進代碼: 擴大測量范圍, 使可測量范圍為: -55度 ~ +125度, 嚴格按照上面的流程進行軟件設(shè)計
3.15 1:34 修正display()函數(shù)中的下一位顯示對上一位的影響
改進代碼
1
#include
2
#include
3
#include //要用到取絕對值函數(shù)abs()
4
//通過DS18B20測試當前環(huán)境溫度, 并通過數(shù)碼管顯示當前溫度值, 目前顯示范圍: -55~ +125度
5
sbit wela = P2^7; //數(shù)碼管位選
6
sbit dula = P2^6; //數(shù)碼管段選
7
sbit ds = P2^2;
8
int tempValue;
9
10
//0-F數(shù)碼管的編碼(共陰極)
11
unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,
12
0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
13
//0-9數(shù)碼管的編碼(共陰極), 帶小數(shù)點
14
unsigned char code tableWidthDot[]={0xbf, 0x86, 0xdb, 0xcf, 0xe6, 0xed, 0xfd,
15
0x87, 0xff, 0xef};
16
17
//延時函數(shù), 對于11.0592MHz時鐘, 例i=10,則大概延時10ms.
18
void delay(unsigned int i)
19
{
20
unsigned int j;
21
while(i--)
22
{
23
for(j = 0; j < 125; j++);
24
}
25
}
26
27
//初始化DS18B20
28
//讓DS18B20一段相對長時間低電平, 然后一段相對非常短時間高電平, 即可啟動
29
void dsInit()
30
{
31
//對于11.0592MHz時鐘, unsigned int型的i, 作一個i++操作的時間大于為8us
32
unsigned int i;
33
ds = 0;
34
i = 100; //拉低約800us, 符合協(xié)議要求的480us以上
35
while(i>0) i--;
36
ds = 1; //產(chǎn)生一個上升沿, 進入等待應(yīng)答狀態(tài)
37
i = 4;
38
while(i>0) i--;
39
}
40
41
void dsWait()
42
{
43
unsigned int i;
44
while(ds);
45
while(~ds); //檢測到應(yīng)答脈沖
46
i = 4;
47
while(i > 0) i--;
48
}
49
50
//向DS18B20讀取一位數(shù)據(jù)
51
//讀一位, 讓DS18B20一小周期低電平, 然后兩小周期高電平,
52
//之后DS18B20則會輸出持續(xù)一段時間的一位數(shù)據(jù)
53
bit readBit()
54
{
55
unsigned int i;
56
bit b;
57
ds = 0;
58
i++; //延時約8us, 符合協(xié)議要求至少保持1us
59
ds = 1;
60
i++; i++; //延時約16us, 符合協(xié)議要求的至少延時15us以上
61
b = ds;
62
i = 8;
63
while(i>0) i--; //延時約64us, 符合讀時隙不低于60us要求
64
return b;
65
}
66
67
//讀取一字節(jié)數(shù)據(jù), 通過調(diào)用readBit()來實現(xiàn)
68
unsigned char readByte()
69
{
70
unsigned int i;
71
unsigned char j, dat;
72
dat = 0;
73
for(i=0; i<8; i++)
74
{
75
j = readBit();
76
//最先讀出的是最低位數(shù)據(jù)
77
dat = (j << 7) | (dat >> 1);
78
}
79
return dat;
80
}
81
82
//向DS18B20寫入一字節(jié)數(shù)據(jù)
83
void writeByte(unsigned char dat)
84
{
85
unsigned int i;
86
unsigned char j;
87
bit b;
88
for(j = 0; j < 8; j++)
89
{
90
b = dat & 0x01;
91
dat >>= 1;
92
//寫"1", 將DQ拉低15us后, 在15us~60us內(nèi)將DQ拉高, 即完成寫1
93
if(b)
94
{
95
ds = 0;
96
i++; i++; //拉低約16us, 符號要求15~60us內(nèi)
97
ds = 1;
98
i = 8; while(i>0) i--; //延時約64us, 符合寫時隙不低于60us要求
99
}
100
else //寫"0", 將DQ拉低60us~120us
101
{
102
ds = 0;
103
i = 8; while(i>0) i--; //拉低約64us, 符號要求
104
ds = 1;
105
i++; i++; //整個寫0時隙過程已經(jīng)超過60us, 這里就不用像寫1那樣, 再延時64us了
106
}
107
}
108
}
109
110
//向DS18B20發(fā)送溫度轉(zhuǎn)換命令
111
void sendChangeCmd()
112
{
113
dsInit(); //初始化DS18B20, 無論什么命令, 首先都要發(fā)起初始化
114
dsWait(); //等待DS18B20應(yīng)答
115
delay(1); //延時1ms, 因為DS18B20會拉低DQ 60~240us作為應(yīng)答信號
116
writeByte(0xcc); //寫入跳過序列號命令字 Skip Rom
117
writeByte(0x44); //寫入溫度轉(zhuǎn)換命令字 Convert T
118
}
119
120
//向DS18B20發(fā)送讀取數(shù)據(jù)命令
121
void sendReadCmd()
122
{
123
dsInit();
124
dsWait();
125
delay(1);
126
writeByte(0xcc); //寫入跳過序列號命令字 Skip Rom
127
writeByte(0xbe); //寫入讀取數(shù)據(jù)令字 Read Scratchpad
128
}
129
130
//獲取當前溫度值
131
int getTmpValue()
132
{
133
unsigned int tmpvalue;
134
int value; //存放溫度數(shù)值
135
float t;
136
unsigned char low, high;
137
sendReadCmd();
138
//連續(xù)讀取兩個字節(jié)數(shù)據(jù)
139
low = readByte();
140
high = readByte();
141
//將高低兩個字節(jié)合成一個整形變量
142
//計算機中對于負數(shù)是利用補碼來表示的
143
//若是負值, 讀取出來的數(shù)值是用補碼表示的, 可直接賦值給int型的value
144
tmpvalue = high;
145
tmpvalue <<= 8;
146
tmpvalue |= low;
147
value = tmpvalue;
148
149
//使用DS18B20的默認分辨率12位, 精確度為0.0625度, 即讀回數(shù)據(jù)的最低位代表0.0625度
150
t = value * 0.0625;
151
//將它放大100倍, 使顯示時可顯示小數(shù)點后兩位, 并對小數(shù)點后第三進行4舍5入
152
//如t=11.0625, 進行計數(shù)后, 得到value = 1106, 即11.06 度
153
//如t=-11.0625, 進行計數(shù)后, 得到value = -1106, 即-11.06 度
154
value = t * 100 + (value > 0 ? 0.5 : -0.5); //大于0加0.5, 小于0減0.5
155
return value;
156
}
157
158
unsigned char const timeCount = 3; //動態(tài)掃描的時間間隔
159
//顯示當前溫度值, 精確到小數(shù)點后一位
160
//若先位選再段選, 由于IO口默認輸出高電平, 所以當先位選會使數(shù)碼管出現(xiàn)亂碼
161
void display(int v)
162
{
163
unsigned char count;
164
unsigned char datas[] = {0, 0, 0, 0, 0};
165
unsigned int tmp = abs(v);
166
datas[0] = tmp / 10000;
167
datas[1] = tmp % 10000 / 1000;
168
datas[2] = tmp % 1000 / 100;
169
datas[3] = tmp % 100 / 10;
170
datas[4] = tmp % 10;
171
if(v < 0)
172
{
173
//關(guān)位選, 去除對上一位的影響
174
P0 = 0xff;
175
wela = 1; //打開鎖存, 給它一個下降沿量
176
wela = 0;
177
//段選
178
P0 = 0x40; //顯示"-"號
179
dula = 1; //打開鎖存, 給它一個下降沿量
180
dula = 0;
181
182
//位選
183
P0 = 0xfe;
184
wela = 1; //打開鎖存, 給它一個下降沿量
185
wela = 0;
186
delay(timeCount);
187
}
188
for(count = 0; count != 5; count++)
189
{
190
//關(guān)位選, 去除對上一位的影響
191
P0 = 0xff;
192
wela = 1; //打開鎖存, 給它一個下降沿量
193
wela = 0;
194
//段選
195
if(count != 2)
196
{
197
/* if((count == 0 && datas[count] == 0)
198
|| ((count == 1 && datas[count] == 0) && (count == 0 && datas[count - 1] == 0)))
199
{
200
P0 = 0x00; //當最高位為0時, 不作顯示
201
}
202
else*/
203
P0 = table[datas[count]]; //顯示數(shù)字
204
}
205
else
206
{
207
P0 = tableWidthDot[datas[count]]; //顯示帶小數(shù)點數(shù)字
208
}
209
dula = 1; //打開鎖存, 給它一個下降沿量
210
dula = 0;
211
212
//位選
213
P0 = _crol_(0xfd, count); //選擇第(count + 1) 個數(shù)碼管
214
wela = 1; //打開鎖存, 給它一個下降沿量
215
wela = 0;
216
delay(timeCount);
217
}
218
}
219
220
void main()
221
{
222
unsigned char i;
223
224
while(1)
225
{
226
//啟動溫度轉(zhuǎn)換
227
sendChangeCmd();
228
//顯示5次
229
for(i = 0; i < 40; i++)
230
{
231
display(tempValue);
232
}
233
tempValue = getTmpValue();
234
}
235
}
改進后的效果圖:
只有一位小數(shù)
兩位小數(shù), 并消除下一位對上一位的影響