本帖最后由 凌凈清河 于 2018-7-24 08:38 編輯
本作品采用STC15F104W單片機和四位共陰極數碼管設計
主要亮點:
1.數碼管使用74HC595作為段選驅動,為初學者提供了新的思路
次要亮點:
1.使用小巧的STC15F104W單片機
DS18B20的通信要點在于時序的嚴格對應,相比之下DHT11這一類的單總線通信時序要求更加寬松。
因為DS18B20算是極為常用的學習器件,故不做過多講解,本次作品不涉及搜索BOM、精度調節等操作,只是單器件讀取溫度值,數據處理將可以顯示的溫度值設置為-20℃~80℃。
(事實證明不同器件之間會有差異,讀取的值也會不盡相同)
IMG_20180720_134627.jpg (2.87 MB, 下載次數: 150)
下載附件
2018-7-24 08:26 上傳
DS18B20數據處理參考普中科技相關例程

#include<STC15.H>
sbit DSPORT=P3^5;//DS18B20管腳定義
#include<intrins.h>
#include"DS18B20.c"
sbit S1=P3^4;
sbit S2=P3^3;//數碼管位選管腳定義
sbit SER=P3^0;
sbit RCLK=P3^1;
sbit SRCLK=P3^2;//74HC595管腳定義
//全局變量表
unsigned char code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//給74HC595的段選值
unsigned char Display_Temperature[4]={0x40,0x40,0x40,0x40};
int Data_temperature=0;
unsigned char t0_cnt=0;
/*##############################################################################################
設計名稱:基于DS18B20的數顯溫度計
設計者:清河
平臺:STC15F104W
硬件部分
數碼管顯示:位選使用74HC138改為2-4線譯碼、段選使用74HC595減少IO口使用
使用4位共陰極數碼管,顯示無符號位
注意:由于STC15系列采用Y5內核,所以有關DS18B20精準延時部分在移植時應首先考慮更換
##############################################################################################*/
void delay(unsigned int cnt)//調用該函數進行一段時間的延時
{
while(cnt--);
}
void hc595send(unsigned char dat)//使用SPI向74HC595發送一個字節的數據
{
unsigned char a;
SRCLK=0;
RCLK=0;
for(a=0;a<8;a++)
{
SER=dat>>7;
dat<<=1;
SRCLK=1;
_nop_();
_nop_();
SRCLK=0;
}
RCLK=1;
_nop_();
_nop_();
RCLK=0;
}
void smgdisplay()//數碼管顯示函數,參數為需要顯示的數組
{
unsigned char i;
for(i=0;i<4;i++)
{
switch(i)//位選,選擇點亮的數碼管
{
case(0):
S1=0;S2=1; break;
case(1):
S1=1;S2=0; break;
case(2):
S1=0;S2=0; break;
case(3):
S1=1;S2=1; break;
}
hc595send(Display_Temperature);
delay(10); //間隔一段時間掃描
hc595send(0x00);//消隱
}
}
void Data_processing()
{
float temperature=0.0;//【03c4】似乎只是一個用于更改值為float類型的中間變量,考慮刪去
int temperature_middle;//為了不更改全局變量中讀取出來的Data_temperature設置此中轉值
if(Data_temperature>0xf000)//當溫度值為負數
{
Display_Temperature[0]=0x40;//顯示符號“-”的段碼
//因為讀取的溫度是實際溫度的補碼,所以減1,再取反求出原碼
temperature_middle=Data_temperature-1;
temperature_middle=~temperature_middle;
temperature=temperature_middle;
temperature_middle=temperature*0.0625*100+0.5;
//留兩個小數點就*100,+0.5是四舍五入,因為C語言浮點數轉換為整型的時候把小數點
//后面的數自動去掉,不管是否大于0.5,而+0.5之后大于0.5的就是進1了,小于0.5的就
//算加上0.5,還是在小數點后面。
if(temperature_middle<2000)
{
if(temperature_middle>=1000)
{
Display_Temperature[1]=smgduan[temperature_middle%10000/1000];
Display_Temperature[2]=smgduan[temperature_middle%1000/100]|0x80;
Display_Temperature[3]=smgduan[temperature_middle%100/10];
}
else
{
Display_Temperature[1]=smgduan[temperature_middle%1000/100]|0x80;
Display_Temperature[2]=smgduan[temperature_middle%100/10];
Display_Temperature[3]=smgduan[temperature_middle%10];
}
}
else
{
unsigned char i;
for(i=0;i<4;i++)
{
Display_Temperature=0x40;
}
}
}
else
{
temperature=Data_temperature;//因為數據處理有小數點所以將溫度賦給一個浮點型變量
//如果溫度是正的那么,那么正數的原碼就是補碼它本身
temperature_middle=(int)(temperature*0.0625*100+0.5);
//留兩個小數點就*100,+0.5是四舍五入,因為C語言浮點數轉換為整型的時候把小數點
//后面的數自動去掉,不管是否大于0.5,而+0.5之后大于0.5的就是進1了,小于0.5的就
//算加上0.5,還是在小數點后面。
if(temperature_middle<8000)
{
if(temperature_middle>=1000)
{
Display_Temperature[0]=smgduan[temperature_middle%10000/1000];
Display_Temperature[1]=smgduan[temperature_middle%1000/100]|0x80;
Display_Temperature[2]=smgduan[temperature_middle%100/10];
Display_Temperature[3]=smgduan[temperature_middle%10];
}
else
{
Display_Temperature[0]=0x00;
Display_Temperature[1]=smgduan[temperature_middle/100]|0x80;
Display_Temperature[2]=smgduan[temperature_middle%100/10];
Display_Temperature[3]=smgduan[temperature_middle%10];
}
}
else
{
unsigned char i;
for(i=0;i<4;i++)
{
Display_Temperature=0x40;
}
}
}
}
void sys_init()
{
TH0=0;
TL0=0;
ET0=1;
TR0=1;
EA=1;
}
void main()
{
sys_init();
while(1)
{
smgdisplay();
}
}
void Temperature_Refresh() interrupt 1
{
TL0 = 0x00;
TH0 = 0x28;//5ms初值
if(t0_cnt==10)
{
hc595send(0x00);
Data_temperature=DS18B20_GetTemperature();
Data_processing();
t0_cnt=0;
}
else
{
t0_cnt++;
}
}
由于中斷時的數據讀取和處理會占用一部分時間,導致數碼管有輕微閃爍感,使用者可以考慮將轉換精度調為最低并修改轉換等待時間以減少數碼管的閃爍感,同時別忘記調一下數據處理函數中對應的精度值。
上述程序仍然臃腫,但由于是普通器件的使用,沒有難點,所以也沒有進行優化,以完成功能為目的。
新礦城學習基地 凌凈清河
|