新手,小試牛刀,通過18b20采集溫度,然后通過四位數碼管顯示出來。
以下是proteus仿真和源程序。
大家多多指教
仿真圖.png (94.49 KB, 下載次數: 92)
下載附件
2018-2-1 14:42 上傳
單片機源程序:
- #include <REGX52.H>
- #define uint8 unsigned char
- #define uint16 unsigned int
- sbit DQ =P3^7;//DS18B20數據端
- sbit KEY1=P1^0;
- sbit KEY2=P1^1;
- sbit KEY3=P1^2;
- uint16 Temperature;
- uint16 TemperatureSave;
- uint8 ReadFlag;//溫度讀取標志位
- uint16 RecTemperature[10];//記錄的溫度
- uint8 RecSum=0;//記錄的數量最多10
- uint8 Fin;
- uint8 mode=0;
- uint8 code DuCode[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
- 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //共陰數碼管段選碼表,0-F無小數點
- uint8 code WeiCode[4]={0xFE,0xFD,0xFB,0xF7};//
- uint8 SegBus[4]={0x40,0x40,0x40,0x40};//數碼管顯示緩存
- code uint8 DecimalNum[16]={0,1,1,2,3,3,4,
- 4,5,6,6,7,8,8,9,9};//DS18B20讀取的16bit數據最低4位對應的小數4舍5入取一位
- void SegShow(void);//數碼管顯示函數
- void Timer0Init(void);//定時器初始化函數
- uint16 ReadTemp(uint8 mode);//讀取溫度函數
- void ShowTemperature(uint16 temperature,uint8* str);
- void main(void)
- {Timer0Init();
- ReadTemp(0);
- while(1)
- {
- if(KEY1==0)
- {
- mode=(mode+1)%2;//模式
- while(KEY1==0);
- }
- if(mode==1)//溫度查詢 +
- {
- if(KEY2==0)
- {
- Fin=(Fin+1)%10;
- while(KEY2==0);
- }
- if(KEY3==0)
- {
- if(--Fin==255)Fin=0;
- while(KEY3==0);
- }
-
- }
- if(ReadFlag)//已經讀取到溫度
- {
- ReadFlag=0;
- if(TemperatureSave!=Temperature)
- {
- TemperatureSave=Temperature;
- RecTemperature[RecSum++]=Temperature;
- RecSum=RecSum%10;
- }
- if(mode==0)
- {
- ShowTemperature(Temperature,SegBus);
- }
- else
- {
- ShowTemperature(RecTemperature[Fin],SegBus);
- }
- SegBus[2]|=0x80;//添加小數點;
- }
- SegShow();
- }
- }
- /**************************************************
- 定時器初始化函數50ms定時中斷
- **************************************************/
- void Timer0Init(void)
- {
- TMOD=0x01;
- TH0=(65536-50000)/256;
- TL0=(65536-50000)%256;
- TR0=1;
- ET0=1;
- EA=1;
- }
- /**************************************************
- 定時器中斷函數
- **************************************************/
- void Timer0_ISR(void) interrupt 1
- {
- static uint8 cnt=0;
- TH0=(65536-50000)/256;
- TL0=(65536-50000)%256;
- cnt++;
- if(cnt>15)//每隔750ms讀取一次溫度
- {
- Temperature=ReadTemp(1);//讀取溫度
- cnt=0;
- ReadTemp(0);//啟動溫度轉換
- ReadFlag=1;
- }
- }
- /**************************************************
- 數碼管用延時函數
- **************************************************/
- void DelaySeg(void)
- {
- uint8 i;
- for(i=0;i<110;i--);
- }
- /**************************************************
- 1位十進制轉數碼管段碼
- **************************************************/
- void Dec1ToSeg(uint8 dec,uint8 *str)
- {
- str[0]=0;//百位不顯示
- str[1]=0;//個位不顯示
- str[2]=DuCode[dec];
- }
- /**************************************************
- 2位十進制轉數碼管段碼
- **************************************************/
- void Dec2ToSeg(uint8 dec,uint8 *str)
- {
- str[0]=0;
- str[1]=DuCode[dec/10];
- str[2]=DuCode[dec%10];
- }
- /**************************************************
- 3位十進制轉數碼管段碼
- **************************************************/
- void Dec3ToSeg(uint8 dec,uint8 *str)
- {
- str[0]=DuCode[dec/100];
- str[1]=DuCode[dec%100/10];
- str[2]=DuCode[dec%10];
- }
- /**************************************************
- 顯示溫度信息
- **************************************************/
- void ShowTemperature(uint16 temperature,uint8* str)
- {
- if(temperature&0x8000)//負溫度
- {
- temperature=~temperature+1;
- str[3]=DuCode[DecimalNum[temperature&0x0f]];//計算小數部分
- temperature=temperature>>4;
- if(temperature>9)//負溫度的時候最多只有2位整數部分
- {
- Dec3ToSeg(temperature,str);
- str[0]=0x40;//-
- }
- else
- {
- Dec2ToSeg(temperature,str);
- str[1]=0x40;//-;
- }
- }
- else
- {
- str[3]=DuCode[DecimalNum[temperature&0x0f]];//計算小數部分
- temperature=temperature>>4;
- if(temperature>99)
- {
- Dec3ToSeg(temperature,str);
- }
- else if(temperature>9)
- {
- Dec2ToSeg(temperature,str);
- }
- else
- {
- Dec1ToSeg(temperature,str);
- }
- }
- }
- /**************************************************
- 數碼管顯示
- **************************************************/
- void SegShow(void)
- {
- P0=0x00;
- P2=WeiCode[0];
- P0=SegBus[0];
- DelaySeg();
- P0=0x00;
- P2=WeiCode[1];
- P0=SegBus[1];
- DelaySeg();
- P0=0x00;
- P2=WeiCode[2];
- P0=SegBus[2];
- DelaySeg();
- P0=0x00;
- P2=WeiCode[3];
- P0=SegBus[3];
- DelaySeg();
- }
- /**************************************************
- 大致延時一次延時2*t+7us
- **************************************************/
- void DelayUs(uint8 t)
- {
- while(--t);
- }
- /**************************************************
- DS18B20初始化
- **************************************************/
- void DS18B20Init(void)
- {
- DQ = 1; //DQ復位
- DelayUs(10); //稍做延時
- DQ = 0; //單片機將DQ拉低
- DelayUs(200);//精確延時 大于 480us 小于960us
- DelayUs(200);
- DQ = 1; //拉高總線
- DelayUs(75); //15~60us 后 接收60-240us的存在脈沖
- DelayUs(75);
- }
- /**************************************************
- 讀取一個字節數據,返回uchar類型數據
- **************************************************/
- uint8 DS18B20Read(void)
- {
- uint8 i=0;
- uint8 cdat=0;
- for(i=8;i>0;i--)
- {
- DQ=0;//給脈沖信號
- cdat>>=1;
- DQ = 1; // 給脈沖信號
- if(DQ)
- cdat|=0x80;
- DelayUs(50);
- }
- return (cdat);
- }
- /**************************************************
- * 功能描述: 向DS18B20寫一個字節數據
- **************************************************/
- void DS18B20Write(uint8 cdat)
- {
- unsigned char i=0;
- for(i=8;i>0;i--)
- {
- DQ=0;
- DQ=cdat&0x01;
- DelayUs(50);
- DQ=1;
- cdat>>=1;
- }
- DelayUs(50);
- }
- /**************************************************
- * 功能描述: 讀取溫度值,返回uint類型數據
- **************************************************/
- uint16 ReadTemp(uint8 mode)
- {
- unsigned char a=0;
- unsigned int b,t;
- DS18B20Init();
- DS18B20Write(0xCC); // 跳過讀序號列號的操作
- switch(mode)
- {
- case 0:
- DS18B20Write(0x44); // 啟動溫度轉換
- return 0;
- case 1:
- DS18B20Write(0xBE); //讀取溫度寄存器
- a=DS18B20Read(); //低位
- b=DS18B20Read(); //高位
- b<<=8;
- t=a+b;
- return (t);
- default:return 0;
- }
- return (0);
- }
復制代碼
0.png (41.64 KB, 下載次數: 54)
下載附件
2018-2-1 15:47 上傳
下載:
數碼管DS18B20溫度整點記錄.zip
(70.75 KB, 下載次數: 122)
2018-2-1 14:43 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|