整体来说这届省赛是历史最难,考试的时候没有把所有功能全部实现,但是还是拿了省一
考完试把代码回顾了一遍,现在完整代码,全部功能已实现,
测频率 T0计数 T1定时
矩阵按键采用2×4,中断扫描法写的,强烈推荐终端扫描的方法,一点都不抖,而且可以决定是按下按键执行我们需要的功能还是松手按键执行功能,还可以实现长短按功能
//完美代码
//测频率 T0计数 T1定时
//学会用中间变量和测量最大值和平均值
#include "stc15f2k60s2.h"
#include "intrins.h"
#include "ds1302.h"
#include "iic.h"
#include "onewire.h"
/*11- 12C 13H 14F 15P 16E 17A*/
unsigned char code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf,0xc6,0x89,0x8e,0x8c,0x86, 0x88};
unsigned char dscom=0;
unsigned char dsbuff[8]={0};
extern unsigned char clk[3];
unsigned char keysta[2][4]={{1,1,1,1},{1,1,1,1}};
unsigned char keyback[2][4]={{1,1,1,1},{1,1,1,1}};
unsigned char keybuff[2][4]={{0xff,0xff,0xff,0xff},{0xff,0xff,0xff,0xff}};
unsigned char code keycode[2][4]={{5,9,13,17},{4,8,12,16}};
unsigned char number=0;
unsigned char ds_count=0;
unsigned char ad_count=0;
unsigned int wendu_count=0;
unsigned char fre_count=0;
unsigned int ym_count=0;
unsigned int frequence;
unsigned char ym_mode=1;// 页面标志位 1时间界面 2回显界面 3参数界面
unsigned char hx_mode=1;// 回显标志位 1温度回显 2湿度回显 3时间回显
unsigned char ad_value; //光照
unsigned char ad_value_last;//上个光照
unsigned int tempurture; //温度
unsigned int tempurture_caiji;//采集的温度
unsigned int tempurture_last;
unsigned int tempurture_max;
unsigned int tempurture_ave=250;
unsigned int shidu=0; //湿度
unsigned int shidu_caiji; //采集的湿度
unsigned int shidu_last;
unsigned int shidu_max=100;
unsigned int shidu_ave=200;
unsigned char ym; //进入手势页面 把当前页面值存给ym
unsigned int key_count=0;
unsigned int tempurture_sum=0;
unsigned char i=0;
unsigned int shidu_sum=0;
unsigned char led_number=0xff;
char canshu=27;
bit ds_read_flag=0; //
bit ad_flag=0; //
bit wendu_flag=0; //
bit wuxiao_flag=0;
bit key_bit=0;
bit longthing=0;
bit l1_flag=0;
bit l2_flag=0;
bit l3_flag=0;
bit l4_flag=0;
bit l5_flag=0;
bit l6_flag=0;
sbit h0=P3^0;
sbit h1=P3^1;
sbit h2=P3^2;
sbit h3=P3^3;
sbit l0=P4^4;
sbit l1=P4^2;
sbit l2=P3^5;
sbit l3=P3^4;
void keysong(unsigned char keydat);
void keyaction(unsigned char dat);
void yemian();
void led_handle();
void LED_function();
void select573(unsigned char channel)
{
P2&=0x1f;
P0=0xff;
switch(channel)
{
case 4:P2=(P2&0x1f)|0x80;break;
case 5:P2=(P2&0x1f)|0xa0;break;
case 6:P2=(P2&0x1f)|0xc0;break;
case 7:P2=(P2&0x1f)|0xe0;break;
}
}
void allinit()
{
select573(4);P0=0xff;
select573(5);P0=0x00;
select573(6);P0=0xff;
select573(7);P0=0xff;
}
void display()
{
select573(7);P0=0xff;
select573(6);
P0=1<<dscom;
select573(7);
P0=tab[dsbuff[dscom]];
if(++dscom==8)
dscom=0;
}
void timerinit()
{
TH1=(65535-1000)/256;
TL1=(65535-1000)%256;
TMOD=0x05;
TF1=0;
TR1=1;
ET1=1;
EA=1;
TH0=0;
TL0=0;
TF0=0;
ET0=0;
TR0=1;
}
//===================按键函数=====================================================================================================================
//============按键扫描=====================
void keyscan()
{
unsigned char i;
static unsigned char j=0;
keybuff[j][0]=keybuff[j][0]<<1|l0;
keybuff[j][1]=keybuff[j][1]<<1|l1;
keybuff[j][2]=keybuff[j][2]<<1|l2;
keybuff[j][3]=keybuff[j][3]<<1|l3;
for(i=0;i<2;i++)
{
if((keybuff[i][j]&0x0f)==0)
{
keysta[i][j]=0;
}
else if((keybuff[i][j]&0x0f)==0x0f)
{
keysta[i][j]=1;
}
}
j++;
if(j>=2)
{
j=0;
}
switch(j)
{
case 0:h2=0;h3=1;break;
case 1:h3=0;h2=1;break;
}
}
//============按键处理==========================
void keyhandle()
{
unsigned char i,j;
for(i=0;i<2;i++)
{
for(j=0;j<4;j++)
{
if(keyback[i][j]!=keysta[i][j])
{
if(keysta[i][j]==0)
{
keyaction(keycode[i][j]);
}
else if(keysta[i][j]==1)
{
keysong(keycode[i][j]);
}
keyback[i][j]=keysta[i][j];
}
}
}
}
//============按键按下====================
void keyaction(unsigned char dat)
{
if(dat==4) //界面按键
{
if(ym_mode==1)//从时间页面切换到回显界面 处于回显界面
{
ym_mode=2; //2回显界面
hx_mode=1; //1温度回显
}
else if(ym_mode==2) ym_mode=3; //3参数界面
else if(ym_mode==3) ym_mode=1; //1时间界面
}
if(dat==5) //回显按键
{
if(ym_mode==2)//如果在2回显界面
{
if(hx_mode==1) hx_mode=2;//2湿度回显
else if(hx_mode==2) hx_mode=3;//3时间回显
else if(hx_mode==3) hx_mode=1;//1温度回显
}
}
if(dat==8) //在参数界面下 加参数
{
if(ym_mode==3) //如果在参数界面下
{
canshu+=1;
if(canshu>=99)
canshu=99;
}
}
if(dat==9) //在参数界面下 减参数
{
if(ym_mode==3) //如果在参数界面下
{
canshu-=1;
if(canshu<=0)
canshu=0;
}
key_bit=1;
}
}
//============按键松开=============
void keysong(unsigned char keydat)
{
if(ym_mode==3&&keydat==9) //=清除所有记录,触发次数重置为0
{
if(longthing==1) //=执行的操作
{
longthing=0;
number=0;
tempurture_max=200;
shidu_max=100;
}
key_bit=0;
key_count=0;
}
}
//=====================main函数===============================================================================================
void main(void)
{
allinit();
timerinit();
ds1302init();
while(1)
{
keyhandle();
if(ds_read_flag==1) //读取时间
{
ds_read_flag=0;
ds1302read();
}
ad_value_last=ad_value;
if(ad_flag==1) //读取光照
{
ad_flag=0;
ad_value=pcf_ad(1);
}
if(wendu_flag==1) //读取温度
{
wendu_flag=0;
tempurture=read_temperature();
}
//=====光照触发采集======================================================================
//防止巧合,刚从第四个页面出来main函数刚好执行到这里再次进入,ym_mode的值还没来得及改变,
//又被赋值,一直会是4,就不会跳出所以这里加一个条件 (ym_mode!=4)
if(((ad_value_last-ad_value)>50)&&(ym_mode!=4))
{
ym=ym_mode;
ym_mode=4;
//=====频率转换为湿度=数据无效这组数据放弃
if(frequence<=200)
{
wuxiao_flag=1; //无效标志位置一
shidu=100; //保留一位小数 *10
}
else if(frequence>=2000)
{
wuxiao_flag=1;
shidu=900; //保留一位小数 *10
}
else
{
wuxiao_flag=0;
}
if(wuxiao_flag==0) // 数据有效的时候才进行数据采集
{
number++;
i++;
//=====温度最大值平均值=================================== tempurture_last shidu_last
tempurture_last=tempurture_caiji;
if(tempurture>tempurture_max)
{
tempurture_max=tempurture;
}
else
{
tempurture_max=tempurture_max;
}
tempurture_caiji=tempurture;
tempurture_sum+=tempurture;
tempurture_ave=tempurture_sum/i;
//=====频率转换为湿度===============
if(frequence<2000&&frequence>200)
{
shidu=(0.044445*frequence+1.11111)*10;//保留一位小数 *10
}
//=====求出最大湿度=========================
shidu_last=shidu_caiji;
if(shidu>shidu_max)
{
shidu_max=shidu;
}
else
shidu_max=shidu_max;
shidu_caiji=shidu;
//=====平均湿度==========================
shidu_sum+=shidu;
shidu_ave=shidu_sum/i;
}
}
LED_function();
//========
}
}
//=====================中断函数===============================================================================================
unsigned char l4_count=0;
void timer1()interrupt 3
{
led_handle();
display();
yemian();
keyscan();
//======读取时间=========
ds_count++;
if(ds_count>=50)
{
ds_read_flag=1;
ds_count=0;
}
//======读取光照ad=======
ad_count++;
if(ad_count>=200)
{
ad_count=0;
ad_flag=1;
}
//======读取温度=========
wendu_count++;
if(wendu_count>=500)
{
wendu_count=0;
wendu_flag=1;
}
//======读取频率=========
fre_count++;
if(fre_count==200)
{
TR0=0;
fre_count=0;
frequence=(TH0*256+TL0)*5;
TH0=0;
TL0=0;
TR0=1;
}
//====3秒切换页面========
if(ym_mode==4)
{
ym_count++;
if(ym_count>=3000)
{
ym_count=0;
ym_mode=ym;
}
}
//======按键长按=========
if(key_bit==1)
{
key_count++;
if(key_count>=2000)
{
key_count=0;
longthing=1;
}
}
//=====LED功能部分======================================
//=====L1===========
if(l1_flag==1)
{
led_number&=0xfe;
}
else
{
led_number|=0x01;
}
//=====L2===========
if(l2_flag==1)
{
led_number&=0xfd;
}
else
{
led_number|=0x02;
}
//=====L3===========
if(l3_flag==1)
{
led_number&=0xfb;
}
else
{
led_number|=0x04;
}
//=====L4===========
if(l4_flag==1)
{
l4_count++;
if(l4_count<=100)
{
led_number&=0xf7;
}
else if((l4_count>100)&&(l4_count<=200))
{
led_number|=0x08;
}
else if(l4_count>200)
{
l4_count=0;
}
}
else
{
led_number|=0x08;
}
//=====L5===========
if(l5_flag==1)
{
led_number&=0xef;
}
else
{
led_number|=0x10;
}
//=====L6===========
if(l6_flag==1)
{
led_number&=0xdf;
}
else
{
led_number|=0x20;
}
}
//=====LED功能部分================================================================================
void LED_function()
{
//========界面指示灯=================
//=====L1=========
if(ym_mode==1) //时间界面
l1_flag=1;
else
l1_flag=0;
//=====L2=========
if(ym_mode==2) //回显界面
l2_flag=1;
else
l2_flag=0;
//=====L3=========
if(ym_mode==4) //湿度界面
l3_flag=1;
else
l3_flag=0;
//========报警指示灯=================
//=====L4=========
if(tempurture_caiji>(canshu*10)) //采集温度大于温度参数
{
l4_flag=1; //L4以0.1s间隔闪烁
}
else
l4_flag=0;
//=====L5=========
if(wuxiao_flag==1) //采集到无效数据L5亮,直到有效数据出现L5灭
{
l5_flag=1;
}
else
l5_flag=0;
//=====L6=========
if((tempurture_caiji>tempurture_last)&&(shidu_caiji>shidu_last)&&(number>=2)) //采集温度和湿度均比上次高L6亮,否则灭
{
l6_flag=1;
}
else
l6_flag=0;
}
//==============LED中断函数=============
void led_handle()
{
P0=0xff;
select573(4);
P0=led_number;
}
//=====================页面函数===============================================================================================
void yemian()
{
if(ym_mode==1) //1时间界面
{
dsbuff[0]=clk[2]/16;
dsbuff[1]=clk[2]%16;
dsbuff[2]=11;
dsbuff[3]=clk[1]/16;
dsbuff[4]=clk[1]%16;
dsbuff[5]=11;
dsbuff[6]=clk[0]/16;
dsbuff[7]=clk[0]%16;
}
else if(ym_mode==2) //2回显界面
{
if(number==0)
{
if(hx_mode==1) //1温度回显
{
dsbuff[0]=12;
dsbuff[1]=10;
dsbuff[2]=10;
dsbuff[3]=10;
dsbuff[4]=10;
dsbuff[5]=10;
dsbuff[6]=10;
dsbuff[7]=10;
}
else if(hx_mode==2) //2湿度回显
{
dsbuff[0]=13;
dsbuff[1]=10;
dsbuff[2]=10;
dsbuff[3]=10;
dsbuff[4]=10;
dsbuff[5]=10;
dsbuff[6]=10;
dsbuff[7]=10;
}
else if(hx_mode==3) //3时间回显
{
dsbuff[0]=14;
dsbuff[1]=10;
dsbuff[2]=10;
dsbuff[3]=10;
dsbuff[4]=10;
dsbuff[5]=10;
dsbuff[6]=10;
dsbuff[7]=10;
}
}
else
{
if(hx_mode==1) //1温度回显
{
dsbuff[0]=12;
dsbuff[1]=10;
dsbuff[2]=tempurture_max/100;
dsbuff[3]=tempurture_max/10%10;
dsbuff[4]=11;
dsbuff[5]=tempurture_ave/100;
dsbuff[6]=tempurture_ave/10%10;
dsbuff[7]=tempurture_ave%10;
}
else if(hx_mode==2) //2湿度回显
{
dsbuff[0]=13;
dsbuff[1]=10;
dsbuff[2]=shidu_max/100;
dsbuff[3]=shidu_max/10%10;
dsbuff[4]=11;
dsbuff[5]=shidu_ave/100;
dsbuff[6]=shidu_ave/10%10;
dsbuff[7]=shidu_ave%10;
}
else if(hx_mode==3) //3时间回显
{
dsbuff[0]=14;
dsbuff[1]=number/10;
dsbuff[2]=number%10;
dsbuff[3]=clk[2]/16;
dsbuff[4]=clk[2]%16;
dsbuff[5]=11;
dsbuff[6]=clk[1]/16;
dsbuff[7]=clk[1]%16;
}
}
}
else if(ym_mode==3) //3参数界面
{
dsbuff[0]=15;
dsbuff[1]=frequence/10000;
dsbuff[2]=frequence%10000/1000;
dsbuff[3]=frequence%1000/100;
dsbuff[4]=frequence%100/10;
dsbuff[5]=frequence%10;
dsbuff[6]=canshu/10;
dsbuff[7]=canshu%10;
}
//=============4采集触发界面===========================
if(ym_mode==4)
{
if(wuxiao_flag==1)
{
dsbuff[0]=16;
dsbuff[1]=10;
dsbuff[2]=10;
dsbuff[3]=tempurture/100;
dsbuff[4]=tempurture/10%10;
dsbuff[5]=11;
dsbuff[6]=17;
dsbuff[7]=17;
}
else
{
dsbuff[0]=16;
dsbuff[1]=10;
dsbuff[2]=10;
dsbuff[3]=tempurture/100;
dsbuff[4]=tempurture/10%10;
dsbuff[5]=11;
dsbuff[6]=shidu/100;
dsbuff[7]=shidu/10%10;
}
}
}
IIC.c 函数
#include "iic.h"
#include "intrins.h"
#define DELAY_TIME 5
sbit scl=P2^0;
sbit sda=P2^1;
//
static void I2C_Delay(unsigned char n)
{
do
{
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
}
while(n--);
}
//
void I2CStart(void)
{
sda = 1;
scl = 1;
I2C_Delay(DELAY_TIME);
sda = 0;
I2C_Delay(DELAY_TIME);
scl = 0;
}
//
void I2CStop(void)
{
sda = 0;
scl = 1;
I2C_Delay(DELAY_TIME);
sda = 1;
I2C_Delay(DELAY_TIME);
}
//
void I2CSendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++){
scl = 0;
I2C_Delay(DELAY_TIME);
if(byt & 0x80){
sda = 1;
}
else{
sda = 0;
}
I2C_Delay(DELAY_TIME);
scl = 1;
byt <<= 1;
I2C_Delay(DELAY_TIME);
}
scl = 0;
}
//
unsigned char I2CReceiveByte(void)
{
unsigned char da;
unsigned char i;
for(i=0;i<8;i++){
scl = 1;
I2C_Delay(DELAY_TIME);
da <<= 1;
if(sda)
da |= 0x01;
scl = 0;
I2C_Delay(DELAY_TIME);
}
return da;
}
//
unsigned char I2CWaitAck(void)
{
unsigned char ackbit;
scl = 1;
I2C_Delay(DELAY_TIME);
ackbit = sda;
scl = 0;
I2C_Delay(DELAY_TIME);
return ackbit;
}
//
void I2CSendAck(unsigned char ackbit)
{
scl = 0;
sda = ackbit;
I2C_Delay(DELAY_TIME);
scl = 1;
I2C_Delay(DELAY_TIME);
scl = 0;
sda = 1;
I2C_Delay(DELAY_TIME);
}
unsigned char pcf_ad(unsigned char channel)
{
unsigned char temp;
EA=0;
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(channel);
I2CWaitAck();
I2CStart();
I2CSendByte(0x91);
I2CWaitAck();
temp=I2CReceiveByte();
I2CSendAck(1);
I2CStop();
EA=1;
return temp;
}
onewire.c函数
#include "onewire.h"
#include "intrins.h"
sbit DQ=P1^4;
//
void Delay_OneWire(unsigned int t)
{
unsigned char i;
while(t--){
for(i=0;i<12;i++);
}
}
//
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;
}
float read_temperature()
{
unsigned int temp;
unsigned char low,high;
EA=0;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
low=Read_DS18B20();
high=Read_DS18B20();
EA=1;
temp=high;
temp=temp<<8;
temp=temp|low;
temp*=0.625;
return temp;
}
ds1302.c函数
#include "ds1302.h"
#include "intrins.h"
sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST=P1^3;
unsigned char clk[3];
//
void Write_Ds1302(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK = 0;
SDA = temp&0x01;
temp>>=1;
SCK=1;
}
}
//
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )
{
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
Write_Ds1302(dat);
RST=0;
}
//
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
unsigned char i,temp=0x00;
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
for (i=0;i<8;i++)
{
SCK=0;
temp>>=1;
if(SDA)
temp|=0x80;
SCK=1;
}
RST=0; _nop_();
SCK=0; _nop_();
SCK=1; _nop_();
SDA=0; _nop_();
SDA=1; _nop_();
return (temp);
}
void ds1302init()
{
Write_Ds1302_Byte(0x8e,0x00);
Write_Ds1302_Byte(0x80,0x05);
Write_Ds1302_Byte(0x82,0x03);
Write_Ds1302_Byte(0x84,0x13);
Write_Ds1302_Byte(0x8e,0x80);
}
void ds1302read()
{
clk[0]=Read_Ds1302_Byte(0x81);
clk[1]=Read_Ds1302_Byte(0x83);
clk[2]=Read_Ds1302_Byte(0x85);
}