第28章 单片机实现数字温度计参考程序
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include <REGX51.H>//51单片机头文件
typedef unsigned char uchar;//类型定义
typedef unsigned int uint; //类型定义
uchar code SEGCODE[]= //定义LED段码
{0X03,0X9F,0X25,0X0D,0X99,0X49,0X21,0X1F,0X01,0X09,
0xff,//blank
0XFD,//LINE
};
//定义按键扫描码表
uchar code KEYCODE[]=
{0XEE,0XED,0XEB,0XE7,
0XDE,0XDD,0XDB,0XD7,
0XBE,0XBD,0XBB,0XB7,
0X7E};
#define NEGCHAR 11 //定义字符'-'常量
#define POSICHAR 10 //定义字符空格常量
#define KEYPORT P2//定义按键端口
#define NO_KEY 13 //定义无按键常量
#define KEYNEXT 10//定义下一位按键常量
#define KEYSET 11//定义SET按键常量
#define KEYSIGN 12//定义符号按键常量
bit DispCon;//是否刷新LED显示器
bit freshcon;//是否闪烁显示
bit DisplayNormal;//正常显示还是显示空白字符
uchar SysMode;//系统模式变量0:正常显示1:设置上限报警值2:设置下限报警值
uchar PT;//设置报警值时,指示设置的数位
uchar Inputt;// 设置时,存放当前设置值
uchar TimeCnt;//记录定时器中断的次数
#define TEMPSECOND 1
#define SIGNPOSI 0
sbit SDA= P1^3;//定义时钟的SDA线
sbit SCL= P1^2;//定义时钟的SCL线
sbit MSDA= P1^4;//定义A/D转换器的SDA线
sbit MCLK= P1^5;//定义A/D转换器的SCL线
sbit CS187=P1^6; //定义A/D转换器的片选线
sbit LEDREDCON=P0^0;//定义红色灯控制引脚
sbit LEDGREENCON=P0^1;//定义绿色灯控制引脚
sbit SPEAKERCON=P0^3;////定义蜂鸣器控制引脚
uchar DB[4];//定义显示及设置缓冲区
561
uint upperv;//保存设置的上限报警值
uint lowerv;//保存设置的下限报警值
/*
入口参数:无
出口参数:按键值或无按键
*/
uchar Scan_Key()
{
uchar KeyTemp,i;//定义局部变量
KEYPORT=0xf0;//行线输出0,列线输出全1
KeyTemp=KEYPORT;//读按键端口值
if(KeyTemp==0xf0)
return NO_KEY;//无键按下,返回
Delay15Ms();//延时去抖
KEYPORT=KeyTemp|0x0f;//列线输出,行线输入
KeyTemp=KEYPORT;//读取按键端口值
for(i=0;i<12;i++)
{
if(KeyTemp==KEYCODE[i])//根据按键端口扫描值,查找按键值break;
}
KEYPORT=0xf0;//行线输出0,列线输出全1
while(KEYPORT!=0xf0) ;//等待按键是否释放
Delay15Ms();//延时
return i;
}
/*
入口参数:
Key:待处理的按键值
出口参数:无
*/
void Process_Key(uchar Key)
{
switch(SysMode)
{
case 0://正常显示模式――显示温度值
if(Key==KEYSET) //用户按下设置键
{
Ini_Ms1();//初始化上限报警设置
562
DispCon=1;
}
break;
case 1://设置上限模式
case 2://设置下限模式
DispCon=1;
Set_Alarm(Key,SysMode);//对按键进行处理
break;
}
}
/*
入口参数:
num:待显示的字符
出口参数:无
*/
void Disp_One_Led(uchar num)
{
uchar i;
SCL=0;//控制SCL输出低电平
for(i=0;i<8;i++)//需要发送8位二进制数
{
SDA=num&0x80;//将数据最高位通过SDA引脚发送出
SCL=1; //控制SCL输出高电平
SCL=0; //控制SCL输出低电平
num<<=1;//生成下次发送的最高位
}
}
void Disp_All_Led()
{
uchar i,j;
for(i=0;i<4;i++)//4位LED数码管
{
j=SEGCODE[DB[i]];
if(i==2) //有一位要带点显示
j-=0x80;
Disp_One_Led(j); //将显示缓冲区的某个字符显示
}
}
563
/*
入口参数:
num:填充缓冲区的温度值
出口参数:无
*/
void Fill_Buf(uint mm)
{
uchar i;
if (mm>498)
{
DB[0]=POSICHAR;//生成+号
mm-=499;//得到温度值
}
else
{
DB[0]=NEGCHAR;//生成负号
mm=499-mm;
}
for(i=3;i>0;i--)//温度值填充显示缓冲区
{
DB[i]=mm%10;
mm/=10;
}
}
void Fresh_LED()
{
uint j;
if(DispCon==1)//是否刷新显示
{
DispCon=0;
switch(SysMode)
{
case 0://正常显示与报警处理
j=Read_Temp();
Fill_Buf(j);
Disp_All_Led();
Process_Alarm(j);//报警处理
break;
case 1:
564
case 2://设置上、下限报警值,闪烁显示操作
if(DisplayNormal==1)
DB[PT]=Inputt;//正常显示值
else
DB[PT]=POSICHAR;//空白字符值
Disp_All_Led();
}
}
}
/*
入口参数:无
出口参数:温度转化后的数字量。
*/
uint Start_Max187()
{
uchar i;
uint j;
MCLK=0;
CS187=0;//片选信号变低
for(i=0;i<10;i++)//延时等待转换完毕
;
MCLK=1;//MCLK发一个脉冲
MCLK=0;
for(i=0;i<12;i++) //接收12位转换数据
{
j<<=1;
MCLK=1;
if(MSDA==1)
j|=0x0001;
MCLK=0;
}
for(i=0;i<10;i++)//延时
;
return j;//返回转换值
}
/*
入口参数:无
出口参数:实际温度值。
*/
565
uint Read_Temp()
{
unsigned int j;
unsigned long m1;
float m2;
j=Start_Max187();//读温度转换值
m1=125L*j;//根据测量电压与铂电阻的关系,计算得出铂电阻阻值
m2=1142784+m1;
m1=14217216-m1;
m2*=1000000;
m1=m2/m1;//铂电阻阻值存于m1中
if(m1>100000)//根据电阻与温度的关系,计算温度值
{ //温度是零上
m1-=100000;
m1*=100;
j=m1/3851;
j+=499;
}
else
{ //温度是零下的
m1=100000-m1;
m1*=100;
j=m1/3851;
j=499-j;
}
return j;
}
void Process_Alarm(uint temp)
{
if(temp>upperv)
{ //上限报警,红色亮,蜂鸣器响
LEDREDCON=0;
SPEAKERCON=0;
}
else if(temp<lowerv)
{ //下限报警,绿色亮,蜂鸣器响
LEDGREENCON=0;
SPEAKERCON=0;
}
566
else
{ //没有报警发生,
LEDGREENCON=1;
SPEAKERCON=1;
LEDGREENCON=1;
}
}
void Ini_Timer0()
{
TMOD=0X01;//T0 工作于方式1
TR0=0;
TH0=(65536-50000)/256;//TH0 赋初值
TL0=(65536-50000)%256;//TL0 赋初值
TR0=1;//启动定时器T0
ET0=1;//开放T0中断
}
void Timer0() interrupt 1
{
TR0=0;
TH0=(65536-50000)/256; //TH0 赋初值
TL0=(65536-50000)%256; //TL0 赋初值
TR0=1; //启动定时器T0
TimeCnt++;
if(TimeCnt>=40)
{//2S时间到
TimeCnt=0;
DispCon=1;//刷新显示
}
if(freshcon==1)
{
if(TimeCnt%4==0)
{//100ms时间到,闪烁显示控制位取反
DisplayNormal=~DisplayNormal;
DispCon=1;
}
}
}
void Ini_System()
{
567
Ini_Timer0();//初始化定时器T0
EA=1;//开放总中断
Ini_Ms0();
upperv=998;
lowerv=0;
DispCon=1;//刷新显示
}
void Ini_Ms0()
{
SysMode=0;//模式0
freshcon=0; //禁止闪烁显示
}
void Ini_Ms1()
{
SysMode=1;//模式1
Fill_Buf(upperv);//填充显示缓冲区
PT=0;//位置变量置0
freshcon=1;//闪烁显示
Inputt=DB[0];
}
void Ini_Ms2()
{
SysMode=2;//模式2
Fill_Buf(lowerv);//填充显示缓冲区
PT=0;
Inputt=DB[0];
}
/*
入口参数:
Key:按键值。
Mode:系统模式。
出口参数:无。
*/
void Set_Alarm(uchar Key,uchar mode)
{ //Key 按键值mode 系统模式
uint j;
switch(Key)
{
case 0:
568
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9: //数字按键
switch(PT)
{
case TEMPSECOND:
if(Key<5)//报警值小于50
Inputt=Key;
break;
case SIGNPOSI://符号位时,不接收数字
break;
default:
Inputt=Key;
}
break;
case KEYSIGN: //符号按键值
if(PT==SIGNPOSI)
{
if(Inputt==POSICHAR) //符号发生改变
Inputt=NEGCHAR;
else
Inputt=POSICHAR;
}
break;
case KEYNEXT://NEXT按键
DB[PT]=Inputt;//保存当前设置值
PT++;//位置变量加一
if(PT>3)
PT=0;//一共有4个设置位
Inputt=DB[PT];
break;
case KEYSET://SET按键
DB[PT]=Inputt;//保存设置值
569
j=DB[1]*100+DB[2]*10+DB[3];//根据输入值,生成报警值
if (DB[0]==POSICHAR)
j+=499;
else
j=499-j;
if(mode==1)
{
upperv=j; //保存上限报警值
Ini_Ms2();//初始化模式2
}
else
{
lowerv=j;//保存下限报警值
Ini_Ms0();//初始化模式0
}
break;
}
}
void main()
{
uchar Key;
Ini_System();//初始化系统
while(1)
{
Fresh_LED();//刷新显示
Key=Scan_Key();//扫描按键
if(Key!=NO_KEY)
Process_Key(Key);//如果有按键,按键处理
}
}
570。