找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 6079|回復(fù): 19
收起左側(cè)

單片機(jī)DS18B20多路溫度采集顯示 Proteus仿真程序

  [復(fù)制鏈接]
ID:856329 發(fā)表于 2021-10-15 23:27 | 顯示全部樓層 |閱讀模式
本帖最后由 Lxy18 于 2021-10-31 23:51 編輯

認(rèn)真學(xué)習(xí)了DS18B20的手冊(cè),發(fā)現(xiàn)DS18B20單總線實(shí)現(xiàn)多路采集,需要讀取ROM指令,通過(guò)ROM指令讀取指定的DS18B20溫度。操作相當(dāng)麻煩,參考了CSDN的例子,最后還是沒(méi)搞出來(lái)。后來(lái)就想能不能把8個(gè)DS18B20連接到8個(gè)IO口上,然后就是分別讀取8個(gè)IO口的溫度數(shù)據(jù),這樣的話就需要8個(gè)驅(qū)動(dòng)程,理論可行,需要的程序相當(dāng)多,所以這樣也不可行。然后就想,如果用一個(gè)驅(qū)動(dòng)程序,在函數(shù)中改變總線變量定義的IO口,也就是改變變量的地址,查找很多資料后,發(fā)現(xiàn)這根本不可能。

最后,就想有沒(méi)有一種芯片可以一個(gè)IO口選通8個(gè)口,經(jīng)過(guò)一番努力之后,果然有,74HC4051,8通道模擬多路選擇器/多路分配器,帶有3個(gè)數(shù)字選擇端(S0至S2),1個(gè)低有效使能端(E),8個(gè)獨(dú)立輸入/輸出端(Y0至Y7)和1個(gè)公共輸入/輸出端(Z)。

然后就是畫(huà)仿真,寫(xiě)程序了。經(jīng)過(guò)測(cè)試后非常好用,程序也非常簡(jiǎn)單。

仿真截圖.png

主程序如下,只實(shí)現(xiàn)了基本的8路溫度采集,溫度報(bào)警、串口什么的都沒(méi)加。


  1. /******************************************************************************
  2. 單片機(jī)八路溫度采集系統(tǒng)
  3. *******************************************************************************/
  4. #include <reg52.h>                        
  5. #include "delay.h"
  6. #include "lcd1602.h"
  7. #include "DS18B20.h"

  8. #define uchar unsigned char          //對(duì)數(shù)據(jù)類型定義
  9. #define uint  unsigned int

  10. /****************************端口定義******************************************/                                 
  11. /*----74HC4051端口定義------------*/

  12. sbit HC4051_A=P2^0;
  13. sbit HC4051_B=P2^1;
  14. sbit HC4051_C=P2^2;
  15.                                                          
  16. /****************************定義變量******************************************/
  17. float Temp[8];                        //溫度變量
  18. uchar Temp_Str[3];            //數(shù)組變量存放溫度數(shù)據(jù)        
  19. /*****************************************************************************/
  20. /***************************函數(shù)聲明******************************************/
  21. void HC4051_CH(uchar ch);//HC4051通道選擇函數(shù)
  22. /******************************************************************************
  23. * 函 數(shù) 名         : 主函數(shù)
  24. * 函數(shù)功能                   :
  25. * 輸    入         : 無(wú)
  26. * 輸    出         : 無(wú)
  27. *******************************************************************************/
  28. void main()
  29. {
  30.         uchar i;
  31.         Lcd1602_Init();              //1602初始化
  32.         Lcd1602_Write_Cmd(0x01);     //清屏
  33.         for(i=0;i<8;i++)                         //8個(gè)溫度傳感器初始化
  34.         {
  35.                 HC4051_CH(i);                          //選擇通道
  36.                 DS18B20_Init();                         //溫度傳感器初始化
  37.         }
  38.         while(1)
  39.         {
  40.                 for(i=0;i<8;i++)                 //讀取8路溫度傳感器溫度值
  41.                 {
  42.                         HC4051_CH(i);                                            //選擇通道
  43.                         Temp[i]=DS18B20_ReadTemp();                   //讀取溫度值
  44.                         if(Temp[i]>0)                                           //正溫度
  45.                         {
  46.                                 Temp_Str[0]=(int)Temp[i]/100+48;          //提取溫度百、十、個(gè)位
  47.                                 Temp_Str[1]=((int)Temp[i]%100)/10+48;
  48.                                 Temp_Str[2]=(int)Temp[i]%10+48;
  49.                         }
  50.                         else                                                           //負(fù)溫度
  51.                         {
  52.                                 Temp[i]=-Temp[i];                           //將負(fù)數(shù)轉(zhuǎn)換為正數(shù)
  53.                                 Temp_Str[0]='-';                           //顯示“—”號(hào)
  54.                                 Temp_Str[1]=((int)Temp[i]%100)/10+48; //提取溫度個(gè)、十位
  55.                                 Temp_Str[2]=(int)Temp[i]%10+48;
  56.                                 Temp[i]=-Temp[i];                           //將溫度恢復(fù)
  57.                         }
  58.                         LcdShowStr(0+4*(i%4),i/4,Temp_Str);//將溫度顯示在LCD上
  59.                 }        
  60.                 Delay_Ms(30);
  61.         }
  62. }
  63. /******************************************************************************
  64. * 函 數(shù) 名         : HC4051_CH(uchar ch)
  65. * 函數(shù)功能                   : HC4051通道選擇函數(shù)
  66. * 輸    入         : ch:選擇的通道
  67. * 輸    出         : 無(wú)
  68. *******************************************************************************/
  69. void HC4051_CH(uchar ch)
  70. {
  71.         HC4051_A=ch%2;
  72.         HC4051_B=(ch%4)/2;
  73.         HC4051_C=ch/4;        
  74. }
