1、试题
(1)功能简述
模拟“温度采集与控制装置” 用于实现温度的实时监测与控制。单片机采集 DS18B20温度传感器的输出信号, 并送到数码管进行显示; 通过传感器得到的温度数据将与用户设定温度上限、下限值做比较, 再由单片机启动控制或报警电路。系统硬件部分主要由单片机最小系统、数码管显示、 DS18B20 温度传感器、矩阵键盘等模块组成。 系统组成框图如图1所示:
(2)设计任务及要求
1. 温度检测
温度检测采用 DS18B20 温度传感器, 数据经过单片机处理后,与用户设定的温度上限(TMAX)和温度下限(TMIN)比较,确定当前温度所处的区间, 数码管温度显示格式如图 2 所示:
关于温度区间的说明:
温度区间 0: 当前温度<TMIN
温度区间 1: TMIN≤当前温度≤TMAX
温度区间 2: 当前温度>TMAX
可设定的最大温度区间: 0℃~99℃
2. 用户输入-3X4 矩阵键盘
通过矩阵键盘设定系统的工作参数,各个按键的功能定义如图 3 所示:
“设置”按键按下后,进入工作参数设定界面,如图 4 所示, 依次按下设定的数值,再次按下“设置” 按键, 保存当前输入的数据,并退出工作参数设定界面。
以设定 TMAX 为 35 摄氏度, TMIN为 25 摄氏度为例说明参数设定过程:按下“设置”按键,然后依次按下数字按键“3” “5” “2” “5” 如图 5 所示,再次按下“设置” 按键, 完成参数设定, 并退出参数设定界面。在输入过程中,按下“清除” 按键, 将清除当前输入数据, 若设定工作参数错误,如 TMAX<TMIN, L2 常亮,修正错误设定并保存参数后, L2 熄灭。
3. 执行机构
执行机构由指示灯 L1 和继电器组成,用于报警和连接外部高低温执行机构。
3.1 实时温度处在温度区间 0, 继电器关闭,指示灯 L1 以 0.8 秒为间隔闪烁;
3.2 实时温度处在温度区间 1, 继电器关闭,指示灯 L1 以 0.4 秒为间隔闪烁;
3.3 实时温度处在温度区间 2, 继电器打开,指示灯 L1 以 0.2 秒为间隔闪烁。
4. 初始化状态说明
系统默认的温度上限(TMAX)为 30℃, 温度下限(TMIN)为 20℃, 可以通过矩阵键盘修改
(3)软、硬件统调
将编译通过的程序下载到单片机芯片中,进行软、硬件统调。
1. 系统初始化状态正确;
2. 数码管显示功能,界面设计满足题目要求;
3. 继电器控制功能实现,无误动作;
4. LED 闪烁控制功能实现;
5. 温度测量功能;
6. 矩阵键盘参数设定功能实现 。
2、试题分析
对于温度传感器来说:
unsigned char get_wendu(){
unsigned char temp,high,low;
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=(low>>4)|(high<<4);
return temp;
}
一些寄存器相关说明。可参考:
https://blog.csdn.net/fanjufei123456/article/details/104443872
对于矩阵按键来说:
//定义r为行,c为列,如果r1=0,c1=0,按键则为第一行第一列,其余同理;
sbit r1=P3^0;
sbit r2=P3^1;
sbit r3=P3^2;
sbit r4=P3^3;
sbit c1=P4^4;
sbit c2=P4^2;
sbit c3=P3^5;
sbit c4=P3^4;
注意按键端口表示方法,可参考:
https://blog.csdn.net/fanjufei123456/article/details/104263738
3、全部代码
text.c
#include<stc15f2k60s2.h>
#include "onewire.h"
#define uchar unsigned char
#define uint unsigned int
void delay();
void display12(uchar f1,uchar f2);
void display34(uchar f3,uchar f4);
void display56(uchar f5,uchar f6);
void display78(uchar f7,uchar f8);
void allinit();
void key_scan();
void Time0_init();
void delayms(uchar ms);
sbit r1=P3^0;
sbit r2=P3^1;
sbit r3=P3^2;
sbit r4=P3^3;
sbit c1=P4^4;
sbit c2=P4^2;
sbit c3=P3^5;
sbit c4=P3^4;
sbit led_light=P0^0;
uchar code tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};
uchar tmin=20;
uchar tmax=30;
uchar mode_1=0; //温度显示桌面
uchar wendu=0; //实时温度显示
uchar f1,f2,f3,f4,f5,f6,f7,f8;
uint count=0;
uchar clean=0;
uchar led1=0;
uchar flag=0;
uchar num=0;
void main(){
allinit();
Time0_init();
ET0=1;
EA=1;
while(1)
{
key_scan();
if(mode_1==0)
{
wendu=get_wendu();
if(wendu<tmin)
{
led1=0;
f1=10;f2=0;f3=10;f4=11;f5=11;f6=11;f7=wendu/10;f8=wendu%10;
}
else if((wendu>=tmin)&&(wendu<=tmax))
{
led1=1;
f1=10;f2=1;f3=10;f4=11;f5=11;f6=11;f7=wendu/10;f8=wendu%10;
}
else if(wendu>tmax)
{
led1=2;
f1=10;f2=2;f3=10;f4=11;f5=11;f6=11;f7=wendu/10;f8=wendu%10;
}
}
else if(mode_1==1)
{
if(clean==1)
{
clean=0;
f1=10;f2=11;f3=11;f4=11;f5=11;f6=10;f7=11;f8=11;
}
if((f2==11)&&(flag==1))
{
flag=0;
f2=num;
}
else if((f3==11)&&(flag==1))
{
flag=0;
f3=num;
}
else if((f7==11)&&(flag==1))
{
flag=0;
f7=num;
}
else if((f8==11)&&(flag==1))
{
flag=0;
f8=num;
if((f2*10+f3)<(f7*10+f8))
{
f1=10;f2=11;f3=11;f4=11;f5=11;f6=10;f7=11;f8=11;
P2=0X80;
P0=0XFD;
}
}
}
display12(f1,f2);
display34(f3,f4);
display56(f5,f6);
display78(f7,f8);
}
}
void key_scan(){
r1=1;r2=1;r3=1;r4=1;
c1=0;c2=1;c3=1;c4=1;
if(!r1)
{
delayms(5);
{
num=0;
flag=1;
}
while(!r1);
}
else if(!r2)
{
delayms(5);
{
num=3;
flag=1;
}
while(!r2);
}
else if(!r3)
{
delayms(5);
{
num=6;
flag=1;
}
while(!r3);
}
else if(!r4)
{
delayms(5);
{
num=9;
flag=1;
}
while(!r4);
}
r1=1;r2=1;r3=1;r4=1;
c1=1;c2=0;c3=1;c4=1;
if(!r1)
{
delayms(5);
{
num=1;
flag=1;
}
while(!r1);
}
else if(!r2)
{
delayms(5);
{
num=4;
flag=1;
}
while(!r2);
}
else if(!r3)
{
delayms(5);
{
num=7;
flag=1;
}
while(!r3);
}
else if(!r4)
{
delayms(5);
{
if(mode_1==0)
{
mode_1=1;
EA=0;
ET0=0;
P2=0X80;P0=0XFF;
P2=0XC0;P0=0XFF;P2=0XFF;P0=0XFF;
f1=10;f2=11;f3=11;f4=11;f5=11;f6=10;f7=11;f8=11;
}
else if(mode_1==1)
{
mode_1=0;
EA=1;ET0=1;
P2=0X80;P0=0XFF;
tmin=f7*10+f8;
tmax=f2*10+f3;
}
}
while(!r4);
}
r1=1;r2=1;r3=1;r4=1;
c1=1;c2=1;c3=0;c4=1;
if(!r1)
{
delayms(5);
{
num=2;
flag=1;
}
while(!r1);
}
else if(!r2)
{
delayms(5);
{
num=5;
flag=1;
}
while(!r2);
}
else if(!r3)
{
delayms(5);
{
num=8;
flag=1;
}
while(!r3);
}
else if(!r4)
{
delayms(5);
{
clean=1;
}
while(!r4);
}
}
void delay(){
uchar i,j;
for(i=10;i>0;i--)
for(j=200;j>0;j--);
}
void allinit(){
P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
P2=0XC0;P0=0XFF;P2=0XFF;P0=0XFF;
}
void display12(uchar f1,uchar f2){
P2=0XC0;P0=0X01;P2=0XFF;P0=tab[f1];
delay();
P2=0XC0;P0=0X02;P2=0XFF;P0=tab[f2];
delay();
}
void display34(uchar f3,uchar f4){
P2=0XC0;P0=0X04;P2=0XFF;P0=tab[f3];
delay();
P2=0XC0;P0=0X08;P2=0XFF;P0=tab[f4];
delay();
}
void display56(uchar f5,uchar f6){
P2=0XC0;P0=0X10;P2=0XFF;P0=tab[f5];
delay();
P2=0XC0;P0=0X20;P2=0XFF;P0=tab[f6];
delay();
}
void display78(uchar f7,uchar f8){
P2=0XC0;P0=0X40;P2=0XFF;P0=tab[f7];
delay();
P2=0XC0;P0=0X80;P2=0XFF;P0=tab[f8];
delay();
}
void Time0_init(){
TMOD=0x01;
TH0=(65536-10000)/256; //10000us=10ms=0.01s
TL0=(65536-10000)%256;
TR0=1;
}
void Time0_service() interrupt 1
{
TH0=(65536-10000)/256; //10000us=10ms=0.01s
TL0=(65536-10000)%256;
count++;
if(led1==0)
{
{
P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
}
if(count==80)
{
count=0;
led_light=~led_light;
}
}
if(led1==1)
{
{
P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
}
if(count==40)
{
count=0;
led_light=~led_light;
}
}
if(led1==2)
{
{
P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
}
if(count==20)
{
count=0;
led_light=~led_light;
}
}
}
void delayms(uchar ms){
uchar i,j,k;
for(k=ms;k>0;k--)
{
i=12;
j=169;
do
{
while(j--);
}
while(i--);
}
}
onewire.c
#include "onewire.h"
//单总线延时函数
void Delay_OneWire(unsigned int t)
{
t=t*12;
while(t--);
}
//DS18B20芯片初始化
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;
}
//通过单总线向DS18B20写一个字节
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);
}
//从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(5);
}
return dat;
}
unsigned char get_wendu(){
unsigned char temp,high,low;
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=(low>>4)|(high<<4);
return temp;
}
onewire.h
#ifndef _ONEWIRE_H
#define _ONEWIRE_H
#include "stc15f2k60s2.h"
#define OW_SKIP_ROM 0xcc
#define DS18B20_CONVERT 0x44
#define DS18B20_READ 0xbe
//IC引脚定义
sbit DQ = P1^4;
//函数声明
void Delay_OneWire(unsigned int t);
void Write_DS18B20(unsigned char dat);
bit Init_DS18B20(void);
unsigned char Read_DS18B20(void);
unsigned char get_wendu();
#endif