此题目难度适中,与前几年相比题量较大,细心去做还是很简单,祝大家都取得好成绩。
下面是程序部分:
主程序代码:
#include <main.h>
#include <ds1302.h>
#include <onewire.h>
#include <iic.h>
void Task_Clock(void)
{
if(++LED_tt == 100){ LED_tt = 0; LED_Ref = 1; }
if(++SEG_tt == 50) { SEG_tt = 0; SEG_Ref = 1; }
if(++KEY_tt == 10) { KEY_tt = 0; KEY_Ref=1;}
if(++Temp_tt == 550) { Temp_tt = 0; Temp_Ref = 1; }
if(++AD_tt == 300) { AD_tt = 0; AD_Ref = 1; }
if(++DS_tt == 1000) { DS_tt = 0; DS_Ref = 1; }
if(++PWM_IN_tt == 500) {PWM_IN_tt = 0; PWM_IN_Ref = 1; }
if(SEG_Show==9){WS_Show_TT++;}
if(WS_Show_TT==3000){WS_Show_TT=0;SEG_Show=SEG_Show_Flag;}
}
void main(void)
{
ALL_Init();
Timer0Init();
EA=1;ET0=1;
Temp_DotValue = Temp_get() ;Delay_MS(5);
#if (PWM != 0)
Timer2Init(); IE2 |= 0X04; //初始化定时器2,且开启定时器2中断
#endif
DS_init();
DS_get();
while(1)
{
if(SEG_Ref == 1)
{
SEG_Ref = 0;
SEG_Refresh();
}
if(KEY_Ref==1)
{
KEY_Ref=0;
ArrKeyScan();
if(KEY_Flag == 1)
{
KEY_Flag = 0;
Task_Key();
}
}
if(Temp_Ref == 1)
{
Temp_Ref = 0;
Temp_DotValue = Temp_get() ;
}
if(PWM_IN_Ref == 1)
{
PWM_IN_Ref = 0 ;
PWM_IN_Freq = 100000 / (PWM_INH_Save + PWM_INL_Save);
}
if(DS_Ref == 1)
{
DS_Ref = 0;
DS_get();
}
if(AD_Ref == 1)
{
AD_Ref = 0;
AD_Value = AD_read(0X01); //滑动变阻器0X03,光敏电阻0X01
// AD_write(AD_Value);
if(AD_Value<=125)//暗状态
{
Dimmed_state=0;
}
else //亮状态
{
Dimmed_state=1;
}
if(SEG_Show!=9)
{
if((Dimmed_state==0)&&(Dimmed_state_befor==1))
{
if(SEG_Show_2!=2)
{
trigger_number++;
gather_time_hour=Get_Time[2];
gather_time_minute=Get_Time[1];
}
gather_Ref=1;
SEG_Show_Flag=SEG_Show;
SEG_Show=9;
}
}
Dimmed_state_befor=Dimmed_state;
}
if(gather_Ref==1)
{
gather_Ref=0;
Temp_Vaue=Temp_DotValue/10000;
if(Temp_Vaue>=99)Temp_Vaue=99;
if(Temp_Vaue<=0)Temp_Vaue=0;
if((PWM_IN_Freq>=200)&&(PWM_IN_Freq<=2000))
{
PWM_IN_Flag=0;
Humidity=(PWM_IN_Freq*2+50)/45;
}
else {PWM_IN_Flag=1; Humidity_invalid++;}
if(SEG_Show_2==0)
{
if(Temp_Max<Temp_Vaue)Temp_Max=Temp_Vaue;
Temp_Average=(Temp_Average*(trigger_number-1)*10+Temp_Vaue*100)/10/trigger_number;
if(PWM_IN_Flag!=1)
{
if(Humidity_Max<Humidity)Humidity_Max=Humidity;
Humidity_Average=(Humidity_Average*(trigger_number-Humidity_invalid-1)*10+Humidity*100)/10/(trigger_number-Humidity_invalid);
}
}
}
if(LED_Ref==1)
{
LED_Ref=0;
LED_Reference();
}
}
}
void Task_Key(void)
{
if((KEY_Value==9)&&(KEY_Press_TIME<2000)){
KEY_Value=0;KEY_Press_TIME=0;
if(SEG_Show==3)
{
if(Temper_Para==0)Temper_Para=0;
else Temper_Para-=1;
}
}
else if((KEY_Value==9)&&(KEY_Press_TIME>=2000)){
KEY_Value=0; KEY_Press_TIME=0;
if((SEG_Show==2)&&(Back_Show==3))
{
trigger_number=0;
gather_time_hour=0;
gather_time_minute=0;
}
}
if(KEY_Value==8){
KEY_Value=0;
if(SEG_Show==3)
{
if(Temper_Para>=99)Temper_Para=99;
else Temper_Para+=1;
}
}
if(KEY_Value==5){
KEY_Value=0;
if(SEG_Show==2)
{
if(Back_Show==1)Back_Show=2;
else if(Back_Show==2)Back_Show=3;
else if(Back_Show==3)Back_Show=1;
}
}
if(KEY_Value==4){
KEY_Value=0;
if(SEG_Show==1){SEG_Show=2;SEG_Show_2=1;}
else if(SEG_Show==2){SEG_Show=3;Back_Show=1;SEG_Show_2=0;}
else if(SEG_Show==3)SEG_Show=1;
}
}
void SEG_Refresh(void)
{
if(SEG_Show == 1)
{
// LEDx_OFF(2);LEDx_OFF(3);LEDx_ON(1);
DigBuf[0] = Get_Time[2] / 10; DigBuf[1] = Get_Time[2] % 10; DigBuf[2] = 20;
DigBuf[3] = Get_Time[1] / 10; DigBuf[4] = Get_Time[1] % 10; DigBuf[5] = 20;
DigBuf[6] = Get_Time[0] / 10; DigBuf[7] = Get_Time[0] % 10;
}
else if(SEG_Show == 2)
{
// SEG_Show_2=1;
// LEDx_OFF(1);LEDx_OFF(3);LEDx_ON(2);
if(Back_Show==1)//温度回显
{
DigBuf[0] = 22; DigBuf[1] = 21;
DigBuf[2] = Temp_Max / 10;
DigBuf[3] = Temp_Max % 10;
DigBuf[4] = 20;
DigBuf[5] = Temp_Average / 100;
DigBuf[6] = Temp_Average % 100 / 10 + 10;
DigBuf[7] = Temp_Average % 10;
}
else if(Back_Show==2)//湿度回显
{
DigBuf[0] = 23; DigBuf[1] = 21;
DigBuf[2] = Humidity_Max/10;
DigBuf[3] = Humidity_Max%10;
DigBuf[4] = 20;
DigBuf[5] = Humidity_Average / 100;
DigBuf[6] = Humidity_Average % 100 / 10 + 10;
DigBuf[7] = Humidity_Average % 10;
}
else if(Back_Show==3)//时间回显
{
DigBuf[0] = 24; DigBuf[1] = trigger_number / 10;
DigBuf[2] = trigger_number % 10;
DigBuf[3] = gather_time_hour / 10;
DigBuf[4] = gather_time_hour % 10;
DigBuf[5] = 20;
DigBuf[6] = gather_time_minute / 10;
DigBuf[7] = gather_time_minute % 10;
}
if(trigger_number==0)
{
DigBuf[1] = 21;
DigBuf[2] = 21;
DigBuf[3] = 21;
DigBuf[4] = 21;
DigBuf[5] = 21;
DigBuf[6] = 21;
DigBuf[7] = 21;
}
}
else if(SEG_Show == 3)//参数界面
{
DigBuf[0] = 25; DigBuf[1] = 21;
DigBuf[2] = 21;
DigBuf[3] = 21;
DigBuf[4] = 21;
DigBuf[5] = 21;
DigBuf[6] = Temper_Para/10;
DigBuf[7] = Temper_Para%10;
if(Temper_Para < 10){DigBuf[6] = 21;DigBuf[7] = Temper_Para; }
}
else if(SEG_Show == 5)//测试界面
{
DigBuf[0]=Humidity/10;DigBuf[1]=Humidity%10;
DigBuf[2]=21;
DigBuf[3]=PWM_IN_Freq/10000;
DigBuf[4]=PWM_IN_Freq%10000/1000;
DigBuf[5]=PWM_IN_Freq%1000/100;
DigBuf[6]=PWM_IN_Freq%100/10;
DigBuf[7]=PWM_IN_Freq%10;
if(PWM_IN_Flag==1)
{
DigBuf[0]=26;DigBuf[1]=26;
}
}
if(SEG_Show == 9)//温湿度界面
{
// LEDx_OFF(1);LEDx_OFF(2);LEDx_ON(3);
DigBuf[0] = 27; DigBuf[1] = 21;
DigBuf[2] = 21;
DigBuf[3] = Temp_Vaue/10;
DigBuf[4] = Temp_Vaue % 10;
DigBuf[5] = 20;
DigBuf[6] = Humidity / 10;
DigBuf[7] = Humidity % 10;
if(PWM_IN_Flag==1)
{
DigBuf[6]=26;DigBuf[7]=26;
}
}
}
void LED_Reference(void)
{
if(SEG_Show==1){LEDx_ON(1);}
else LEDx_OFF(1);
if(SEG_Show==2){LEDx_ON(2);}
else LEDx_OFF(2);
if(SEG_Show==9){LEDx_ON(3);}
else LEDx_OFF(3);
if(Temp_Vaue>Temper_Para)
{
if(LED_4_Flag==0){LED_4_Flag=1;LEDx_ON(4);}
else if(LED_4_Flag==1){LED_4_Flag=0;LEDx_OFF(4);}
}
if(PWM_IN_Flag==1){ LEDx_ON(5);}
else if(PWM_IN_Flag==0){LEDx_OFF(5);}
}
void Timer2(void) interrupt 12
{
if(PWM_IN == 1)
{
PWM_INH_tt++;
if(PWM_Deuty_flag == 1)
{
PWM_Deuty_flag = 0;
PWM_INL_Save = PWM_INL_tt;
PWM_INL_tt = 0;
}
}
else if(PWM_IN == 0)
{
PWM_INL_tt++;
if(PWM_Deuty_flag == 0)
{
PWM_Deuty_flag = 1;
PWM_INH_Save = PWM_INH_tt;
PWM_INH_tt = 0;
}
}
}
void Timer2Init(void) //10微秒@12.000MHz
{
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0x88; //设置定时初始值
T2H = 0xFF; //设置定时初始值
AUXR |= 0x10; //定时器2开始计时
}
void Timer0(void) interrupt 1
{
P0 =0X00; //先设置选择数码管位选的P0输出值(消影)
P2|=0XC0; // 将P27 P26 设置为1 其他位保持不变
P2&=0XDF; // 将P26设置为0 其他位保持不变
P2&=0X1F; //关闭所有的74HC573锁存器
P0=tab[DigBuf[DigCom]]; //先设置选择数码管段选的P0输出值
P2|=0XE0; //将P27 P26 P25设置为1 其他位保持不变
P2&=0XFF; //这行程序可以不用写。
P2&=0X1F; //关闭所有的74HC573锁存器 0001 1111
P0=(0X01<<DigCom); //先设置选择数码管位选的P0输出值
P2|=0XC0; // 将P27 P26 设置为1 其他位保持不变
P2&=0XDF; // 将P26设置为0 其他位保持不变
P2&=0X1F; //关闭所有的74HC573锁存器
if(++DigCom==8)DigCom=0;
Task_Clock();
}
void Timer0Init(void) //1毫秒@12.000MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x20; //设置定时初始值
TH0 = 0xD1; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
void ALL_Init(void)
{
P0 =0X00; //先设置关闭蜂鸣器继电器的P0输出值(全关)
P2|=0XA0; // 将P27 P25 设置为1 其他位保持不变
P2&=0XBF; // 将P26设置为0 其他位保持不变
P2&=0X1F; //关闭所有的74HC573锁存器
P0 =0XFF; //先设置关闭所有的LED的P0输出值(全关)
P2|=0X80; // 将P27设置为1 其他位保持不变
P2&=0X9F; // 将P26 P25设置为0 其他位保持不变
P2&=0X1F; //关闭所有的74HC573锁存器
P0 =0X00; //先设置选择数码管位选的P0输出值(全不选)
P2|=0XC0; // 将P27 P26 设置为1 其他位保持不变
P2&=0XDF; // 将P26设置为0 其他位保持不变
P2&=0X1F; //关闭所有的74HC573锁存器
}
void Key_W(unsigned char Value)
{
unsigned char Val = Value;
P3=Val;P44=Val>>7;P42=(Val&0x40)>>6; // 0111 1111 0100 0000
}
unsigned char Key_R()
{
unsigned char Val = 0XFF,Val_P3=0,Val_P44=0,Val_P42=0;
Val_P3 = P3; Val_P44 = P44; Val_P42 = P42;
Val = ((Val_P3&0X3f)|(Val_P44<<7)|(Val_P42<<6)); //0011 1111 | 1000 0000 | 0100 000
return Val;
}
/***矩阵按键**/
void ArrKeyScan(void)
{
unsigned char key,key1,key2;
switch(KeyState)
{
case KEY_Check:
{
Key_W(0X0F); //P3=0XF0; //所有列全部输出低电平
if((Key_R()&0X0F)!=0X0F) //有按键被按下,能知道那一行,但不知道那一列
{
KeyState = KEY_Press;
}
}
break;
case KEY_Press:
{
// Key_W(0X0F);
if((Key_R()&0X0F)!=0X0F) //消抖之后继续判断,是否按键依然被按下着,证明确实有按键被按下了
key1=Key_R()&0X0F; //key1 存储按键的行值(即哪一行有按键被按下) 1110 1101 1011 0111
Key_W(0XF0); //改变为所有行全部输出低电平
if(((Key_R()&0XF0)|0X10)!=0XF0) //还是有按键被按下,能知道那一列,但不知道那一行
{
key2=(Key_R()&0XF0)|0X10; //key2 存储按键的列值(即哪一行有按键被按下) 1110 1101 1011 0111
key=key1|key2; //行值与列值相或,下面就可以得出那一列哪一行被按下了
if(key!=0xff) //判断一下是都真的有按键被按下,其实这一句可以不写。
{
switch(key) //分析出哪一个按键被按下了
{
case 0x7b: KEY_Value = 5 ;break;
case 0x77: KEY_Value = 4 ;break;
case 0xbb: KEY_Value = 9 ;break;
case 0xb7: KEY_Value = 8 ;break;
default: break;
}
KeyState = KEY_Release;
}
}
}
break;
case KEY_Release:
{
Key_W(0X0F); //P3=0XF0; //所有列全部输出低电平
if((Key_R()&0X0F)!=0X0F) //有按键被按下,能知道那一行,但不知道那一列
{
if(KEY_Value==9)
{
KEY_Press_TIME = KEY_Press_TIME + 10;
}
}
else
{
KeyState = KEY_Check;
KEY_Flag = 1;
}
}
break;
default: break;
}
}
void Delay_MS(unsigned int MS)
{
unsigned int i,j;
for(i=0;i<MS;i++)
for(j=910;j>0;j--);
}
程序是我按照以前学习大科的方法之后写出来的,可能有些理解和大家不是很一样,还会出一点小Bug,请大家指教。如有侵权,联系删除。