也是刚刚把这个题目做完,让我们一起来看看2021年的题目吧,有什么不对的地方,还希望大家指正。
题目
?
?
?
?
?
首先依旧还是三大模块(数码管、LED、按键) ,还有DS18B20,DA输出。写了有一些省赛题了,每次考的都是这些东西,只要平常每个模块都有练习过,应该是不难的。我发现从2020年开始,虽然还是用四个按键,但是变成了矩阵按键,之前都是独立按键。
1 数码管显示
数码管有温度显示,参数设置和DA输出三个界面,通过s4来切换。
2 LED
当在模式1状态时L1亮,数码管处于温度显示界面时L2亮,参数设置界面时L3亮,DA输出界面时L4亮。
3 按键模块
使用的是矩阵键盘,s4是三个界面的切换,s8,s9是温度参数加减1,这里有个小坑就是设定的温度参数只有在退出参数设置界面时才生效,这就要定义两个温度参数的变量,一个是用来在温度参数加减的,在退出温度参数界面时赋值给另一个变量,另一个是用来和实时温度比较大小的。s5有两个模式,模式一 实时温度小于温度参数DA输出0v,否则输出5v。模式二 按照图所给的关系输出电压。
4 DS18B20
就是改写底层驱动代码部分(onewire),然后放在定时器中,每隔一段时间读取一次。
5 DAC
就是改写底层驱动代码部分(IIC)。
onewire.c
#include"onewire.h"
sbit DQ = P1^4;
void Delay_OneWire(unsigned int t)
{
t*=12;
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;
}
unsigned int Get_temp()
{
unsigned int result;
unsigned char high,low;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
low=Read_DS18B20();
high=Read_DS18B20();
result=(high<<8)|low;
result*=6.25;
return result;
}
onewire.h
#ifndef _ONEWIRE_H_
#define _ONEWIRE_H_
#include<stc15f2k60s2.h>
void Delay_OneWire(unsigned int t);
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
bit init_ds18b20(void);
unsigned int Get_temp();
#endif
IIC.c
#include"IIC.h"
#define DELAY_TIME 5
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1
sbit SDA = P2^1;
sbit SCL = P2^0;
void IIC_Delay(unsigned char i)
{
do{_nop_();}
while(i--);
}
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 0;
}
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 1;
IIC_Delay(DELAY_TIME);
}
bit IIC_WaitAck(void)
{
bit ackbit;
SCL = 1;
IIC_Delay(DELAY_TIME);
ackbit = SDA;
SCL = 0;
IIC_Delay(DELAY_TIME);
return ackbit;
}
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++)
{
SCL = 0;
IIC_Delay(DELAY_TIME);
if(byt & 0x80) SDA = 1;
else SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 1;
byt <<= 1;
IIC_Delay(DELAY_TIME);
}
SCL = 0;
}
void DA_out(unsigned char date)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x40);
IIC_WaitAck();
IIC_SendByte(date);
IIC_WaitAck();
IIC_Stop();
}
IIC.h
#ifndef _IIC_H_
#define _IIC_H_
#include<stc15f2k60s2.h>
#include<intrins.h>
void IIC_Delay(unsigned char i);
void IIC_Start(void);
void IIC_Stop(void);
bit IIC_WaitAck(void);
void IIC_SendByte(unsigned char byt);
void DA_out(unsigned char date);
#endif
init.c
#include"init.h"
#define u8 unsigned char
#define u16 unsigned int
#define state_0 0
#define state_1 1
#define state_2 2
u8 code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff,0xc6,0x8c,0x88};
u8 seg[]={11,11,11,11,11,11,11,11};
static u8 segaddr=0;
u8 value=0;
extern u8 mode;
void all_init() //关闭无关外设
{
P2=(P2&0x1f)|0x80;P0=0xff;P2&=0x1f;
P2=(P2&0x1f)|0xa0;P04=0;P06=0;P2&=0x1f;
P2=(P2&0x1f)|0xc0;P0=0x00;P2&=0x1f;
P2=(P2&0x1f)|0xe0;P0=0xff;P2&=0x1f;
}
void display() //数码管显示函数
{
P2=(P2&0x1f)|0xe0;P0=0xff;P2&=0x1f;
P2=(P2&0x1f)|0xc0;P0=1<<segaddr;P2&=0x1f;
if(mode!=2&&segaddr==5)
{
P2=(P2&0x1f)|0xe0;P0=tab[seg[segaddr]]&0x7f;P2&=0x1f;
}
else
{
P2=(P2&0x1f)|0xe0;P0=tab[seg[segaddr]];P2&=0x1f;
}
if(++segaddr==8)segaddr=0;
}
u8 Read_key() //矩阵键盘
{
static u8 key_press,key_num=0,key_state=0;
key_press=P3&0x0f;
switch(key_state)
{
case state_0:
if(key_press!=0x0f)
key_state=state_1;
break;
case state_1:
if(key_press!=0x0f)
{
if((key_press & 0x08)==0) key_num=4;
if((key_press & 0x04)==0) key_num=5;
if((key_press & 0x02)==0) key_num=6;
if((key_press & 0x01)==0) key_num=7;
key_state=state_2;
}
else
key_state=state_0;
break;
case state_2:
if(key_press==0x0f)
key_state=state_0;
break;
}
value=key_num;
key_num=0;
return value;
}
void Timer0Init(void)
{
AUXR |= 0x80;
TMOD &= 0xF0;
TL0 = 0xCD;
TH0 = 0xD4;
TF0 = 0;
TR0 = 1;
ET0 = 1;
EA = 1;
}
init.h
#ifndef _INIT_H_
#define _INIT_H_
#include<stc15f2k60s2.h>
void all_init();
void display();
unsigned char Read_key();
void Timer0Init(void);
#endif
jm.c
#include"jm.h"
#include"IIC.h"
#define u8 unsigned char
#define u16 unsigned int
u16 TT=2500,TF=2500;
extern u8 mode,seg[]; // extern表示此变量是在别处定义的,要在此处引用
extern u16 temp,RB2;
extern bit MS;
void jm4()
{
if(mode==1) //温度显示界面
{
seg[0]=12;
seg[1]=11;
seg[2]=11;
seg[3]=11;
seg[4]=temp/1000;
seg[5]=temp/100%10;
seg[6]=temp/10%10;
seg[7]=temp%10;
}
else if(mode==2) //参数设置界面
{
seg[0]=13;
seg[1]=11;
seg[2]=11;
seg[3]=11;
seg[4]=11;
seg[5]=11;
seg[6]=TF/1000;
seg[7]=TF/100%10;
}
else if(mode==3) //DA输出界面
{
seg[0]=14;
seg[1]=11;
seg[2]=11;
seg[3]=11;
seg[4]=11;
seg[5]=RB2/100;
seg[6]=RB2/10%10;
seg[7]=RB2%10;
}
}
void jm5() //模式切换函数
{
if(MS==0)
{
if(temp<TT)
{
DA_out(0);
RB2=0;
}
else
{
DA_out(255);
RB2=500;
}
}
else
{
if(temp<=2000)
{
DA_out(196);
RB2=100;
}
else if(temp>2000&&temp<=4000)
{
DA_out((0.15*temp-200)*51.0);
RB2=(u16)(0.15*temp-200+0.5);
}
else
{
DA_out(204);
RB2=400;
}
}
}
void jm8()
{
if(mode==2)TF-=100;
}
void jm9()
{
if(mode==2)TF+=100;
}
void LED() //LED显示函数
{
u8 i=0xff;
if(MS==0)
{
P2=(P2&0x1f)|0x80;P0=i&0xfe;P2&=0x1f;
}
else
{
P2=(P2&0x1f)|0x80;P0=i|0x01;P2&=0x1f;
}
if(mode==1)
{
P2=(P2&0x1f)|0x80;P0=i&0xfd;P2&=0x1f;
}
else if(mode==2)
{
P2=(P2&0x1f)|0x80;P0=i&0xfb;P2&=0x1f;
}
else if(mode==3)
{
P2=(P2&0x1f)|0x80;P0=i&0xf7;P2&=0x1f;
}
}
jm.h
#ifndef _JM_H_
#define _JM_H_
#include<stc15f2k60s2.h>
void jm4();
void jm5();
void jm8();
void jm9();
void LED();
#endif
main.c
#include"init.h"
#include"jm.h"
#include"onewire.h"
#include"IIC.h"
#define u8 unsigned char
#define u16 unsigned int
u8 num=0,temp_count=0;
u8 mode=1;
u16 temp,RB2=325;
bit MS=0,temp_flag=0;
extern TT,TF;
void main()
{
all_init();
Timer0Init();
while(1)
{
if(temp_flag==1) //每200ms读取一次温度的值
{
temp_flag=0;
temp=Get_temp();
}
num=Read_key();
switch(num)
{
case 4:
if(++mode==4)mode=1;
break;
case 5:
MS^=1;
break;
case 6:
jm8();
TT=TF;
break;
case 7:
jm9();
TT=TF;
break;
}
jm4();
jm5();
LED();
}
}
void Timer0() interrupt 1
{
display();
if(++temp_count==200)
{
temp_count=0;
temp_flag=1;
}
}
最后再说一次,每个模块都是比较简单的,最重要的编程逻辑。
|