📄 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 + -