编程部分是笔者自己编写,且已在板子上调试成功,免费分享给读者,如有不足忘指正。
使用的芯片为竞赛芯片IAP,并非练习芯片52。
功能简述
设备按照用户通过按键设定的时间间隔自动采集并存储温度数据,并具有采集完成提醒、数码管显示等功能,系统硬件部分主要由按键电路、电源供电电路、RTC 时钟、传感器电路和显示电路组成.
单总线驱动程序、DS1302 芯片驱动程序、CT107D 单片机考试平台电路原理图以及本题所涉及到的芯片数据手册,可参考计算机上的电子文档。程序流程图及相关工程文件请以考生号命名,并保存在计算机上的考生文件夹中(文件夹名为考生准考证号,文件夹位于Windows 桌面上)
设计任务及要求
main.c
#include"STC15F2K60S2.h"
#include"ds1302.h"
#include"onewire.h"
#define uchar unsigned char
#define uint unsigned int
bit blink;
bit flag_wendu;
uchar code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff};
uchar yi,er,san,si,wu,liu,qi,ba; //yi---ba为1-8个数码管
uchar flag_S4; //标志位
uchar samplemiao; //采集间隔
uchar flag_scan;
uchar shi,fen,miao; //时钟时分秒
uchar wendu; //温度
uchar samplewendu[10]; //采集的10次温度记录在该数组
uchar suoyin; //索引
void allinit(void);
void Timer0Init(void);
void timer0();
void keyscan(void);
void display1(uchar yi,uchar er);
void display2(uchar san,uchar si);
void display3(uchar wu,uchar liu);
void display4(uchar qi,uchar ba);
void delayms(uint ms);
void main(void)
{
allinit();
Timer0Init();
set_sfm(23,59,50); //默认RTC时间
yi=11;er=11;san=11;si=11;wu=11;liu=10;qi=0;ba=1; //设备上电后,自动进入参数设置界面
while(1)
{
wendu=read_temperature();// 读温度
shi=Read_Ds1302(0x85); //读时间
fen=Read_Ds1302(0x83);
miao=Read_Ds1302(0x81);
keyscan(); //按键判断
if(flag_scan==3) //关定时器
{
ET0=1;
EA=1;
}
if(flag_wendu==1)//开始写温度索引显示
{
flag_wendu=0;
flag_scan=5;
qi=wendu/10;ba=wendu%10;
ET0=0;EA=0;
}
if(flag_scan==5)
{
yi=11;er=11;san=11;si=11;wu=11;liu=11;qi=11;ba=11;
P2=0X80;P0=0XFE;
delayms(100);
P2=0X80;P0=0XFF;
delayms(100);
}
if(flag_scan==2)
{
flag_scan=0; //下面为按照时间先后顺序,切换显示设备内存储的温度数据
yi=10;er=suoyin/10;san=suoyin%10;si=11;wu=11;liu=10;qi=samplewendu[suoyin]/10;ba=samplewendu[suoyin]%10;
suoyin++; //索引值加1;
if(suoyin==10) suoyin=0; //重新从第一个采集的温度显示
}
display1(yi,er);
display2(san,si);
display3(wu,liu);
display4(qi,ba);
}
}
void allinit(void) // 初始化
{
P2=0XA0;P0=0X00;
P=0X80;P0=0XFF;
P2=0XC0;P0=0XFF;
P2=0XFF;P0=0XFF;
}
void Timer0Init(void) //5毫秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x00; //设置定时初值
TH0 = 0x28; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
void timer0() interrupt 1 using 1
{
uchar i,j,k;
i++;j++;k++;
if(i==200)
{
i=0;
blink=!blink; //时钟显示界面下,提示符 1、2 以 1 秒为间隔闪烁
if(blink==1)
{
san=10;liu=10;
}
else if(blink==0)
{
san=11;liu=11;
}
}
if(j==1&&(flag_scan==3)&&samplemiao==1) //采集间隔1s
{
uchar k; //为什么让j=1,是为了方便多次记录温度,但这样写每次会有5ms的误差。
//wendu=read_temperature();
P2=0xa0;P0=0x00;
samplewendu[k++]=wendu; //记录温度
if(k==10)
{
k=1;
flag_wendu=1;
}
}
if(j==200&&flag_scan==3&&samplemiao==1) j=0;//5*200ms后j=0,即1s后再次记录温度
if(k==1&&(flag_scan==3)&&samplemiao==5) //采集间隔5s
{ //30s,60s的没写,但类似1,5s编程
uchar k;
samplewendu[k++]=wendu;
if(k==10)
{
k=1;
flag_wendu=1;
}
}
if(k=1000&&flag_scan==3&&samplemiao==5) k=0;//5*1000ms后k=0,即5s后再次记录温度
}
void keyscan(void)
{
if(P30==0) //S4按下
{
delayms(5);
if(P30==0)
{
if(flag_scan==0) //索引界面显示后
{
flag_scan=4;//参数切换
yi=11;er=11;san=11;si=11;wu=11;liu=10;qi=0;ba=1; //初始状态
flag_S4=0;
}
}
while(!P30);//按键弹起退出循环
}
else if(P31==0)
{
delayms(5);
if(P31==0) //S5按键按下
{
flag_scan=2;P2=0X80;P0=0XFF;
}
while(!P31);
}
else if(P32==0) //S6按下
{
delayms(5);
if(P32==0)
{
flag_scan=3;
samplemiao=qi*10+ba; //记录采集间隔
wendu=read_temperature();
//wendu=30;
suoyin=0;
//samplewendu[0]=wendu;
}
while(!P32);
}
else if(P33==0) //S7按下
{
delayms(5);
if(P33==0)
{
flag_scan=4; //进入参数显示界面
flag_S4++;
}
while(!P33);
}
if(flag_scan==4)
{
EA=0;ET0=0; //定时器开始工作
yi=11;er=11;san=11;si=11;wu=11;liu=10;
if(flag_S4==0) {qi=0;ba=1;} //采集间隔显示1s
if(flag_S4==1) {qi=0;ba=5;} //5s
if(flag_S4==2) {qi=3;ba=0;} //30s
if(flag_S4==3) {qi=6;ba=0;} //60s
if(flag_S4==4) {flag_S4=0;qi=0;ba=1;} //60后再按一次重新从1开始
}
if(flag_scan==3)
{
yi=shi/16;er=shi%16; //显示时间,时间读出来为16进制要转换成十进制
si=fen/16;wu=fen%16;
qi=miao/16;ba=miao%16;
}
}
void display1(uchar yi,uchar er)
{
P2=0XC0;P0=0X01;
P2=0XFF;P0=tab[yi];
delayms(1);
P2=0XC0;P0=0X02;
P2=0XFF;P0=tab[er];
delayms(1);
}
void display2(uchar san,uchar si)
{
P2=0XC0;P0=0X04;
P2=0XFF;P0=tab[san];
delayms(1);
P2=0XC0;P0=0X08;
P2=0XFF;P0=tab[si];
delayms(1);
}
void display3(uchar wu,uchar liu)
{
P2=0XC0;P0=0X10;
P2=0XFF;P0=tab[wu];
delayms(1);
P2=0XC0;P0=0X20;
P2=0XFF;P0=tab[liu];
delayms(1);
}
void display4(uchar qi,uchar ba)
{
P2=0XC0;P0=0X40;
P2=0XFF;P0=tab[qi];
delayms(1);
P2=0XC0;P0=0X80;
P2=0XFF;P0=tab[ba];
delayms(1);
P2=0XC0;P0=0XFF;
P2=0XFF;P0=0XFF;
}
void delayms(uint ms)
{
uint i,j;
for(i=0;i0;j--);
}
}
onewire.c
/*
程序说明: 单总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台(外部晶振12MHz) STC89C52RC单片机
日 期: 2011-8-9
*/
#include"STC15F2K60S2.h"
sbit DQ = P1^4; //单总线接口
//单总线延时函数
void Delay_OneWire(unsigned int t) //STC89C52RC
{
while(t--);
}
//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(50);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(50);
}
//从DS18B20读取一个字节
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(50);
}
return dat;
}
//DS18B20设备初始化
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(120);
DQ = 0;
Delay_OneWire(800);
DQ = 1;
Delay_OneWire(100);
initflag = DQ;
Delay_OneWire(50);
return initflag;
}
unsigned char read_temperature(void)
{
unsigned char temp;
unsigned char low,high;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay_OneWire(200);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
high=Read_DS18B20();
low=Read_DS18B20();
high=high<<4;
low=low>>4;
temp=temp|low;
return temp;
}
ds1302.c
/*
程序说明: DS1302驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台 8051,12MHz
日 期: 2011-8-9
*/
#include"STC15F2K60S2.h"
#include
#include
sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST = P1^3; // DS1302复位
unsigned char shijian[]={0,30,8,0,0,0,0};
void Write_Ds1302_Byte(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK=0;
SDA=temp&0x01;
temp>>=1;
SCK=1;
}
}
void Write_Ds1302( unsigned char address,unsigned char dat )
{
RST=0;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
SCK=0;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
RST=1;
_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
Write_Ds1302_Byte(address);
Write_Ds1302_Byte(dat); /////////////////////////////////////////////////
RST=0;
}
unsigned char Read_Ds1302 ( unsigned char address )
{
unsigned char i,temp=0x00;/////////////////////////////////////
RST=0;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
SCK=0;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
RST=1;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
Write_Ds1302_Byte(address);
for (i=0;i<8;i++)
{
SCK=0;
temp>>=1;
if(SDA)
temp|=0x80;
SCK=1;
}
RST=0;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
RST=0;
SCK=0;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
SCK=1;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
SDA=0;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
SDA=1;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
//dat1=temp/16;
//dat2=temp%16;
// temp=dat1*10+dat2;/////////////////////////////////////////////////////////////////
return (temp);
}
void set_sfm(unsigned char shi,unsigned char fen,unsigned char miao)
{
Write_Ds1302(0x8e,0x00);
Write_Ds1302(0x84,(shi/10)*16+shi%10);
Write_Ds1302(0x82,(fen/10)*16+fen%10);
Write_Ds1302(0x80,(miao/10)*16+miao%10);
Write_Ds1302(0x8e,0x80);
}
ds1302.h