?? all.c
字號:
/*項目名稱:數字式多路溫度檢測、顯示與報警系統*/
/*創建 人:孫云輝 */
/*創建時間:2008.05.25 */
/*修改時間:2008.06.01 */
/*功 能:全部功能 */
/*版 本:V1.0 */
#include<reg51.h>
/////////////////////////////////////////////////
/********************基本程序*******************/
/////////////////////////////////////////////////
/*短延時程序16us為單位 延時時間=24+Num*16 微秒*/
void Delay_short(unsigned int n)
{
unsigned int i;
for(i=0;i<n;i++)
{}
}
/*長延時程序,以5ms為單位*/
void Delay_long(unsigned char N)
{ unsigned char i;
unsigned int j;
for(i=0;i<N;i++)
{ for(j=0;j<315;j++) //一個循環16us,共5ms
{}
}
}
/////////////////////////////////////////////////
/*******************鍵盤部分********************/
/////////////////////////////////////////////////
/*鍵盤鍵值定義*/
#define MENU 0xee //KEY1 菜單鍵
#define UP 0xde //KEY2 菜單上翻或加一鍵
#define SET 0xeb //KEY3 確認鍵
#define CHANGE 0xe7 //KEY4 搜索ROM鍵
#define LEFT 0xed //KEY5 光標左移
#define DOWN 0xdd //KEY6 菜單下翻或減一鍵
#define RIGHT 0xdb //KEY7 光標右移
#define QUIT 0xd7 //KEY8 退出鍵
/*鍵盤接口定義*/
sbit R1= P2^4; //第一列按鍵
sbit R2= P2^5; //第二列按鍵
/*鍵盤掃描程序,返回鍵值*/
unsigned char Key_scan(void)
{
unsigned char i,j;
R1=0; //掃描第一列
i=P2; //讀取鍵值
Delay_long(2); //延時10ms去抖動
j=P2; //再次讀取鍵值
R1=1; //第一列初始化
if(i==j) //兩次鍵值相同表示有鍵按下
{
switch(j)
{
case 0xee: return(j);break;//KEY1
case 0xed: return(j);break;//KEY5
case 0xeb: return(j);break;//KEY3
case 0xe7: return(j);break;//KEY4
}
}
R2=0;
i=P2;
Delay_long(2);
j=P2;
R2=1;
if(i==j)
{
switch(j)
{
case 0xde: return(j);break;//KEY2
case 0xdd: return(j);break;//KEY6
case 0xdb: return(j);break;//KEY7
case 0xd7: return(j);break;//KEY8
default:return(0); //無鍵按下返回0
}
}
}
/////////////////////////////////////////////////
/*******************報警部分********************/
/////////////////////////////////////////////////
/*蜂鳴器接口*/
sbit voice=P1^7;
bit Alarm_flag; //報警標志位 1報警 0取消報警
/*報警子程序 */
/*全局變量:Alarm_flag=1報警=0報警解除*/
void Alarm(void)
{
unsigned char i;
if(Alarm_flag==1) //當Alarm_flag有效
{
for(i=0;i<10;i++) //報警一段時間
voice=~voice;
Delay_long(5);
}
}
}
/////////////////////////////////////////////////
/********************LCD部分********************/
/////////////////////////////////////////////////
/*LCD接口定義*/
sbit LcdRS = P1^0; //lcd數據/命令選擇端 數據1命令0
sbit LcdRW = P1^1; //lcd讀/寫選擇端 讀1寫0
sbit LcdEn = P1^2; //lcd使能控制端 1有效
sfr LcdIO = 0x80; //lcd數據接口 P0=0x80
/****向LCD寫入命令或數據部分****/
#define LCD_COMMAND 0 // 輸出指令
#define LCD_DATA 1 // 輸出數據
#define LCD_CLEAR_SCREEN 0x01 // 清屏指令
#define LCD_HOME 0x02 // 光標返回原點指令
/*寫LCD子程序 */
/*入口參數:數據style=1 指令style=0 input:寫入的內容*/
void LCD_Write(bit style, unsigned char input)
{
LcdRS=style; //數據style=1 指令style=0
LcdRW=0; //寫
LcdIO=input; //P0口輸出
Delay_short(10); //延時
LcdEn=1; //lcd使能
Delay_short(10); //延時
LcdEn=0; //停止
}
/****初始化LCD程序****/
void LCD_Initial()
{
Delay_long(6); //延遲5*6=30ms
LCD_Write(LCD_COMMAND,0x38); //8位數據端口,2行顯示,5*7點陣
LCD_Write(LCD_COMMAND,0x38);
LCD_Write(LCD_COMMAND,0x38); //發送三遍
Delay_short(2); //延遲大于39us
LCD_Write(LCD_COMMAND,0x0c); //顯示模式設置:開啟顯示, 無光標 0x0c
Delay_short(2); //延遲大于39us
LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏 0x01
Delay_short(100); //延遲大于1.53ms
LCD_Write(LCD_COMMAND,0x06); //輸入模式設置:AC遞增, 畫面不動 0x06
}
/*液晶字符輸入的位置定位程序*/
/*入口參數:x范圍:0-15 y范圍:1,2*/
void GotoXY(unsigned char x, unsigned char y)
{
unsigned char address;
if(y==1)
address=0x80+x; //y=1顯示在第一行
else
address=0xc0+x; //y=2顯示在第二行
LCD_Write(LCD_COMMAND, address);
}
/*將字符串輸出到液晶顯示函數*/
/*入口參數:字符串指針 */
void Print(unsigned char *str)
{
while(*str!='\0')
{
LCD_Write(LCD_DATA,*str);
str++;
}
}
/////////////////////////////////////////
/***********DS18B20部分*****************/
/////////////////////////////////////////
/*DS18B20接口定義*/
sbit DQ =P1^6; //單總線接口
/*全局變量定義*/
unsigned char DS_Temp[5][3]={{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}}; //存放溫度值(負數用補碼表示)
//0:符號1:整數2:小數
unsigned char DS_Tl[5]={0,0,0,0,0}; //溫度報警上限
unsigned char DS_Th[5]={0,0,0,0,0}; //溫度報警下限
unsigned char ID[5][8]={{0},{0},{0},{0},{0}}; //存放序列號
//*DS18B20指令定義*/
#define READ_ROM 0x33 //讀ROM指令
#define MATCH_ROM 0x55 //匹配ROM指令
#define SKIP_ROM 0xCC //跳過ROM指令
#define ALARM_SEARCH 0xEC //報警搜索指令
#define CONVERT_T 0x44 //溫度轉換指令
#define WRITE_SCR 0x4E //寫暫存器指令
#define READ_SCR 0xBE //讀暫存器指令
#define COPY_SCR 0x48 //復制暫存器指令
/*ds18b20初始化函數 返回初始化狀態*/
unsigned char DS_Reset(void)
{
unsigned char presence;
DQ = 1; //DQ復位
Delay_short(1); //稍做延時
DQ = 0; //單片機將DQ拉低
Delay_short(29); //精確延時480us
DQ = 1; //拉高總線
Delay_short(3); //等待存在信號
presence=DQ; //稍做延時后 如果presence=0則初始化成功 =1則初始化失敗
Delay_short(25);
if(presence==0)
return 1; //初始化成功返回1
else
return 0; //初始化失敗返回0
}
/*從ds18b20讀一個字節 dat為返回值*/
unsigned char DS_ReadByte(void)
{
unsigned char i=0;
unsigned char j=0;
unsigned char dat=0;
for (i=0;i<8;i++)
{
DQ = 0; //給脈沖信號
dat>>=1; //右移位等待接收一位數據
DQ = 1; //給脈沖信號
for(j=0;j<3;j++) ; //延時15微秒
if(DQ) //從低位開始接收數據
dat|=0x80;
Delay_short(6); //等待復位
}
return(dat);
}
/*向ds18b20寫一個字節 dat為待寫入字節*/
void DS_WriteByte(unsigned char dat)
{
unsigned char i=0;
for (i=0; i<8; i++)
{
DQ = 0; //給脈沖信號
DQ = dat&0x01; //從低位開始發送數據
Delay_short(5);
DQ = 1; //給脈沖信號
dat>>=1; //右移位等待發送
}
Delay_short(5) ;
}
/*讀DS18B20序列號程序*/
/*入口參數:器件序號*/
/*全局變量:ID[5][8]*/
void DS_ReadID(unsigned char Num)
{
signed char i;
DS_Reset();
DS_WriteByte(READ_ROM) ;
for(i=7;i>-1;i--) //從最低位開始讀取
{
ID[Num][i]=DS_ReadByte();
}
}
/*匹配序列號程序 */
/*入口參數:器件序號(0-4)*/
/*全局變量:ID[5][8] */
unsigned char Match_ID(unsigned char Num)
{
signed char i;
if(DS_Reset()==1) //有器件響應
{
DS_WriteByte(MATCH_ROM); //發送ID
for(i=7;i>-1;i--)
{
DS_WriteByte(ID[Num][i]);
}
return 1; //返回1表示成功
}
else
return 0; //返回0表示失敗
}
/*顯示序列號程序 */
/*入口參數為器件序號(0-4)*/
/*全局變量:ID[5][8] */
void Show_ID(unsigned char Num) //Num為序號
{
unsigned char i;
GotoXY(0,2); //顯示NO:
Print("NO:");
GotoXY(3,2);
LCD_Write(LCD_DATA,Num+1+0x30); //顯示序號(1-5)對應ID0-ID4
GotoXY(0,1);
for(i=0;i<8;i++)
{
unsigned char l=ID[Num][i]&0x0f; //取低4位
unsigned char h=ID[Num][i]&0xf0; //取高4位
h>>=4;
if((h>=0x00)&&(h<=0x09))
LCD_Write(LCD_DATA,h+0x30); //取ASCII碼
else
LCD_Write(LCD_DATA,h+0x37); //取ASCII碼
if((l>=0x00)&&(l<=0x09))
LCD_Write(LCD_DATA,l+0x30); //取ASCII碼
else
LCD_Write(LCD_DATA,l+0x37); //取ASCII碼
}
}
/*讀取ds18b20當前溫度 和Th,Tl */
/*入口參數:器件編號(0-4) */
/*全局變量DS_Temp[5][3] DS_Th[5] DS_Tl[5]*/
void DS_ReadTemp(unsigned char Num)
{
unsigned char temp_lsb=0; //溫度寄存器低字節
unsigned char temp_msb=0; //溫度寄存器高字節
unsigned char Temp=0;
DS_Reset(); //初始化
DS_WriteByte(SKIP_ROM); //跳過讀序號列號的操作
DS_WriteByte(CONVERT_T); //啟動溫度轉換
Delay_short(5); //延時過程
DS_Reset(); //初始化
Match_ID(Num); //匹配ROM
DS_WriteByte(READ_SCR); //讀取溫度寄存器前兩個就是溫度
temp_lsb=DS_ReadByte(); //讀取溫度寄存器低字節
temp_msb=DS_ReadByte(); //讀取溫度寄存器高字節
DS_Th[Num]=DS_ReadByte(); //讀取TH
DS_Tl[Num]=DS_ReadByte(); //讀取TL
if(temp_msb>0xf0)
DS_Temp[Num][0]=1; //取溫度符號(正為0,負為1)
else
DS_Temp[Num][0]=0;
DS_Temp[Num][1]=temp_msb<<4; //取溫度整數部分的高四位
DS_Temp[Num][1]+=(temp_lsb&0xf0)>>4; //取溫度整數部分的低四位
Temp=DS_Temp[Num][1];
DS_Temp[Num][2]=temp_lsb&0x0f; //取溫度小數部分
if(DS_Temp[Num][0]==1) //溫度為負的處理
{
DS_Temp[Num][1]=~DS_Temp[Num][1]; //整數取反
DS_Temp[Num][2]=~DS_Temp[Num][2]+1;//小數取反加1
if(DS_Temp[Num][2]==0x10) //如果有進位(在溫度為負整數時)
{
DS_Temp[Num][1]=DS_Temp[Num][1]+1; //整數加1
DS_Temp[Num][2]= 0; //小數清0
}
}
if((Temp+1>DS_Th[Num])||(Temp<DS_Tl[Num]))
Alarm_flag=1;
else
Alarm_flag=0;
}
/*溫度數據轉換成液晶字符顯示 */
/*全局變量 DS_Temp[5][3] */
/*入口參數 器件序號(0-4) */
void TempDisp(unsigned char Num)
{
GotoXY(0,1);
Print("NO."); //顯示NO.
GotoXY(3,1);
LCD_Write(LCD_DATA,Num+1+'0'); //顯示器件序號(1-5)
LCD_Write(LCD_DATA,':'); //顯示“:”
if(DS_Temp[Num][0]==0)
LCD_Write(LCD_DATA,'+') ; //溫度為正顯示“+”否則顯示“-”
else
LCD_Write(LCD_DATA,'-') ;
LCD_Write(LCD_DATA,DS_Temp[Num][1]/100+'0') ; //百位
LCD_Write(LCD_DATA,(DS_Temp[Num][1]%100)/10+'0') ; //十位
LCD_Write(LCD_DATA,DS_Temp[Num][1]%10+'0') ; //個位
LCD_Write(LCD_DATA,'.') ; //小數點
LCD_Write(LCD_DATA,DS_Temp[Num][2]*10/16+'0') ; //十分位
}
/*顯示TH和TL程序 */
/*入口參數:器件序號Num(0-4)位置坐標y(1,2) */
/*全局變量:DS_Tl[5] DS_Th[5] */
void ThTlDisp(unsigned char Num,unsigned char y)
{
unsigned char Th=DS_Th[Num]; //
unsigned char Tl=DS_Tl[Num];
GotoXY(1,y);
Print("TH="); //顯示TH
if(Th>=0x80) //為負顯示“-”并取絕對值
{
LCD_Write(LCD_DATA,'-');
Th=~Th+1;
}
else
LCD_Write(LCD_DATA,'+'); //為正顯示“+”
LCD_Write(LCD_DATA,Th/100+'0'); //百位
LCD_Write(LCD_DATA,(Th%100)/10+'0'); //十位
LCD_Write(LCD_DATA,Th%10+'0'); //個位
GotoXY(9,y);
Print("TL="); //顯示TL
if(Tl>=0x80) //為負顯示“-”并取絕對值
{
LCD_Write(LCD_DATA,'-');
Tl=~Tl+1;
}
else
LCD_Write(LCD_DATA,'+'); //為正顯示“+”
LCD_Write(LCD_DATA,Tl/10+'0'); //十位
LCD_Write(LCD_DATA,Tl%10+'0'); //個位
}
/////////////////////////////////////////////////////
/***************STC單片機ISP功能部分****************/
/////////////////////////////////////////////////////
/*STC新增特殊功能寄存器聲明*/
sfr ISP_DATA = 0xe2; //ISP數據寄存器
sfr ISP_ADDRH = 0xe3; //EEPROM地址高8位
sfr ISP_ADDRL = 0xe4; //EEPROM地址高8位
sfr ISP_CMD = 0xe5; //ISP命令模式寄存器:0無操作,1讀,2寫,3擦除
sfr ISP_TRIG = 0xe6; //ISP命令觸發寄存器:先寫46H再寫B9H則ISP_CMD生效
sfr ISP_CONTR = 0xe7; //ISP控制寄存器:取81H允許ISP功能
/*定義ISP命令模式*/
#define ISP_ReadByte 0x01 //字節讀指令
#define ISP_WeiteByte 0x02 //字節寫指令
#define ISP_Erase 0x03 //扇區擦除指令
/*ISP讀DS18B20 ID程序 */
/*入口參數:1,DS18b20編號(0-4) */
/*全局變量:DS18B20的ID號存儲區:ID[5][8] */
/*功 能:讀出某個扇區內的8字節DS18B20的ID載入RAM */
void ISP_Read8(unsigned char Num)
{
unsigned char i;
ISP_CONTR=0x81; //允許ISP功能,并配制等待時間
ISP_CMD=ISP_ReadByte; //送ISP字節讀指令
ISP_ADDRH=0x20+Num*0x02; //送地址高字節
for(i=0;i<8;i++) //讀8字節
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -