看之前强烈建议先自己做一遍!!!
- 演示效果
- 题目讲解
- 代码
- main.c
- ds1302.c
- ds1302.h
- onewire.c
- onewire.h
- 工程文件
演示效果
题目讲解
首先我们从系统框图看起:
做题之前要做的是把系统框图里面的各个模块先提前调试好!!!
调试完成后进一步看题目:
然后按照如图数码管显示界面进行显示。
uchar SMG_mode=0,temp; //数码管模式定义 温度定义
uchar time_gap=1; //采集间隔时间定义
void main(void)
{
init(); //初始开发板
while(1)
{
temp=rd_temperature();
if(SMG_mode==0) //界面1,设置界面
{
get_time(); //时间获取
SMG[0]=SMG[1]=SMG[2]=SMG[3]=SMG[4]=20; //数码管全熄
SMG[5]=21;SMG[6]=time_gap/10;SMG[7]=time_gap%10; //显示采集间隔
}
else if(SMG_mode==1)//界面2,时钟显示界面
{
SMG[0]=time[2]/10;SMG[1]=time[2]%10; //显示时
SMG[3]=time[1]/10;SMG[4]=time[1]%10; //显示分
SMG[6]=time[0]/10;SMG[7]=time[0]%10; //显示秒
}
SMG_output();
Dkey_scan();
}
}
注意要求:时钟界面,提示符1,2以1秒为间隔闪烁。
所以提示符要放在定时器里面进行赋值显示。
//定时器初始化
void Timer0Init(void) //5毫秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x00; //设置定时初值
TH0 = 0x28; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
EA=1;ET0=1; //打开定时器0中断
}
uchar t,state=0; //中断计数 显示状态
//定时器0中断服务函数
void time0() interrupt 1
{
if(SMG_mode==1)
{
t++;
if(t>=200) //200*5 以一秒为间隔
{
t=0;
if(state==1)
{
state=0;SMG[2]=SMG[5]=20; //熄灭
}
else
{
state=1;SMG[2]=SMG[5]=21; //亮
}
}
}
}
由于是按下S5,从设置界面进入时间显示界面,所以按键扫描对应的程序也要修改。由于时间要在按键按下才开始计时,所以初始化时间一定要在按键中初始化!!!按下S4。设置界面由1s,5s,30s,60s来回切换
void Dkey_scan(void)
{
static uchar keybyte=0;
static uchar key;
if(((P3&0X0F)!=0X0F)&&(keybyte==0))
{
delay5ms();
if((P3&0X0F)!=0X0F)
{
keybyte=1;key=P3&0x0f;
}
}
if((keybyte==1)&&((P3&0X0F)==0X0F))
{
if((P3&0X0F)==0X0F)
{
switch(key)
{
case 0x0e:
break;
case 0x0d:
break;
case 0x0b: //S5
if(SMG_mode==0){SMG_mode=1;ds1302_init();} //按下S5进入时间显示,并初始化时间
break;
case 0x07:
if(SMG_mode==0) //间隔时间只能设置模式改变
{ //时间间隔切换
if(time_gap==1)time_gap=5;
else if(time_gap==5)time_gap=30;
else if(time_gap==30)time_gap=60;
else if(time_gap==60)time_gap=1;
}
break;
}
keybyte=0;
}
}
}
然后接着往下看题目。
由于要进行时间采集,所以定时器的使用,在定时器内进行采集。
bit enable=0; //控制采集打开和关闭
uchar Temp_stat[10]={0,0,0,0,0,0,0,0,0,0};//温度数据保存
uchar count=0;//定义采集次数
uint stat_t=0; //采集定时器计数
//定时器0中断服务函数
void time0() interrupt 1
{
if(enable==1)
{
stat_t++;
if((stat_t*5)>=(time_gap*1000)) //5*s >=采集时间进行采集*1000ms
{
stat_t=0;
Temp_stat[count]=temp; //采集
count++; //计数
if(count>=10){P2=0X80;P0=0Xfe; //点亮L1
count=0;enable=0;SMG_mode=2;} //采集完10次关闭,数码管显示切换
}
}
if(SMG_mode==1)
{
t++;
if(t>=200) //200*5 以一秒为间隔
{
t=0;
if(state==1)
{
state=0;SMG[2]=SMG[5]=20; //熄灭
}
else
{
state=1;SMG[2]=SMG[5]=21; //亮
}
}
}
}
采集完成后的温度显示。
else if(SMG_mode==2) //采集完成后的温度显示
{
SMG[0]=21;SMG[1]=count/10; //-00
SMG[2]=count%10;SMG[3]=SMG[4]=20;
SMG[6]=Temp_stat[count]/10;SMG[7]=Temp_stat[count]%10;
}
然后就是对按键进行修改。
S6, L1 熄灭,按照时间先后顺序,切换显示设备内存储的温度数据;
S7 按键进入参数设置界面(图 1),待用户输入温度采集间隔之后,可以进行
下一次的温度采集工作。
void Dkey_scan(void)
{
static uchar keybyte=0;
static uchar key;
if(((P3&0X0F)!=0X0F)&&(keybyte==0))
{
delay5ms();
if((P3&0X0F)!=0X0F)
{
keybyte=1;key=P3&0x0f;
}
}
if((keybyte==1)&&((P3&0X0F)==0X0F))
{
if((P3&0X0F)==0X0F)
{
switch(key)
{
case 0x0e:if(SMG_mode==2){SMG_mode=0;count=0;time_gap=1;}//S7重新设置
break;
case 0x0d:if(SMG_mode==2){P2=0X80;P0=0Xff; //熄灭L1
count++;if(count==10)count=0;} //按顺序切换
break;
case 0x0b: //S5
if(SMG_mode==0){SMG_mode=1;
ds1302_init();enable=1;} //按下S5进入时间显示,并初始化时间,打开温度捕获使能
break;
case 0x07:
if(SMG_mode==0) //间隔时间只能设置模式改变
{ //时间间隔切换
if(time_gap==1)time_gap=5;
else if(time_gap==5)time_gap=30;
else if(time_gap==30)time_gap=60;
else if(time_gap==60)time_gap=1;
}
break;
}
keybyte=0;
}
}
}
最后按照如图要求进行微调就做完了。
代码
main.c
#include <stc15f2k60s2.h>
#include "intrins.h"
#include "onewire.h"
#include "ds1302.h"
#define uchar unsigned char
#define uint unsigned int
void SMG_output(void);
void init(void);
void Delay1ms(void);
void delay5ms(void);
void Dkey_scan(void);
void Timer0Init(void);
extern uchar time[7]; //ds1302.c中定义的存储时间的数组
uchar tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,\
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xff,0xbf};
uchar SMG[8]={20,20,20,20,20,20,20,20};//初始显示10,全息数码管
uchar SMG_mode=0,temp; //数码管模式定义 温度定义
uchar time_gap=1; //采集间隔时间定义
uchar t,state=0; //中断计数 显示状态
bit enable=0; //控制采集打开和关闭
uchar Temp_stat[10]={0,0,0,0,0,0,0,0,0,0};//温度数据保存
uchar count=0;//定义采集次数
uint stat_t=0; //采集定时器计数
void main(void)
{
init(); //初始开发板
Timer0Init();
while(1)
{
temp=rd_temperature();
if(SMG_mode==0) //界面1,设置界面
{
SMG[0]=SMG[1]=SMG[2]=SMG[3]=SMG[4]=20; //数码管全熄
SMG[5]=21;SMG[6]=time_gap/10;SMG[7]=time_gap%10; //显示采集间隔
}
else if(SMG_mode==1)//界面2,时钟显示界面
{
get_time(); //时间获取
SMG[0]=time[2]/10;SMG[1]=time[2]%10; //显示时
SMG[3]=time[1]/10;SMG[4]=time[1]%10; //显示分
SMG[6]=time[0]/10;SMG[7]=time[0]%10; //显示秒
}
else if(SMG_mode==2) //采集完成后的温度显示
{
SMG[0]=21;SMG[1]=count/10; //-00
SMG[2]=count%10;SMG[3]=SMG[4]=20;
SMG[6]=Temp_stat[count]/10;SMG[7]=Temp_stat[count]%10;
}
SMG_output();
Dkey_scan();
}
}
void Dkey_scan(void)
{
static uchar keybyte=0;
static uchar key;
if(((P3&0X0F)!=0X0F)&&(keybyte==0))
{
delay5ms();
if((P3&0X0F)!=0X0F)
{
keybyte=1;key=P3&0x0f;
}
}
if((keybyte==1)&&((P3&0X0F)==0X0F))
{
if((P3&0X0F)==0X0F)
{
switch(key)
{
case 0x0e:if(SMG_mode==2){SMG_mode=0;count=0;time_gap=1;}//S7重新设置
break;
case 0x0d:if(SMG_mode==2){P2=0X80;P0=0Xff; //熄灭L1
count++;if(count==10)count=0;} //按顺序切换
break;
case 0x0b: //S5
if(SMG_mode==0){SMG_mode=1;
ds1302_init();enable=1;} //按下S5进入时间显示,并初始化时间,打开温度捕获使能
break;
case 0x07:
if(SMG_mode==0) //间隔时间只能设置模式改变
{ //时间间隔切换
if(time_gap==1)time_gap=5;
else if(time_gap==5)time_gap=30;
else if(time_gap==30)time_gap=60;
else if(time_gap==60)time_gap=1;
}
break;
}
keybyte=0;
}
}
}
//定时器0中断服务函数
void time0() interrupt 1
{
if(enable==1)
{
stat_t++;
if((stat_t*5)>=(time_gap*1000)) //5*200s >=采集时间进行采集*1000ms
{
stat_t=0;
Temp_stat[count]=temp; //采集
count++; //计数
if(count>=10){P2=0X80;P0=0Xfe; //点亮L1
count=0;enable=0;SMG_mode=2;} //采集完10次关闭,数码管显示切换
}
}
if(SMG_mode==1)
{
t++;
if(t>=200) //200*5 以一秒为间隔
{
t=0;
if(state==1)
{
state=0;SMG[2]=SMG[5]=20; //熄灭
}
else
{
state=1;SMG[2]=SMG[5]=21; //亮
}
}
}
}
void Timer0Init(void) //5毫秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x00; //设置定时初值
TH0 = 0x28; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
EA=1;ET0=1; //打开定时器0中断
}
void SMG_output(void)
{
uchar i;
for(i=0;i<8;i++)
{
P2=(P2&0X1F)|0Xc0;
P0=(1<<i);
P2=(P2&0X1F)|0Xe0;
P0=tab[SMG[i]];
Delay1ms();
}
P2=(P2&0X1F)|0Xc0;
P0=0Xff;
P2=(P2&0X1F)|0Xe0;
P0=0Xff;
}
void init(void)
{
P2=(P2&0X1F)|0XA0;
P0=0X00;
P2=(P2&0X1F)|0X80;
P0=0Xff;
P2=(P2&0X1F)|0Xc0;
P0=0Xff;
P2=(P2&0X1F)|0Xe0;
P0=0Xff;
}
void Delay1ms(void) //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
_nop_();
i = 11;
j = 190;
do
{
while (--j);
} while (--i);
}
void delay5ms(void) //@11.0592MHz
{
unsigned char i, j;
i = 54;
j = 199;
do
{
while (--j);
} while (--i);
}
ds1302.c
#include "ds1302.h"
uchar time[7]={50,59,23,0,0,0,0};
void ds1302_init(void)
{
uchar i,j=0x80;
Write_Ds1302_Byte(0x8e,0x00);
for(i=0;i<7;i++)
{
Write_Ds1302_Byte(j,time[i]);
j +=2;
}
Write_Ds1302_Byte(0x8e,0x80);
}
void get_time(void)
{
uchar i,j=0x81;
Write_Ds1302_Byte(0x8e,0x00);
for(i=0;i<7;i++)
{
time[i]=Read_Ds1302_Byte(j);
j +=2;
}
Write_Ds1302_Byte(0x8e,0x80);
}
//
void Write_Ds1302(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK = 0;
SDA = temp&0x01;
temp>>=1;
SCK=1;
}
}
//
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )
{
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
Write_Ds1302(((dat/10)<<4)|(dat%10));
RST=0;
}
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
unsigned char i,temp=0x00;
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
for (i=0;i<8;i++)
{
SCK=0;
temp>>=1;
if(SDA)
temp|=0x80;
SCK=1;
}
RST=0; _nop_();
SCK=0; _nop_();
SCK=1; _nop_();
SDA=0; _nop_();
SDA=1; _nop_();
return (((temp/16)*10)+(temp%16));
}
ds1302.h
#ifndef __DS1302_H
#define __DS1302_H
#include <stc15f2k60s2.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit SCK = P1^7;
sbit SDA = P2^3;
sbit RST = P1^3;
void ds1302_init(void);
void get_time(void);
void Write_Ds1302(unsigned char temp);
void Write_Ds1302_Byte( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302_Byte( unsigned char address );
#endif
onewire.c
#include "onewire.h"
unsigned char rd_temperature(void)
{
unsigned char de,gao;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
de=Read_DS18B20();
gao=Read_DS18B20();
return((de >>4)|(gao<<4));
}
//
void Delay_OneWire(unsigned int t)
{
t=t*8;
while(t--);
}
//
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;
}
onewire.h
#ifndef __ONEWIRE_H
#define __ONEWIRE_H
#include <stc15f2k60s2.h>
sbit DQ = P1^4;
unsigned char rd_temperature(void); //; ;
void Delay_OneWire(unsigned int t);
unsigned char Read_DS18B20(void);
bit init_ds18b20(void);
void Write_DS18B20(unsigned char dat);
#endif
工程文件
有注释的工程文件