设计要求
从DS18B20温度传感器上获取环境温度,并将其温度值显示到数码管上。
按键“S16”定义为“温度参数”按键,按下按键S16按键可将当前温度设置为温度参数。
当温度超过温度参数时,LED1指示灯亮,否则LED1指示灯熄灭;
数码管显示格式如下图所示:
温度为26.2°C(数码管最低位显示固定字符C)
备注:
单片机IRC振荡器频率设置为12MHz。
按键模式:KBD;扩展方式:IO模式。
显示的温度值保留小数点后一位有效数字。
个人代码
#include <STC15F2K60S2.H>
#include "intrins.h"
sbit DQ=P1^4;
code unsigned char Seg_Table[] = {
0xc0, //0
0xf9, //1
0xa4, //2
0xb0, //3
0x99, //4
0x92, //5
0x82, //6
0xf8, //7
0x80, //8
0x90, //9
0xc6, //C 10
0xff //熄灭 11
};
unsigned char Seg_Buff[]={11,11,11,11,2,6,2,10};
float tempermax=26.2,temper;
unsigned char flag_seg=0,flag_key=0,flag_temper=0,flag_tempermax=0;
unsigned char keyval,keyold,keydown,keyup;
void init74hc138(unsigned char n){
P2=(P2&0x1f)|(n<<5);
P2&=0x1f;
}
void init(){
P0=0xff;
init74hc138(4);
P0=00;
init74hc138(5);
}
void Delay_OneWire(unsigned int t)
{
unsigned char i;
while(t--){
for(i=0;i<12;i++);
}
}
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
return dat;
}
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag;
}
void r_ds18b20_temper(){
unsigned char th,tl;
EA=0;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
tl=Read_DS18B20();
th=Read_DS18B20();
temper=(th<<8|tl)*0.0625;
EA=1;
}
void Key_Loop(){
P34=0;
keyval=0;
if(P33==0)keyval=1;
keydown=keyval&(keyold^keyval);
keyup=~keyval&(keyold^keyval);
if(keyval&&keyold!=keyval)flag_tempermax=1;
keyold=keyval;
}
void seg(unsigned char addr,num){
P0=0xff;
init74hc138(7);
P0=0x01<<addr;
init74hc138(6);
P0=Seg_Table[num];
if(addr==5)P0&=0x7f;
init74hc138(7);
}
void Seg_Loop(){
static unsigned char i=0;
seg(i,Seg_Buff[i]);
i++;
if(i==8)i=0;
}
void seg_temper(){
Seg_Buff[6]=(int)(temper*10)%10;
Seg_Buff[5]=(int)temper%10;
Seg_Buff[4]=(int)temper/10;
}
void Timer0_Init(void) //100微秒@12.000MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x50; //设置定时初始值
TH0 = 0xFB; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
EA = 1;
}
void main(){
init();
Timer0_Init();
while(1){
if((int)(temper*10)>(int)(tempermax*10)){
P0=0xfe;
init74hc138(4);
}else{
P0=0xff;
init74hc138(4);
}
if(flag_tempermax){
flag_tempermax=0;
tempermax=temper;
}
if(flag_seg){
flag_seg=0;
Seg_Loop();
}
if(flag_key){
flag_key=0;
Key_Loop();
}
if(flag_temper){
flag_temper=0;
r_ds18b20_temper();
seg_temper();
}
}
}
void Timer0_Isr(void) interrupt 1
{
static unsigned char count1=0,count2=0;
static unsigned int count3=0;
count1++;count2++;count3++;
if(count1==2){
count1=0;
flag_seg=1;
}
if(count2==20){
count2=0;
flag_key=1;
}
if(count3==1000){
count3=0;
flag_temper=1;
}
}