復(fù)制代碼

評(píng)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

相關(guān)帖子

回復(fù)

使用道具 舉報(bào)

ID:795427 發(fā)表于 2021-10-31 20:18 | 顯示全部樓層
采用74HC4051思路方法不錯(cuò)。學(xué)習(xí)學(xué)習(xí)!
回復(fù)

使用道具 舉報(bào)

ID:856329 發(fā)表于 2021-10-31 23:33 | 顯示全部樓層
發(fā)現(xiàn)被人拿到咸魚(yú)賣了,30元一個(gè)
回復(fù)

使用道具 舉報(bào)

ID:744809 發(fā)表于 2021-11-3 15:07 | 顯示全部樓層
可以直接把八路都接到一根引腳的,然后用ID的方式去讀不同芯片的溫度
回復(fù)

使用道具 舉報(bào)

ID:654797 發(fā)表于 2021-12-13 07:27 | 顯示全部樓層
Lxy18 發(fā)表于 2021-10-31 23:33
發(fā)現(xiàn)被人拿到咸魚(yú)賣了,30元一個(gè)

這都有人買(mǎi)呀
回復(fù)

使用道具 舉報(bào)

ID:654797 發(fā)表于 2021-12-13 07:38 | 顯示全部樓層
不是程序多,是那個(gè)程序要改成多端口的,你是從網(wǎng)上抄來(lái)的吧!網(wǎng)上那個(gè)只能用一個(gè)端口,你要是只改函數(shù)名,就想用肯定多了,你要將程序的函數(shù)都改成有參數(shù)的,調(diào)用時(shí)通過(guò)參數(shù)確定用那個(gè)端口,這樣可以減少代碼量
回復(fù)

使用道具 舉報(bào)

ID:856329 發(fā)表于 2022-1-20 11:40 | 顯示全部樓層
vscos 發(fā)表于 2021-12-13 07:38
不是程序多,是那個(gè)程序要改成多端口的,你是從網(wǎng)上抄來(lái)的吧!網(wǎng)上那個(gè)只能用一個(gè)端口,你要是只改函數(shù)名, ...

程序原創(chuàng)的!!io作為函數(shù)參數(shù),就不可能實(shí)現(xiàn),我也想過(guò)這樣。現(xiàn)在單總線ROM方式已經(jīng)搞出來(lái)了。
回復(fù)

