第六届考查的是一个DS1302的时间显示和一个DS18B20的温度间隔采集,然后保存10个数据。
主要的难点我觉得是如何采集和保存10个温度数据和与该界面无关的按键操作无效。
设备工作模式的说明的3,4点
1.温度采集本身有时间间隔,所以不能放到中断里直接读取,通过设置一个中间变量,保存中间变量的数据,来进行读取。2.保存温度数据要在中断里执行,主程序里面过多语句的话,会影响采集温度的时效性和显示。3.设备工作模式的3,4点通过设置标志位,判断标志位,使与本界面无关的按键操作无效。
代码风格学习大科的,相对简单通俗易懂。
主函数
#include <STC15F2K60S2.H>
#include "ds1302.h"
#include "onewire.h"
#define uchar unsigned char
#define uint unsigned int
void display1(uchar yi,uchar er,uchar san,uchar si);
void display2(uchar wu,uchar liu,uchar qi,uchar ba);
void delayms(int ms);
void writetime();
void readtime();
void Timer0Init(void);
void keyscan();
uchar temget();
uchar tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff};
uchar time[]={50,59,23,2,3,1,20};
uchar yi,er,san,si,wu,liu,qi,ba;
uchar set=0,delay=1,flag,num,n,m,fla;
uchar wendu[10];
int tt;
void allinit()
{
P2=0xa0;
P0=0x00;
P2=0x80;
P0=0xff;
P2=0xc0;
P2=0xff;
P2=0xe0;
P0=0xff;
}
void main()
{
allinit();
Timer0Init();
writetime();
while(1)
{
keyscan();
num=temget();
if(set==0)
{
yi=11;er=11;san=11;si=11;wu=11;liu=10;qi=delay/10;ba=delay%10;
}
else if(set==1)
{
if(flag==0)
{
readtime();
yi=time[2]/10;er=time[2]%10;si=time[1]/10;wu=time[1]%10;qi=time[0]/10;ba=time[0]%10;
if(time[0]%2==0)
{
san=10;liu=10;
if(m==10)
{
P2=0x80;P0=0xfe;
}
}
else if(time[0]%2==1)
{
san=11;liu=11;
if(m==10)
{
P2=0x80;P0=0xff;
}
}
}
else if(flag==1)
{
yi=10;er=n/10;;san=n%10;si=11;wu=11;liu=10;qi=wendu[n]/10;ba=wendu[n]%10;
fla++;
if(fla==100)
{
fla=0;
n++;
if(n==10)
{
n=0;
}
}
}
}
display1(yi,er,san,si);
display2(wu,liu,qi,ba);
}
}
按键执行函数
void keyscan()
{
if(P30==0) //S7
{
delayms(5);
if(P30==0)
{
if(set==1)
{
if(flag==1)
{
set=0;n=0;
flag=0;
}
}
}
while(!P30);
}
else if(P31==0)//S6
{
delayms(5);
if(P31==0)
{
if(set==1)
{
if(m==10)
{
flag=1;m=0;
P2=0x80;P0=0xff;
}
}
}
while(!P31);
}
else if(P32==0) //S5
{
delayms(5);
if(P32==0)
{
if(set==0)
{
set=1;
ET0=1;EA=1;
}
}
while(!P32);
}
else if(P33==0) //S4
{
delayms(5);
if(P33==0)
{
if(set==0)
{
if(delay==1)delay=5;
else if(delay==5)delay=30;
else if(delay==30)delay=60;
else if(delay==60)delay=1;
}
}
while(!P33);
}
}
定时中断函数
void Timer0Init(void) //5毫秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x00; //设置定时初值
TH0 = 0x28; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
void time0() interrupt 1
{
tt++;
if(tt==delay*200)
{
tt=0;
wendu[m]=num;
m++;
if(m==10)
{
ET0=0;EA=0;
}
}
}
温度读取和时钟显示函数
uchar temget()
{
uchar temp,low,high;
Init_DS18B20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay_OneWire(200);
Init_DS18B20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
low=Read_DS18B20();
high=Read_DS18B20();
temp=high<<4;
temp|=low>>4;
return temp;
}
void writetime()
{
uchar i,add=0x80;
for(i=0;i<7;i++)
{
time[i]=((time[i]/10)<<4)|(time[i]%10);
}
Write_Ds1302_Byte(0x8e,0x00);//打开写保护
for(i=0;i<7;i++)
{
Write_Ds1302_Byte(add,time[i]);
add=add+2;
}
Write_Ds1302_Byte(0x8e,0x80);//关闭写保护
}
void readtime()
{
uchar i,add=0x81;
Write_Ds1302_Byte(0x8e,0x00);
for(i=0;i<7;i++)
{
time[i]=Read_Ds1302_Byte(add);
add=add+2;
time[i]=(time[i]/16)*10+time[i]%16;
}
Write_Ds1302_Byte(0x8e,0x80);
}
数码管显示和延时函数
void display1(uchar yi,uchar er,uchar san,uchar si)
{
P2=0xc0;
P0=0x01;
P2=0xe0;
P0=tab[yi];
delayms(1);
P2=0xc0;
P0=0x02;
P2=0xe0;
P0=tab[er];
delayms(1);
P2=0xc0;
P0=0x04;
P2=0xe0;
P0=tab[san];
delayms(1);
P2=0xc0;
P0=0x08;
P2=0xe0;
P0=tab[si];
delayms(1);
}
void display2(uchar wu,uchar liu,uchar qi,uchar ba)
{
P2=0xc0;
P0=0x10;
P2=0xe0;
P0=tab[wu];
delayms(1);
P2=0xc0;
P0=0x20;
P2=0xe0;
P0=tab[liu];
delayms(1);
P2=0xc0;
P0=0x40;
P2=0xe0;
P0=tab[qi];
delayms(1);
P2=0xc0;
P0=0x80;
P2=0xe0;
P0=tab[ba];
delayms(1);
}
void delayms(int ms)
{
int i,j;
for(i=0;i<ms;i++)
for(j=0;j<845;j++);
}
onewire和ds1302驱动为官方驱动
来源:CSDN
作者:学单片机的菜鸟
链接:https://blog.csdn.net/qq_43783627/article/details/104647712