功能简述
设备按照用户通过按键设定的时间间隔自动采集并存储温度数据,并具有采集完成提醒、数码管显示等功能,系统硬件部分主要由按键电路、电源供电电路、 RTC 时钟、传感器电路和显示电路组成。 系统框图如图 1 所示:
单总线驱动程序、 DS1302 芯片驱动程序、 CT107D 单片机考试平台电路原理图以及本题所涉及到的芯片数据手册,可参考计算机上的电子文档。程序流程图及相关工程文件请以考生号命名,并保存在计算机上的考生文件夹中(文件夹名为考生准考证号,文件夹位于Windows 桌面上)。
设计任务及要求
1. 数码管显示
1.1 设备上电后,自动进入参数设置界面(图 1) 此时,通过按键 S4 切换 4 个温度采集间隔时间,分别为 1 秒、 5 秒、 30 秒和 60 秒;
按下按键 S5,确认采集间隔时间,并退出参数设置界面(图 1),进入时钟显示界面(图 2)并开始采集温度。
要求: 时钟显示界面(图 2)下,提示符 1、 2 以 1 秒为间隔闪烁
1.2 当设备按照用户设定的采集间隔采集到 10 个数据后,指示灯 L1 闪烁提示本次温度采集已经完成,此时进入数码管温度采集显示界面(图 3):
此时,按下 S6, L1 熄灭,按照时间先后顺序,切换显示设备内存储的温度数据;按下 S7 按键进入参数设置界面(图 1),待用户输入温度采集间隔之后,可以进行下一次的温度采集工作。
说明: 索引指的是当前显示的温度按照采集时间先后顺序的编(00-09)。
2. 温度检测功能
使用 DS18B20 温度传感器完成温度测量功能。
3. RTC
使用 DS1302 时钟芯片完成 RTC 的相关功能。
4. 设备工作模式说明
(1) 默认 RTC 时间: 23 时 59 分 50 秒;
(2) 默认温度数据采集间隔为 1 秒;
(3) 设备处在不同的显示界面下,与该界面无关的按键操作无效;
(4) 温度数据最大存储容量: 10 个
5. 电路原理图设计
使用基本阻容元器件、集成运算放大器设计硬件电路,完成如下功能:
已知某种类型的传感器输出 4-20mA 电流信号,设计电路将电流信号转换为 0V-5V的电压信号。简述所设计电路的工作原理,并绘制出电路原理图。
主函数
#include<stc15f2k60s2.h>
#include "ds1302.h"
#include "onewire.h"
typedef unsigned char uchar;
typedef unsigned int uint;
uchar code SMG_duan[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
uchar code SMG_wei[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
uchar time_display[8]; //时间显示界面
uchar temp_display[8]; //温度显示界面
uchar set_display[8]; //参数设置界面
uchar temperature[10]; //温度数据
uchar mode; //设置采集时间间隔
uchar time_nop[]={1,5,30,60}; //时间间隔
uchar caiji_count=0; //采集次数计数
uchar mode_flag=0; //显示界面选择
uchar shuju_count; //数据
uchar suoyin_count; //索引
uchar real_nop;
bit blink_flag; //闪烁
bit caiji_flag; //采集标志
bit led_flag; //led闪烁
void Timer0Init();
char Key_init();
void delayms(uchar ms);
void main()
{
uchar key_val;
P2=0XA0;P0=0X00;
P2=0X80;P0=0Xff;
Timer0Init();
DS1302_init();
temp_display[0]=0x40; temp_display[3]=0x00;
temp_display[4]=0x00; temp_display[5]=0x40;
set_display[0]=0x00; set_display[1]=0x00; set_display[2]=0x00;
set_display[3]=0x00;
set_display[4]=0x00; set_display[5]=0x40;
while(1)
{
DS1302_read();
time_display[0]=SMG_duan[TIME[2]/16];
time_display[1]=SMG_duan[TIME[2]%16];
time_display[3]=SMG_duan[TIME[1]/16];
time_display[4]=SMG_duan[TIME[1]%16];
time_display[6]=SMG_duan[TIME[0]/16];
time_display[7]=SMG_duan[TIME[0]%16];
key_val=Key_init();
switch(key_val)
{
case 4:
if(mode_flag==0)
{
mode++;
if(mode==4)
mode=0;
}
break;
case 5:
if(mode_flag==0)
{
real_nop=time_nop[mode];
mode_flag=1;
}
break;
case 6:
if(mode_flag==2)
{
led_flag=0;
suoyin_count++;
if(suoyin_count==10)
suoyin_count=0;
P2=0X80;P0=0XFF;P2=0X00;
}
break;
case 7:
if(mode_flag==2)
{
mode_flag=0;
}
break;
}
set_display[6]=SMG_duan[time_nop[mode]/10];
set_display[7]=SMG_duan[time_nop[mode]%10];
if(caiji_flag)
{
caiji_flag=0;
if(caiji_count<10)
{
ET0=0;
temperature[caiji_count]=temp_get();
ET0=1;
}
else
{
led_flag=1;
mode_flag=2;
caiji_count=0; //要置零,数据个数最大为10
}
caiji_count++;
}
temp_display[1]=SMG_duan[suoyin_count/10];
temp_display[2]=SMG_duan[suoyin_count%10];
temp_display[6]=SMG_duan[temperature[suoyin_count]%100/10];
temp_display[7]=SMG_duan[temperature[suoyin_count]%10];
}
}
#define key_input P3
#define key_state_0 0 //判断是否按下
#define key_state_1 1 //判断是否为抖动
#define key_state_2 2 //判断是否弹起
char Key_init()
{
static char key_state = 0;
char key_press, key_return = 0;
uchar key_mask=0x0f;
key_press = key_input&key_mask;
switch (key_state)
{
case key_state_0:
if (key_press!=key_mask)
key_state = key_state_1;
break;
case key_state_1:
if (key_press!=key_mask)
{
if(key_press==0x0e) key_return = 7; //S7
if(key_press==0x0d) key_return = 6; //S6
if(key_press==0x0b) key_return = 5; //S5
if(key_press==0x07) key_return = 4; //S4
key_state = key_state_2;
}
else
key_state = key_state_0;
break;
case key_state_2:
if (key_press==0x0f)
key_state = key_state_0;
break;
}
return key_return;
}
void Timer0Init() //1毫秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xCD; //设置定时初值
TH0 = 0xD4; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
EA=1;
ET0=1;
}
void Timer0() interrupt 1
{
uchar i;
static uint SMG_count=0,blink_count=0,mode_count=0;
SMG_count++;
blink_count++;
if(SMG_count==3)
{
SMG_count=0;
P2=0XC0;P0=0X00;P2=0X00;
P2=0XC0;P0=SMG_wei[i];
if(mode_flag==0)
{
P2=0XE0;P0=~set_display[i];P2=0X00;
}
if(mode_flag==1)
{
P2=0XE0;P0=~time_display[i];P2=0X00;
}
if(mode_flag==2)
{
P2=0XE0;P0=~temp_display[i];P2=0X00;
}
i++;
if(i==8)
i=0;
}
if(blink_count==1000) //1s
{
blink_count=0;
blink_flag=~blink_flag;
if(blink_flag)
{
time_display[2]=0x40; time_display[5]=0x40;
}
else
{
time_display[2]=0x00; time_display[5]=0x00;
}
if(led_flag==1)
{
if(blink_flag)
{
P2=0X80;P0=0XFE;P2=0X00;
}
else
{
P2=0X80;P0=0XFf;P2=0X00;
}
}
}
if(mode_flag==1)
{
mode_count++;
if(mode_count==real_nop*1000)
{
mode_count=0;
caiji_flag=1; //开始采集温度
}
}
}
DS1302时钟模块
#include "ds1302.h"
typedef unsigned char uchar;
typedef unsigned int uint;
uchar code Write_add[]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};
uchar code Read_add[]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
uchar TIME[]={0X50,0X59,0X23,0x00,0x00,0x00,0x19};
void Write_Ds1302_Byte(unsigned char dat)
{
unsigned char i;
SCK = 0;
_nop_();
for (i=0;i<8;i++)
{
if (dat & 0x01) // 等价于if((addr & 0x01) ==1)
{
SDA_SET; //#define SDA_SET SDA=1 /*电平置高*/
}
else
{
SDA_CLR; //#define SDA_CLR SDA=0 /*电平置低*/
}
SCK_SET;
_nop_();
SCK_CLR;
_nop_();
dat = dat >> 1;
}
}
/********************************************************************/
/*单字节读出一字节数据*/
unsigned char Read_Ds1302_Byte(void)
{
unsigned char i, dat=0;
for (i=0;i<8;i++)
{
dat = dat >> 1;
if (SDA_R) //等价于if(SDA_R==1) #define SDA_R SDA /*电平读取*/
{
dat |= 0x80;
}
else
{
dat &= 0x7F;
}
SCK_SET;
_nop_();
SCK_CLR;
_nop_();
}
return dat;
}
/********************************************************************/
/*向DS1302 单字节写入一字节数据*/
void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat)
{
RST_CLR;
_nop_();
SCK_CLR;
_nop_();
RST_SET;
_nop_();
addr = addr & 0xFE;
Write_Ds1302_Byte(addr); /*写入目标地址:addr,保证是写操作,写之前将最低位置零*/
Write_Ds1302_Byte(dat); /*写入数据:dat*/
RST_CLR; /*停止DS1302总线*/
_nop_();
}
unsigned char Ds1302_Single_Byte_Read(unsigned char addr)
{
unsigned char temp;
RST_CLR; /*RST脚置低,实现DS1302的初始化*/
_nop_();
SCK_CLR; /*SCK脚置低,实现DS1302的初始化*/
_nop_();
RST_SET; /*启动DS1302总线,RST=1电平置高 */
_nop_();
addr = addr | 0x01;
Write_Ds1302_Byte(addr); /*写入目标地址:addr,保证是读操作,写之前将最低位置高*/
temp=Read_Ds1302_Byte(); /*从DS1302中读出一个字节的数据*/
RST_CLR; /*停止DS1302总线*/
_nop_();
SD=0;
_nop_();
SD=1;
_nop_();
return temp;
}
void DS1302_init()
{
uchar i;
Ds1302_Single_Byte_Write(0x8e,0x00);
for(i=0;i<7;i++)
{
Ds1302_Single_Byte_Write(Write_add[i],TIME[i]);
}
Ds1302_Single_Byte_Write(0x8e,0x81);
}
void DS1302_read()
{
uchar i;
for(i=0;i<7;i++)
{
TIME[i]=Ds1302_Single_Byte_Read(Read_add[i]);
}
}
DS18B20温度传感器模块
#include "onewire.h"
void Delay500us();
void Delay15us();
void Delay60us();
void Delay100us();
void Delay_OneWire(unsigned int t)
{
while(t--);
}
void delayms(unsigned int ms)
{
int i,j;
for(i=0;i<=ms;i++)
for(j=850;j>0;j--);
}
//DS18B20芯片初始化
bit Init_DS18B20(void)
{
bit initflag = 0;
Delay_OneWire(12);
DQ = 0;
Delay500us();
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag;
}
//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
Delay15us();
DQ = dat&0x01;
Delay60us();
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
_nop_();
_nop_();
_nop_();
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay100us();
}
return dat;
}
void DS18b20()
{
Init_DS18B20();
delayms(1);
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Init_DS18B20();
delayms(1);
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
}
int temp_get()
{
unsigned char low,high;
unsigned char temp;
DS18b20();
low=Read_DS18B20();
high=Read_DS18B20();
temp=high<<4;
temp|=low>>4;
return temp;
}
void Delay500us() //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
i = 6;
j = 93;
do
{
while (--j);
} while (--i);
}
void Delay15us() //@11.0592MHz
{
unsigned char i;
i = 39;
while (--i);
}
void Delay60us() //@11.0592MHz
{
unsigned char i, j;
i = 1;
j = 162;
do
{
while (--j);
} while (--i);
}
void Delay100us() //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
i = 2;
j = 15;
do
{
while (--j);
} while (--i);
}
以上就是代码全部内容,欢迎交流,通过学习~