|
分享我的期末作業(yè),基于51單片機(jī)的多點(diǎn)溫度測(cè)量
同時(shí)多點(diǎn)溫度測(cè)量是在單總線上掛載多個(gè)18b20溫度傳感器
單片機(jī)源程序如下:
- #include <reg51.h>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define MAXNUM 4 //宏定義單總線上最大可掃描DS18B20個(gè)數(shù)
- //*****************************//
- //**初始定義管腳、變量與數(shù)組***//
- //*****************************//
- sbit DS=P3^7;
- sbit lcden=P2^7;//液晶使能端
- sbit lcdrs=P2^6;//液晶數(shù)0據(jù)命令選擇端
- sbit lcdrw=P2^5;
- union{
- uchar c[2];
- uint x;
- }temp;
- uchar time=0;
- uint cc,xs; //變量cc中保存計(jì)算出的溫度值的整數(shù)部分,xs保存計(jì)算出的溫度值的小數(shù)部分的第一位
- uchar idata disbuffer[6]; //LCD顯示緩存數(shù)組
- uchar idata ID[4][8]={0};//{{0x28,0xff,0x80,0x2e,0x70,0x16,0x03,0xad},{0x28,0xff,0x95,0xb5,0x81,0x16,0x03,0x50},{0x28,0xff,0x02,0x96,0xa1,0x16,0x04,0x59},{0x28,0xff,0xf0,0xf5,0x62,0x16,0x04,0xd3}};
- //{"82FF08E2076130DA","82FF595B18613005","82FF20691A614095","82FF0F5F2661403D"}; //用于記錄各DS18B20的ROM序列號(hào)
- uchar idata RomID_temp[8]; //匹配DS18B20時(shí)臨時(shí)記錄要匹配DS18B20的序列號(hào)
- uchar east[5]=" EAST";
- uchar west[5]=" WEST";
- uchar south[5]="SOUTH";
- uchar north[5]="NORTH";
- uchar m=0;
- uchar num=0;
- //***************************//
- //*******18b20時(shí)序延時(shí)*******//
- //***************************//
- void delay(uint i) //i*9.62us
- {
- uint j;
- for(j=i;j>0;j--);
- }
-
- void delay_ms(uchar i) //(j*2+1+2)*i+5
- { uchar j; //12MHz 0.5*i ms
- do{j=248;
- do{j--;}while(j);
- i--;
- }while(i);
- }
-
- void delay_2us(uchar i) // 2*i+5 us
- {
- while(--i);
- }
- //**************************//
- //******18b20子程***********//
- //**************************//
- uchar DS_init(void) //18B20復(fù)位,初始化函數(shù)
- {
- uchar presence;
- DS=0; delay_2us(250); //根據(jù)DS18B20的復(fù)位時(shí)序.先把總線拉低555us
- DS=1; delay_2us(30); //再釋放總線,65us后讀取DS18B20發(fā)出的信號(hào)
- presence=DS; delay_2us(250); //如果復(fù)位成功,則presence的值為0;否則為1
- return (presence); //返回0則初始化成功,否則失敗
- }
-
- uchar read_byte(void) //讀1字節(jié)
- {
- uchar i,j,dat=0;
- for(i=1;i<=8;i++) //作8個(gè)循環(huán),讀出的8位組成一個(gè)字節(jié)
- {DS=0; _nop_(); //先將總線拉低1us,
- DS=1; delay_2us(2); //再釋放總線,產(chǎn)生讀起始信號(hào),延遲9us后讀取總線上的DS18B20發(fā)出的值
- j=DS; delay_2us(30); //一位讀完后,延遲65us后讀下一位
- dat=(j<<7)|(dat>>1); //讀出的數(shù)據(jù)最低位在一個(gè)字節(jié)的最低位,這樣剛好一個(gè)字節(jié)在DAT里
- }
- return(dat);
- }
-
- uchar read_2bit(void) //讀2位
- {
- uchar i=0,j=0;
- DS=0; _nop_(); //先將總線拉低1us,
- DS=1; delay_2us(2); //再釋放總線,產(chǎn)生讀起始信號(hào),延遲9us后讀取總線上的DS18B20發(fā)出的值
- j=DS; delay_2us(30); //一位讀完后,延遲65us后讀下一位
- DS=0; _nop_();
- DS=1; delay_2us(2);
- i=DS; delay_2us(30);
- i=j*2+i; //將讀出的兩位放到變量i中,其中第一個(gè)讀出的位處于i的第1位;而第二個(gè)讀出的位處于i的第0位
- return(i);
- }
-
- void write_byte(uchar dat) //寫(xiě)1字節(jié)
- {
- uchar i;
- for(i=0;i<8;i++) //作8個(gè)循環(huán),寫(xiě)入的8位組成一個(gè)字節(jié)
- {DS=0; //先將總線拉低
- DS = dat&0x01; //向總線上放入要寫(xiě)的值
- delay_2us(50); //延遲105us,以使DS18B20能采樣到要寫(xiě)入的值
- DS = 1; //釋放總線,準(zhǔn)備寫(xiě)入下一位
- dat>>=1; //將要寫(xiě)的下一位移到dat的最低位
- }
- }
-
- void write_bit(bit dat) //寫(xiě)1位
- {
- DS=0; //先將總線拉低
- DS=dat; //向總線上放入要寫(xiě)的值
- delay_2us(50); //延遲105us,以使DS18B20能采樣到要寫(xiě)入的值
- DS = 1; //釋放總線
- }
- //************************//
- //*******1602延時(shí)*********//
- //************************//
- void delay1(uint z)
- {
- uint i,j;
- for(i=z;i>0;i--)
- for(j=110;j>0;j--);
- }
- //************************//
- //******1602子程**********//
- //************************//
- void write_com(uchar com) //寫(xiě)命令
- {
- lcdrs=0;//選擇寫(xiě)命令模式
- P0=com;//將要寫(xiě)的命令字送到數(shù)據(jù)總線上
- delay1(5);//稍作延時(shí)以待數(shù)據(jù)穩(wěn)定
- lcden=1;//使能端給一高電平脈沖,因?yàn)槌跏蓟瘮?shù)中已將lcden置零
- delay1(5);//稍作延時(shí)
- lcden=0;//將使能端置零完成高脈沖
- }
- void write_data(uchar date) //寫(xiě)數(shù)據(jù)
- {
- lcdrs=1;//選擇寫(xiě)數(shù)據(jù)操作
- P0=date;//將要寫(xiě)的數(shù)據(jù)送到數(shù)據(jù)總線上
- delay1(5);//稍作延時(shí)
- lcden=1;//使能端給一高電平脈沖
- delay1(5);
- lcden=0;
- }
- void init() //1602初始化
- {
- lcdrw=0;
- lcden=0;
- write_com(0x38);//設(shè)置16*2顯示,5*7點(diǎn)陣,8位數(shù)據(jù)接口
- write_com(0x0c);//設(shè)置開(kāi)顯示,不顯示光標(biāo)
- write_com(0x06);//寫(xiě)一個(gè)字節(jié)后地址指針加1
- write_com(0x01);//顯示清零,數(shù)據(jù)指針清零
- write_com(0x80);//設(shè)置數(shù)據(jù)指針起點(diǎn)
- }
- //****************************//
- //***讀取18b20溫度數(shù)據(jù)子程 ***//
- //****************************//
- void Read_Temperature_rom(void) //讀取溫度函數(shù)
- { uchar i;
- DS_init();
- write_byte(0x55); //匹配ROM
- for(i=0;i<8;i++) //發(fā)出64位ROM編碼
- write_byte(RomID_temp[i]);
- write_byte(0x44); //開(kāi)始轉(zhuǎn)換溫度
- DS_init();
- write_byte(0x55); //匹配ROM
- for(i=0;i<8;i++) //發(fā)出64位ROM編碼
- write_byte(RomID_temp[i]);
- write_byte(0xBE); //發(fā)讀溫度命令
- temp.c[1]=read_byte(); //讀低字節(jié),之所以c[1]中放低字節(jié),是因?yàn)镃51采用的是大端格式
- temp.c[0]=read_byte(); //讀高字節(jié),之所以c[0]中放低字節(jié),是因?yàn)镃51采用的是大端格式
- //共用體定義
- }
-
- void Temperature_cov(void) //溫度轉(zhuǎn)化
- {
- cc=temp.x/16; //計(jì)算出溫度值的整數(shù)部分,這個(gè)語(yǔ)句相當(dāng)于數(shù)值乘0.0625再取整數(shù)部分
- xs=temp.x&0x0f; //取溫度值小數(shù)部分的第一位
- xs=xs*10; //這兩條語(yǔ)句相當(dāng)于乘0.625,得小數(shù)位的第一位,注意不是乘0.0625
- xs=xs/16;
- }
- //***********************//
- //******顯示子程*********//
- //***********************//
- void display_m(void) //顯示18b20個(gè)數(shù)或方向
- {
- uchar i;
- write_com(0x8B);
- //write_data('0'+m);
- if(m==0)
- for(i=0;i<5;i++)
- {write_data(east[i]);}
- if(m==1)
- for(i=0;i<5;i++)
- {write_data(west[i]);}
- if(m==2)
- for(i=0;i<5;i++)
- {write_data(south[i]);}
- if(m==3)
- for(i=0;i<5;i++)
- {write_data(north[i]);}
- }
- void display_ROMID(void) //顯示序列號(hào)
- {
- uchar tmp[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,
- 0x37,0x38,0x39,0x41,0x42,0x43,0x44,0x45,0x46};
- uchar k,i;
- uchar disbuffer_rom[16];
- disbuffer_rom[0]=(ID[m][k]&0x0F);
- disbuffer_rom[1]=((ID[m][k]&0xF0)>>4);
- disbuffer_rom[2]=(ID[m][k+1]&0x0F);
- disbuffer_rom[3]=((ID[m][k+1]&0xF0)>>4);
- disbuffer_rom[4]=(ID[m][k+2]&0x0F);
- disbuffer_rom[5]=((ID[m][k+2]&0xF0)>>4);
- disbuffer_rom[6]=(ID[m][k+3]&0x0F);
- disbuffer_rom[7]=((ID[m][k+3]&0xF0)>>4);
- disbuffer_rom[8]=(ID[m][k+4]&0x0F);
- disbuffer_rom[9]=((ID[m][k+4]&0xF0)>>4);
- disbuffer_rom[10]=(ID[m][k+5]&0x0F);
- disbuffer_rom[11]=((ID[m][k+5]&0xF0)>>4);
- disbuffer_rom[12]=(ID[m][k+6]&0x0F);
- disbuffer_rom[13]=((ID[m][k+6]&0xF0)>>4);
- disbuffer_rom[14]=(ID[m][k+7]&0x0F);
- disbuffer_rom[15]=((ID[m][k+7]&0xF0)>>4);
- write_com(0x80+0x40);
- for(i=0;i<16;i++)
- {
-
- write_data(tmp[disbuffer_rom[i]]); //1602寫(xiě)入序列號(hào)
- }
- }
-
- void display(void) //溫度顯示
- {
- disbuffer[0]='+';
- disbuffer[1]=cc/10;
- disbuffer[2]=cc%10;
- disbuffer[3]='.';
- disbuffer[4]=xs;
- disbuffer[5]='C';
- write_com(0x80);
- write_data(disbuffer[0]);
- write_com(0x81);
- write_data('0'+disbuffer[1]);
- write_com(0x82);
- write_data('0'+disbuffer[2]);
- write_com(0x83);
- write_data(disbuffer[3]);
- write_com(0x84);
- write_data('0'+disbuffer[4]);
- write_com(0x85);
- write_data(disbuffer[5]);
- }
-
- void diplay_final(void) //顯示所用到的18b20的實(shí)時(shí)溫度
- { uint q;
- for(q=0;q<8;q++)
- {
- RomID_temp[q]=ID[m][q]; //給序列號(hào),等待匹配
- }
- Read_Temperature_rom(); //讀取溫度
- Temperature_cov(); //溫度轉(zhuǎn)換
- display(); //顯示溫度
- }
- //****************************//
- //*****多點(diǎn)18b20搜索子程******//
- //****************************//
- void search_rom(void) //遍歷搜索單線上所連的所有18b20的序列號(hào)
- {
- uchar k,l=0,chongtuwei,m,n,a;
- uchar _00web[MAXNUM]={0};
- do
- {
- DS_init(); //復(fù)位單總線上的所有DS18B20
- write_byte(0xf0); //單片機(jī)發(fā)布搜索命令
- for(m=0;m<8;m++)
- {
- uchar s=0; //s用來(lái)記錄本次循環(huán)得到的1個(gè)字節(jié)(8位)序列號(hào)
- for(n=0;n<8;n++)
- {
- k=read_2bit(); //讀第m*8+n位的原碼和反碼,保存在k中
- k=k&0x03; //屏蔽掉k中其它位的干擾,為下一步判斷作準(zhǔn)備
- s>>=1; //s右移一位,即把上一次循環(huán)得到的位值右移一位,
- //這樣執(zhí)行完一次n為變量的循環(huán),便可得到一個(gè)字節(jié)的ROM號(hào)
- if(k==0x01) //k為01,表明讀到的數(shù)據(jù)為0,即所有器件在這一位都為0,所以向總線上寫(xiě)0
- //同時(shí)對(duì)s的值不進(jìn)行操作,即這位的序列號(hào)記為0
- {
- write_bit (0);
- }
- else if(k==0x02)//k為02,表明讀到的數(shù)據(jù)為1,即所有器件在這一位都為1,所以向總線上寫(xiě)1
- {
- s=s|0x80; //記錄下此位的值,即s的最高位置1
- write_bit (1);
- }
- else if(k==0x00)
- {
- chongtuwei=m*8+n+1; //記錄下這個(gè)沖突位發(fā)生的位置;之所以加1是為了讓_00web數(shù)組中的第一位保持0不變,
- //便于判斷搜索循環(huán)是否結(jié)束;
- if(chongtuwei>_00web[l])//如果沖突位比標(biāo)志00位的位高,即發(fā)現(xiàn)了新的沖突位,那么這位寫(xiě)0
- {
- write_bit (0);
- _00web[++l]=chongtuwei; //依次記錄位比沖突標(biāo)志位高的沖突位在_00web數(shù)組中
- }
- else if(chongtuwei<_00web[l]) //如果沖突位比標(biāo)志00位的位低,那么把ID中這位所在的字節(jié)右移n位,
- { //從而得到這位先前已經(jīng)寫(xiě)過(guò)的值,如果為0,說(shuō)明這位先前寫(xiě)的是0,那么繼續(xù)寫(xiě)0,
- // 如果這位先前寫(xiě)的是1,那么繼續(xù)寫(xiě)1
- a=(ID[num-1][m]>>n)&0x01;
- s=s|(a<<7); //記錄下此位的值
- write_bit(a);
- }
- else if(chongtuwei==_00web[l])//如果沖突位就是標(biāo)志00位,那么s的最高位置1,即這位記為1,同時(shí)向總線上寫(xiě)1;
- //之所以不寫(xiě)0,是因?yàn)榍懊嬉呀?jīng)寫(xiě)過(guò)0,再寫(xiě)0,就得不到遍歷的效果.
- {
- s=s|0x80;
- write_bit (1);
- l=l-1; //改變標(biāo)志00位的位置,即向前推一個(gè)00位,并且是往低位方向推
- }
- }
- }
- ID[num][m]=s;
- }
- num++; //DS18B20的個(gè)數(shù)加1
- }while((_00web[l]!=0)&&(num<MAXNUM));//如果沖突位記錄數(shù)組已經(jīng)前推到0值或是DS18B20的數(shù)目已經(jīng)超過(guò)最大允許數(shù)目,
- //就退出循環(huán)
- }
- //************************//
- //*********主程序*********//
- //************************//
- void main()
- {
- delay(10);
- search_rom();
- TMOD = 0x01; //選擇工作方式1
- TH0 = 0x3C; //設(shè)置初始值,定時(shí)50MS
- TL0 = 0xB0;
- EA = 1; //打開(kāi)總中斷
- ET0 = 1; //打開(kāi)定時(shí)器0中斷
- TR0 = 1; //啟動(dòng)定時(shí)器0
- init();
- while(1)
- {
- display_ROMID(); //顯示序列號(hào)
- display_m(); //顯示18b20個(gè)數(shù)
- diplay_final(); //顯示溫度
-
- …………限于本文篇幅 余下代碼請(qǐng)從51黑下載附件…………
復(fù)制代碼
完整代碼下載:
多點(diǎn)溫度測(cè)量.zip
(53.69 KB, 下載次數(shù): 76)
2018-1-28 18:16 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
|
評(píng)分
-
查看全部評(píng)分
|