使用道具 舉報(bào)

ID:856329 發(fā)表于 2022-1-20 11:45 | 顯示全部樓層
vscos 發(fā)表于 2021-12-13 07:38
不是程序多,是那個(gè)程序要改成多端口的,你是從網(wǎng)上抄來(lái)的吧!網(wǎng)上那個(gè)只能用一個(gè)端口,你要是只改函數(shù)名, ...

按你所說(shuō),用8個(gè)IO口接8個(gè)18B20,溫度讀取函數(shù)設(shè)置通道選擇參數(shù)(IO口不能作為參數(shù)輸入),那在函數(shù)中如何根據(jù)輸入的通道切換操作的IO口?
回復(fù)

使用道具 舉報(bào)

ID:161164 發(fā)表于 2022-1-20 14:29 | 顯示全部樓層
Lxy18 發(fā)表于 2022-1-20 11:45
按你所說(shuō),用8個(gè)IO口接8個(gè)18B20,溫度讀取函數(shù)設(shè)置通道選擇參數(shù)(IO口不能作為參數(shù)輸入),那在函數(shù)中如何 ...

對(duì)~
但I(xiàn)O口的讀寫(xiě)不能直接P00 = 1 或 if(P00)
要參考arduino的寫(xiě)法
  1. void digitalWrite(char PinNum, bit Command){
  2.         if(Command){
  3.                 P0 |= 0x01 << PinNum;
  4.         }else{
  5.                 P0 &= ~(0x01 << PinNum);
  6.         }
  7. }
  8. bit digitalRead(char PinNum){
  9.         if(P0 & (0x01<<PinNum))
  10.                 return 1;
  11.         else
  12.                 return 0;
  13. }
復(fù)制代碼
回復(fù)

使用道具 舉報(bào)

ID:856329 發(fā)表于 2022-3-14 08:50 | 顯示全部樓層
lkc8210 發(fā)表于 2022-1-20 14:29
對(duì)~
但I(xiàn)O口的讀寫(xiě)不能直接P00 = 1 或 if(P00)
要參考arduino的寫(xiě)法

原來(lái)如此,學(xué)到了學(xué)到了。
回復(fù)

使用道具 舉報(bào)

ID:1016228 發(fā)表于 2022-4-6 20:47 | 顯示全部樓層
lkc8210 發(fā)表于 2022-1-20 14:29
對(duì)~
但I(xiàn)O口的讀寫(xiě)不能直接P00 = 1 或 if(P00)
要參考arduino的寫(xiě)法

這兩個(gè)函數(shù)什么意思啊,能吧根據(jù)參數(shù)選擇IO口寫(xiě)具體點(diǎn)嗎,單片機(jī),求求大佬解惑了
回復(fù)

使用道具 舉報(bào)

ID:1016228 發(fā)表于 2022-4-6 21:19 | 顯示全部樓層
lkc8210 發(fā)表于 2022-1-20 14:29
對(duì)~
但I(xiàn)O口的讀寫(xiě)不能直接P00 = 1 或 if(P00)
要參考arduino的寫(xiě)法

哦,就是把所有的P0^n=i;換成digitalWrite(n,i)。P0^n換成digitalRead(n),是嗎?
我這樣做了,可是出錯(cuò)了呀,數(shù)據(jù)讀不出來(lái)
回復(fù)

使用道具 舉報(bào)

