|
10黑幣
這里有兩段程序一個是是基于DS18B20驅動MAX7219顯示溫度測量的的程序;另一份是超聲波測距(有溫度補償)的程序注有兩個DS18B20測量兩個不同地方的溫度,求大神把這兩個程序合并成一段程序,使單片機能實現兩個功能
第一個程序
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit din=P1^2;
sbit cs=P1^3;
sbit clk=P1^4;
sbit DQ=P1^5; //DS18B20端口DQ
uchar dig;
sbit DIN=P1^7; //小數點
bit list_flag=0; //顯示開關標志
uchar code tab[]={0x7e,0x30,0x6d,0x79,0x33,0x5d0,0x5f,
0x70,0x7f,0x7b,0x4e,0x63,0x01,0x00};
uchar data temp_data[2]={0x00,0x00};
unsigned char data display[]={0x00,0x00,0x00,0x00,0x00,0x00};
unsigned char code ditab[]={0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,
0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09};
void Delay(uint ms) //延時函數
{
while(ms--);
}
uchar Init_DS18B20(viod) //初始化DS18B20
{
uchar status;
DQ=1; //DQ復位
Delay(8); //延時
DQ=0; //單片機將DQ拉低
Delay(90); //精確延時,大于480ms
DQ=1; //拉高總線
Delay(8);
status = DQ; //如果為0,則初始化成功;如果為1,則初始化失敗
Delay(100);
DQ=1;
return(status) ;
}
uchar ReadOneByte(void) //讀一個字節
{
uchar i=0;
uchar dat=0;
for(i=8;i>0;i--)
{
DQ=0; //給脈沖信號
dat >>=1;
DQ=1;
_nop_();
_nop_();
if(DQ)
{
dat |= 0x80;
}
Delay(4);
DQ=1;
}
return(dat);
}
void WriteOneByte(uchar dat) //寫一個字節
{
uchar i=0;
for(i=8;i>0;i--)
{
DQ=0;
DQ=dat&0x01;
Delay(5);
DQ=1;
dat>>=1;
}
}
void Read_Temperature(void) //讀取溫度
{
if(Init_DS18B20()==1)
{
list_flag=1;
}
else
{
list_flag=0;
WriteOneByte(0xCC); //跳過讀序號列號的操作
WriteOneByte(0x44); //啟動溫度轉換
Init_DS18B20();
WriteOneByte(0xCC); //跳過讀序號列號的操作
WriteOneByte(0xBE); //啟動溫度轉換
temp_data[0]=ReadOneByte();
temp_data[1]=ReadOneByte();
}
}
void Temperature_trans()
{
uchar ng=0;
if((temp_data[1]&0xF8)==0xF8)
{
temp_data[1]=~temp_data[1];
temp_data[0]=~temp_data[0]+1;
if(temp_data[0]==0x00)
{
temp_data[1]++;
}
ng=1;
}
display[4]=temp_data[0]&0x0f;
display[0]=ditab[display[4]]; //查表得小數位的值
display[4]=((temp_data[0]&0xf0)>>4)|((temp_data[1]&0x0f)<<4);
display[3]=display[4]/100;
display[1]=display[4]%100;
display[2]=display[1]/10;
display[1]=display[1]%10;
if(ng==1) //溫度為零度以下
{
display[5]=12; //顯示"—"
}
else
{
display[5]=13; //不顯示“-”
}
if(!display[3]) //高位為0,不顯示
{
display[3]=13;
if(!display[2]) //次高位為0,不顯示
display[2]=13;
}
}
void write_7219(uchar add,uchar date) //add為接受MAX7219的地址;data為要寫入的數據
{
uchar i;
cs=0;
for(i=0;i<8;i++)
{
clk=0;
din=add&0x80; //按照高位在前,低位在后的順序發送
add<<=1; //先發送地址
clk=1;
}
for(i=0;i<8;i++)
{
clk=0;
din=date&0x80;
date<<=1; //在發送數據
clk=1;
}
cs=1;
}
void init_7219()
{
write_7219(0x0c,0x01); //0x0c為關斷模式寄存器;0x01表示顯示器處于工作狀態
write_7219(0x0a,0x0f); //0x0a為亮度調節寄存器;0x0f使數碼管顯示亮度為最亮
write_7219(0x09,0x00); //0x09為譯碼模式選擇寄存器;0x00為非譯碼方式
write_7219(0x0b,0x07); //0x0為掃描限制寄存器;0x07表示可將8個LED數碼管
}
void disp_Max7219(uchar dig,uchar date) //指定位,顯示某一數
{
write_7219(dig,date);
}
void main()
{
init_7219();
while(1)
{
Temperature_trans();
Read_Temperature();
if(list_flag==0)
{
disp_Max7219(1,tab[display[5]]);
disp_Max7219(2,tab[display[3]]);
disp_Max7219(3,tab[display[2]]);
disp_Max7219(4,tab[display[1]]|0x80); //|0x80為帶上小數點
disp_Max7219(5,tab[display[0]]);
disp_Max7219(7,tab[11]);
disp_Max7219(8,tab[10]);
}
}
}
第二個程序
#include<reg52.h>
#include<intrins.h>
#include<math.h>
#define uchar unsigned char
#define uint unsigned int
uchar code dispBUF[33]={"Temperature: Distance: mm "};
uchar numcode[10]={'0','1','2','3','4','5','6','7','8','9'};
uint num[29]={0};
uchar jsh,jsl; //計數器的高低位
uchar count=0; //10秒計次數
uint distance; //距離
uint temp; //溫度變量
uchar bdata flag; //DS18B20存在標準
sbit RS=P2^0; //LCD RS
sbit RW=P2^1; //LCD RW
sbit E =P2^2; //LCD E
sbit DQ_1=P2^7; //DS18B20數字端口
sbit Busy = P0^7; //LCD 忙
void Delay(uint time);
void delay1ms(uint ms);
void delay();
void delay15(uchar us);
void BUMA(void);
void B20_WDAT(uchar dat);
uchar B20_RDAT(void);
void Init_18B20_1(void); //初始化18B20 _超聲
void Write_Comm(uchar); //寫入LCD命令
void Write_Data(uchar); //寫入LCD數據
void Init_LCD(void);
sbit sta_flag =flag^0; //10MS到標準位,flag即通用標志位,當sta_flag=1時,表示到了10ms
sbit fuhao =flag^1; //溫度的符號位
sbit START =P3^0; //啟動測距
sbit CNT =P2^4; //發射超聲波
sbit CSBIN =P2^5; //返回信號
sbit BUZZER =P3^7;
/******************定時器1溢出***************************/
void timer1(void)interrupt 2 using 1
{TR1=0;} //關閉定時器/計數器1
/*********定時器0溢出中斷函數,每60MS溢出****************/
void timer0(void)interrupt 1 using 0 //定時器0
{
TH0=0x15;
TL0=0xA0; //定時器0設定初值
TH1=0;
TL1=0; //計數器1清零
sta_flag=1;
count++;
_nop_();
_nop_();
_nop_();
_nop_();
CNT=1; //先延時,后開始發送40KHz的超聲波
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_(); //40KHZ的倒數就是25us,12個_nop_();就是24us
CNT=0; //保持一段時間高電平
_nop_();
_nop_();
_nop_();
_nop_();
TR1=1; //延時,避免直達信號干擾,啟動定時器/計數器1
delay15(50); //延時避開直達信號
}
/***************系統初始化*************************/
void SYS_INIT()
{
uchar i;
for(i=0;i<29;i++) //顯示清零
{ num[ i]=0;}
TMOD=0x11; //工作方式寄存器TMOD,設置定時器/計數器0和1均為16位定時/計數器
TH0 =0x15;
TL0 =0xA0; //設置定時器/計數器0的初值,60ms溢出
P0 =0;
CNT=0; //P2^5口,發射發射超聲波
CSBIN=1; //P2^6口,接收信號
EA =1; //開總中斷
}
/******************距離計算***************************/
void JULIJS() //使用全局變量,可以定義為空
{
float c,d,s;
uint t;
if(temp<0x8000)
c=331.4+0.61*temp*0.0625;
else //溫度為負
c=331.4-0.61*temp*0.0625;
t=jsh*256+jsl-120; //計算計數值
d=(c*t*0.001)/2;
d*=d;
s=d-7.98;
distance=sqrt(s); //修正后的值,數據通過全局變量distance傳輸
}
/****************轉換成2進制***************/
void HEXtoBCD()
{
float tp;
unsigned long int tmp;
fuhao=0; //溫度符號位
if(temp<0x8000)
tp=temp*0.0625;
else //溫度為負,則求補碼得到原碼
{
BUMA();
tp=temp*0.0625;
fuhao=1;
}
tp*=10;
tmp=tp;
num[12]=tmp/100; //數據轉換后放到顯示數組里面
if(fuhao)
num[12]=num[12]|0x80; //最高位加上符號位
num[13]=tmp/10-(tmp/100)*10;
tmp=distance;
num[25]=tmp/1000;
tmp%=1000;
num[26]=tmp/100;
tmp%=100;
num[27]=tmp/10;
tmp%=10;
num[28]=tmp/1;
}
/**************溫度轉換函數***************************/
void TESTTEMP()
{
Init_18B20_1(); //初始化18B20
if(flag)
{
B20_WDAT(0xCC); // 跳過讀序號列號的操作,忽略ROM匹配
B20_WDAT(0x44); // 發送溫度轉化命令
}
}
/***********讀取溫度函數**************/
uint GET_WD(void)
{
uint a = 0, b = 0, t = 0;
Init_18B20_1(); //初始化18B20
B20_WDAT(0xCC); //跳過讀序號列號的操作
B20_WDAT(0xBE); //發送讀溫度命令
a = B20_RDAT();
b = B20_RDAT(); //讀取一個字節(讀出高8位和低8位)
t = b;
t <<= 8;
t = t | a; //字節合并
return (t); //返回結果給調用
}
/***************18B20復位函數***********************/
void Init_18B20_1()
{
DQ_1 = 1; //DQ復位
Delay(10);
DQ_1 = 0; //單片機將DQ拉低
Delay(80); //480us
DQ_1 = 1; //拉高總線
Delay(10); //稍做延時后 如果x=0則初始化成功,x=1則初始化失敗
if(DQ_1)
flag=0;
else
flag=1;
Delay(20);
}
/*******************讀數據******************************/
uchar B20_RDAT(void) //讀取一個字節
{
uchar i = 0;
uchar dat = 0;
for (i = 8; i > 0; i--)
{
DQ_1 = 0; // 拉低數據線,開始讀數據
dat >>= 1;
DQ_1 = 1; // 拉高數據線,停止讀數據
if(DQ_1)
dat |= 0x80; //拼裝處理
Delay(15);
}
return (dat); //注意讀取的為補碼
}
/*********************寫數據****************************/
void B20_WDAT(uchar dat)
{
uchar i = 0;
for (i = 8; i > 0; i--)
{
DQ_1 = 0; //拉低數據線至少15us以作為起始信號
DQ_1 = dat&0x01; //取出低位的一位數據
Delay(5); //稍作延時
DQ_1 = 1; //將數據線拉高以作為停止信號
dat>>=1; //移位,為寫入下一位數據做準備
}
}
/*******************數據轉換函數**************************/
void BUMA()
{
temp=~temp; //按位取反
temp+=1;
}
/**************************LCD顯示函數*******************/
void LCD_DISP()
{
uchar a,b,d;
Init_LCD();
Write_Comm(0x01); //清顯示
Write_Comm(0x80); //寫首地址
for(a=0;a<16;a++)
{
d=dispBUF[a];
if((a>11)&&(a<14)) //如果是結果位到num[]里面讀取
{
d=numcode[num[a]]; //待顯示的結果
}
if(14==a)
{
d=0xdf;
}
Write_Data(d); //寫入要顯示的數據
}
Write_Comm(0xc0); //換行,換到第二行
for(b=16;b<33;b++)
{
d=dispBUF[ b];
if((b>24)&&(b<29))
{
d=numcode[num[ b]];
}
Write_Data(d); //寫入要顯示的數據(數據傳輸)
}
}
/*********檢查LCD忙狀態***********/
bit LCD_BUSY() //lcd_busy為1時,忙,等待。lcd-busy為0時,閑,可寫指令與數據
{
bit BS;
RW = 1;
RS = 0;
E = 1;
delay1ms(1);
BS =(bit)(P0&0x80);
E = 0;
return BS;
}
/*******************寫指令函數******************************/
void Write_Comm(uchar lcdcomm) //寫指令
{
while(LCD_BUSY());
RS = 0;
RW = 0;
E = 1;
delay1ms(1);
P0= lcdcomm;
delay1ms(1);
E = 0;
}
/*********************寫數據函數****************************/
void Write_Data(uchar lcddata)//寫數據
{
while(LCD_BUSY());
RS = 1;
RW = 0;
E = 1;
delay1ms(1);
P0= lcddata;
delay1ms(1); //判斷是否忙狀態
E = 0;
}
/*********************初始化LCD****************************/
void Init_LCD()
{
delay(); //稍微延時,等待LCD進入工作狀態
Write_Comm(0x01); //清顯示
Delay(2);
Write_Comm(0x38); //8位2行 5*8
Delay(2);
Write_Comm(0x06); //文字不動,光標右移
Delay(2);
Write_Comm(0x0c); //顯示開/關,光標開閃爍開
Delay(2);
}
/*************************延時n*15US函數*************************/
void delay15(uchar us)
{
do
{
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
us--;
}
while(us);
}
/************************18b20延時函數************************/
void Delay(uint time)
{
while( time-- );
}
/****************************延時1MS*************************/
void delay1ms(uint ms)
{
uint i,j;
for(i=0;i<ms;i++)
for(j=0;j<100;j++);
}
/***************************顯示延時函數*********************/
void delay()
{
uchar y;
for(y=0;y<0xff;y++);
}
/*********************導通即可驅動蜂鳴器*********************/
void beep(uint bp)
{
uchar i, j;
for (i=0;i<250;i++)
{
BUZZER=!BUZZER; //BEEP取反
for (j = 0 ; j<bp ; j++) //需要產生方波
_nop_(); //一個CPU周期
}
BUZZER=0; //關閉蜂鳴器
}
/*******************系統主函數******************/
void main(void)
{
uchar i,j;
for(i=0;i<255;i++)
for(j=0;j<255;j++); //延時
SYS_INIT(); //初始化
while(!START )
{
beep(150); //調用beep()函數,使喇叭發聲
delay1ms(500);
LCD_DISP(); //顯示
sta_flag=0; //標準位復位
ET0=1; //開定時器0中斷
TR0=1; //啟動定時器0
TESTTEMP(); //啟動溫度轉換
while(1)
{
if(sta_flag) //10MS到了(sta_flag=1)
{
while(0==CSBIN); //收到回波
TR1=0; //關閉計數器1
jsh=TH1;
jsl=TL1; //讀取計數器高低位的數值
HEXtoBCD(); //轉換成BCD碼
JULIJS(); //計算距離
if(15==count) //900MS到,檢測溫度
{
temp=GET_WD(); //讀取溫度
count=0;
TESTTEMP(); //重新啟動轉換
LCD_DISP(); //刷新顯示
}
sta_flag=0; //標準位復位
}
if(distance<=110)
{
beep(150);
}
}
}
}
|
-
-
test.zip
2016-6-18 22:50 上傳
點擊文件名下載附件
31.65 KB, 下載次數: 5
附帶電路圖
|