ID:1016228 發(fā)表于 2022-4-6 21:21 | 顯示全部樓層
lkc8210 發(fā)表于 2022-1-20 14:29
對(duì)~
但I(xiàn)O口的讀寫(xiě)不能直接P00 = 1 或 if(P00)
要參考arduino的寫(xiě)法
  1. #include "reg52.h"

  2. void digitalWrite(char PinNum, bit Command){
  3.         if(Command){
  4.                 P1 |= 0x01 << PinNum;
  5.         }else{
  6.                 P1 &= ~(0x01 << PinNum);
  7.         }
  8. }

  9. bit digitalRead(char PinNum){
  10.         if(P1 & (0x01<<PinNum))
  11.                 return 1;
  12.         else
  13.                 return 0;
  14. }

  15. //單總線延時(shí)函數(shù)
  16. void Delay_OneWire(unsigned int t){
  17.   while(t--);
  18. }

  19. //通過(guò)單總線向DS18B20寫(xiě)一個(gè)字節(jié)
  20. void Write_DS18B20(unsigned char N,unsigned char dat){
  21.   unsigned char i;
  22.   for(i=0;i<8;i++){
  23.     digitalWrite(N,0);
  24.     digitalWrite(N,dat&0x01);
  25.     Delay_OneWire(5);
  26.     digitalWrite(N,1);
  27.     dat >>= 1;
  28.   }
  29.   Delay_OneWire(5);
  30. }

  31. //從DS18B20讀取一個(gè)字節(jié)
  32. unsigned char Read_DS18B20(unsigned char N){
  33.   unsigned char i;
  34.   unsigned char dat;

  35.   for(i=0;i<8;i++){
  36.     digitalWrite(N,0);
  37.     dat >>= 1;
  38.     digitalWrite(N,1);
  39.     if(digitalRead(N)){
  40.       dat |= 0x80;
  41.     }            
  42.     Delay_OneWire(5);
  43.   }
  44.   return dat;
  45. }

  46. //DS18B20設(shè)備初始化
  47. bit init_ds18b20(unsigned char N){
  48.   bit initflag = 0;
  49.          
  50.   digitalWrite(N,1);
  51.   Delay_OneWire(12);
  52.   digitalWrite(N,0);
  53.   Delay_OneWire(80);
  54.   digitalWrite(N,1);
  55.   Delay_OneWire(10);
  56.   initflag = digitalRead(N);
  57.   Delay_OneWire(5);
  58.   
  59.   return initflag;
  60. }

  61. unsigned int rd_temperature(unsigned char N){
  62.   unsigned char low, high;

  63.   init_ds18b20(N);                               // 初始化
  64.   Write_DS18B20(N,0xCC);                          // 跳過(guò)ROM
  65.   Write_DS18B20(N,0x44);                          // 啟動(dòng)溫度轉(zhuǎn)換

  66.   init_ds18b20(N);
  67.   Write_DS18B20(N,0xCC);
  68.   Write_DS18B20(N,0xBE);                          // 讀取寄存器
  69.   low = Read_DS18B20(N);                         // 低字節(jié)
  70.   high = Read_DS18B20(N);                        // 高字節(jié)

  71.   return (high<<8)+low;
  72. }
復(fù)制代碼
就這個(gè)代碼,rd_temperature函數(shù)讀數(shù)據(jù)
回復(fù)

使用道具 舉報(bào)

ID:1110110 發(fā)表于 2024-1-25 15:34 | 顯示全部樓層
太感謝了,DIY小玩意就做關(guān)于這個(gè)的方向,只不過(guò)是需要將讀取的八路溫度數(shù)據(jù)傳輸?shù)絣abview上位機(jī)進(jìn)行檢測(cè),作者是否對(duì)labview上位機(jī)有研究?
回復(fù)

使用道具 舉報(bào)

ID:383215 發(fā)表于 2024-1-25 17:47 | 顯示全部樓層
單片機(jī)的應(yīng)用思路,就是要用好單片機(jī)的內(nèi)部資源包括程序讓外圍電路越簡(jiǎn)單越好,樓主增加74HC4051讓單片機(jī)編程變的簡(jiǎn)單的思路完全背離了單片機(jī)應(yīng)用的基本思路,肯定是不可取的。雖然74HC4051只是幾毛錢(qián),但是,增加了74HC4051電路就復(fù)雜了,增加74HC4051讀寫(xiě)8個(gè)18B20,依然用掉單片機(jī)的4個(gè)I/O口,相當(dāng)于用4個(gè)I/O口換取8個(gè)18B20的讀寫(xiě),還增加了一片74HC4051,一點(diǎn)也不劃算。單片機(jī)讀取8個(gè)18B20溫度的正確編程思路只有兩個(gè),一個(gè)是用8個(gè)I/O口連接8個(gè)18B20,編程思路是同時(shí)對(duì)8個(gè)18B20做初始化和跳過(guò)ROM指令的操作,然后把8個(gè)18B20的溫度讀出來(lái),另一個(gè)是8個(gè)18B20的8個(gè)單總線接單片機(jī)的一個(gè)I/O口,用匹配ROM的方法把每一個(gè)18B20的溫度讀出來(lái),無(wú)論是8個(gè)I/O口接8個(gè)18B20還是8個(gè)18B20的8個(gè)單總線接單片機(jī)的一個(gè)I/O口,都可以用細(xì)化到步的編程方法,提高單片機(jī)的CPU應(yīng)用率,頂多是讀取溫度的時(shí)間慢一點(diǎn)而已(最多慢零點(diǎn)零幾秒到零點(diǎn)幾秒),溫度是一個(gè)漸變的過(guò)程,讀取溫度的時(shí)間慢一點(diǎn)對(duì)絕大多數(shù)的溫度控制毫無(wú)影響。個(gè)人意見(jiàn),僅供參考。

評(píng)分

參與人數(shù) 2黑幣 +25 收起 理由
liang1981 + 5 正確思路
admin + 20 回帖助人的獎(jiǎng)勵(lì)!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:1110110 發(fā)表于 2024-1-25 20:15 | 顯示全部樓層
請(qǐng)教一下關(guān)于lcd1602的代碼怎樣編寫(xiě)
回復(fù)

使用道具 舉報(bào)

ID:856329 發(fā)表于 2024-1-26 11:25 | 顯示全部樓層
kmsj 發(fā)表于 2024-1-25 17:47
單片機(jī)的應(yīng)用思路,就是要用好單片機(jī)的內(nèi)部資源包括程序讓外圍電路越簡(jiǎn)單越好,樓主增加74HC4051讓單片機(jī)編 ...

前面已經(jīng)說(shuō)明,最開(kāi)始匹配rom的程序沒(méi)做出來(lái),所以才選擇這個(gè)方案,雖然增加了io口,增加了一個(gè)芯片,但是可以實(shí)現(xiàn)功能,而且相對(duì)于匹配rom替換DS18B20不需要重新讀取rom,不需要修改程序。各有優(yōu)缺點(diǎn)。工程角度肯定考慮成本,但是這僅僅是學(xué)習(xí)交流使用,交作品用的。
回復(fù)

使用道具 舉報(bào)

ID:383215 發(fā)表于 2024-1-26 18:35 | 顯示全部樓層
Lxy18 發(fā)表于 2024-1-26 11:25
前面已經(jīng)說(shuō)明,最開(kāi)始匹配rom的程序沒(méi)做出來(lái),所以才選擇這個(gè)方案,雖然增加了io口,增加了一個(gè)芯片,但 ...

如果僅僅是交作品混學(xué)分,就沒(méi)有討論的意義了,就算是交作品混學(xué)分,用匹配ROM或者8個(gè)I/O口讀出8個(gè)18B20的溫度,你的老師為你負(fù)責(zé)的話,得到的學(xué)分更高才對(duì),最關(guān)鍵可以提高自己的編程水平。
回復(fù)

使用道具 舉報(bào)

ID:73422 發(fā)表于 2024-2-18 20:58 | 顯示全部樓層
可以并行一次性讀取8個(gè)DS18B20里的數(shù)據(jù)放入8個(gè)單元的數(shù)組里,然后對(duì)這些數(shù)據(jù)進(jìn)行處理就可以了。這個(gè)方法程序簡(jiǎn)單,不需要多余的電路,也不用讀ID,就是要占用8個(gè)IO口。
回復(fù)

使用道具 舉報(bào)

ID:1110110 發(fā)表于 2024-2-25 10:59 | 顯示全部樓層
可以分享一下全套源碼嗎?
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表