51单片机:220v 家用定时开关控制系统模拟(基于开发板固有硬件)

        本实验是单片机开发的一次小作业,因为系统涉及独立按键(开关键、上下左右键,自行定义)、LED 数码管、蜂鸣器、中断、定时器等相关设施,对51单片机的使用比较全面,所以拿来举例复盘。

系统采用实时时钟,通过设定可以控制 220V 电源的接通时刻与接通的时间长短。

51单片机主要特点总结

1.单片机系统框架

2.单片机存储器配置特点

3单片机I/O口展示

4中断简介

本次小实验相关东西

1.资源定义:

数码管 1-8 功能分配:

数码管 1-2: 分钟

数码管 3-4: 秒

数码管 5: 空闲,全黑,模式显示,1:开始时间设置,2:结束时间设置,3:运行

数码管 6-8: 显示 220 或 000 按键:

KEY1: 开机,设置键,单击,开机,双击切换设置模式,长按,系统关机;

KEY2: (单击)左移键,相当于光标,移动当前编辑位,左移

KEY3: (单击)右移键,相当于光标,移动当前编辑位,右移

KEY4: (单击)上,数值增加 KEY5: (单击)下,数值减小

2.功能实现:

F1开机,单击 KEY1,带 BEEP,数码管 1-4 显示全 0,数码管 5: 黑,数码管 6-8 显示全 0.

F2关机,长按 KEY1,带 BEEP,关机,数码管显示全黑.

F3设置功能切换,开机后,双击 KEY1,第 5 位数码管点亮,循环显示 1-2-3,。。。 F4[10 分].进入设置时间状态,开机后,双击 KEY1,第 5 位数码管显示 1、2,进入开始时间编辑模式,默认 1-4 数码 管显示全 0,其中最后一位,即第四位,闪烁,0.5 秒周期;

F5闪烁循环,进入编辑状态后,显示全 0,最后一位闪烁,单击 KEY2,闪烁位左移,循环;单击 KEY3,闪烁 位右移,循环。

F6数值编辑,进入编辑状态后,显示全 0,单击 KEY2,单击 KEY3,移动闪烁,单击KEY4 或KEY5,闪烁位增1或减 1,循环。

F7设置完毕,双击 KEY1,第 5 位数码管点亮,显示 3,定时系统开始运行,启动一个定时器,时间分辨率为秒,(模拟时,用“开始时间值”更新当前时间值,此时开始时间到,开始通电),此时,6-8 位显示220,表示220电源接通,同时 beep 开始,间隔 3 秒 beep 一次,持续,表示运行状态。运行到结束时间值,时,停止beep,220显示位 000,表示断电。

          注意:系统的默认实时时钟为从 0 时 0 分 0 秒开始,实时时钟开机后一直运行直到关机,为了简化处理,实时时钟不必与北京时间同步。例如:设定的开始接通时间 12:00,设定结束接通时间 12:01,则实时时钟运行到12:00时开始 Beep,6-8 位显示 220,表示 220v 电源接通,12:01 时 Beep 关闭,表示 220v 电源断开,220 显示位000

3.代码展示:

3.1 初始定义

#include "reg52.h"

typedef unsigned int u16;	  //对数据类型进行声明定义
typedef unsigned char u8;

u8 code smgduan[18]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
//显示0~F的值

u16 flag=0,key_time,digit=0,digit2=0,state=0,duration=0,pause=0;
u16 a=0,b=0,c=0,d=0,a1=0,b1=0,c1=0,d1=0,a2=0,b2=0,c2=0,d2=0,e=0,f=0,h=0,i=0,j=0,k=0,l=200,m=1,n=0;
u16 key1=0,key1_state=0,only_k1_down=0,key1_is_s=0,key1_is_d=0,key1_is_l=0,key2=0,key2_state=0,key3=0,key3_state=0,key4=0,key4_state=0,key5=0,key5_state=0,key2_is_s=0,key3_is_s=0,key4_is_s=0,key5_is_s=0;

sbit beep=P2^0;

sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;

sbit k1=P1^0;
sbit k2=P1^1;
sbit k3=P1^2;
sbit k4=P1^3;
sbit k5=P1^4;

3.2数码管部分


void Display(u16 a,u16 b,u16 c,u16 d,u16 e,u16 f,u16 g,u16 h)
{	 P0=0;
		  
		switch(i)	 //位选,选择点亮的数码管,
		{
			case(0):
				LSA=0;LSB=0;LSC=0;P0=smgduan[a]; break;//显示第1位
			case(1):
				LSA=1;LSB=0;LSC=0;P0=smgduan[b];  break;//显示第2位
			case(2):
				LSA=0;LSB=1;LSC=0;P0=smgduan[c];  break;//显示第3位
			case(3):
				LSA=1;LSB=1;LSC=0;P0=smgduan[d];  break;//显示第4位
			case(4):
				LSA=0;LSB=0;LSC=1;P0=smgduan[e];  break;//显示第5位
			case(5):
				LSA=1;LSB=0;LSC=1;P0=smgduan[f];  break;//显示第6位
			case(6):
				LSA=0;LSB=1;LSC=1;P0=smgduan[g];  break;//显示第7位
			case(7):
				LSA=1;LSB=1;LSC=1;P0=smgduan[h];  break;//显示第8位
		}
		i++;
		if(i>=8)
		i=0;	 
	
}

3.3控制闪烁的函数

(17为不存在的数代表灭)


void flash1()
{	  
	 	  if(digit%500<=250)
		                     Display(a,b,c,d,e,0,0,0);
	     else
	                        Display(17,b,c,d,e,0,0,0);			
}
void flash2()
{	  
	 	  if(digit%500<=250)
		                     Display(a,b,c,d,e,0,0,0);
	      else
	                         Display(a,17,c,d,e,0,0,0);			
}
void flash3()
{	  
	 	  if(digit%500<=250)
		                     Display(a,b,c,d,e,0,0,0);
	      else
	                         Display(a,b,17,d,e,0,0,0);			
}
void flash4()
{	  
	 	  if(digit%500<=250)
		                      Display(a,b,c,d,e,0,0,0);
	       else
	                          Display(a,b,c,17,e,0,0,0);			
}  

3.4按键函数,包括单击,双击,长按

void key1_down()
{
         if(k1==0&&only_k1_down==0)
                                     {only_k1_down=1;flag=0;}
         if(flag>=3&&k1==0)
                                     {only_k1_down=0;key1=0;}
}
		
void key1_up()
{        if(k1==1)
                    key1=1;
}

void key1judge()
{
      key1_down();key1_up();

switch(key1_state)
{
    case 0:
                         if(key1==1)
                                           {k=1;}
                         if(key1==0&&k==1)
                                          {key1_state=1;key_time=0;k=0;} 
                         break;

    case 1:

                         if(key_time<300&&key1==1)

                                         {key1_state=2;duration=2*key_time;pause=0;}
                        if(key_time>=300&&key1==0)													  //长按k1
                                          {key1_state=0;key1_is_l=1;}
                        break;

    case 2:

                         if(pause<duration) 
                                         {if(key1==0)
                                                    {key1_state=3;key_time=0;}
                                          }															  //单击k1
                         else
                                         {key1_state=0;key1_is_s=1;}
                        break;

    case 3:

                        if(key_time<300&&key1==1)
                                        {key1_state=0;key1_is_d=1;}
                        if(key_time>300&&key1==0)  					                              	//双击k1

                                        {key1_state=0;key1_is_l=1;}
                                              break;
}
}


void key2judge()
{
          switch(key2_state)
                             {case 0:
                                      if(k2==0)
                                               {key2_state=1;key_time=0;}
                                       break;

                             case 1:
                                      if(key_time<300&&k2==1)									   //k2单击
                                                            {key2_is_s=1;key2_state=0;}
                                      if(key_time>=300)
                                                            {key2_state=0;}
                                      break;
                             }
}

void key3judge()
{
             switch(key3_state)
                              {case 0:
                                      if(k3==0)
                                                {key3_state=1;key_time=0;}
                                        break;

                               case 1:
                                       if(key_time<300&&k3==1)										  //k3单击
                                                               {key3_is_s=1;key3_state=0;}
                                        if(key_time>=300)
                                                                  { key3_state=0;}
                                           break;
                             }
}

void key4judge()
{
              switch(key4_state)
                               { case 0:
                                         if(k4==0)
                                                    {key4_state=1;key_time=0;}
                                          break;

                                 case 1:															  //k4单击
                                         if(key_time<300&&k4==1)
                                                    {key4_is_s=1;key4_state=0;}
                                           if(key_time>=300)
                                                        {key4_state=0;}
                                            break;
                                 }
}

void key5judge()
{ switch(key5_state)
                                {case 0:
                                         if(k5==0)
                                                              {key5_state=1;key_time=0;}
                                            break;

                                 case 1:
                                         if(key_time<300&&k5==1)
                                                             {key5_is_s=1;key5_state=0;}
                                          if(key_time>=300)
                                                             {key5_state=0;}
                                             break;
                               }
}				

3.5定时器中断

(可以结合上图定时器中断框图看)

/*******************************************************************/
void Timer0Init()
{
	TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。
	TH0=0XFC;	//给定时器赋初值,定时1ms
	TL0=0X18;	
	ET0=1;//打开定时器0中断允许
	EA=1;//打开总中断
	TR0=1;//打开定时器			
}

void Timer1Init()
{
	TMOD|=0X10;//选择为定时器1模式,工作方式1,仅用TR1打开启动。
	TH1=0XFC;	//给定时器赋初值,定时1ms
	TL1=0X18;	
	ET1=1;//打开定时器1中断允许
	EA=1;//打开总中断
	TR1=1;//打开定时器			
}


void  Timer0() interrupt 1    
{	  
 TH0 = 0xfc;   
  TL0 = 0x18;   
 digit++;  //1ms 
 if(digit%10==0)	  
{key_time++;pause++;flag++;l++;}      
    
}

void  Timer1() interrupt 3    
{	  
 TH1 = 0xfc;   
 TL1 = 0x18;   
digit2++;  //1ms
if(digit2%1000==0)
{d++;n++;}
  
}

主函数,采用状态机的方法实现各功能的结合

(状态机代码的编写能力很重要)

/*****************************************************/
void main()
{
      Timer0Init();
	  Timer1Init();
      TR1=0;
while(1)
{
      if(state==1&&l<25)
                         {if(  digit%4==0)
                                           {  beep=~beep;}
					     }
      if(state==0&&l<25)
                        {if(digit%4==0)
                                            {beep=~beep;}
					     }




       if(state==8)

	   
                       {  if(n%3==0&&n!=0)
                                                {l=0;}
                          if(digit%4==0&&l<25)
                                               {beep=~beep;}
                        }



  
       if(key_time>=4000)
                             { key_time=0;}
       if(pause>=4000)
                            { pause=0;}
       if(flag>=4000)
                            {flag=0;}
        if(l>=400)
                            {l=200;} 
       if(digit >= 8000)   
                           {digit = 0;}

       if(d==10)
                        {c++;d=0;}
       if(c==6)
                        {b++;c=0;}
       if(b==10)
                         {a++;b=0;}
       if(a==6)
                         {a=0;b=0;c=0;d=0;}
       if(digit2>=4000)
                         {  digit2=0;
                                    if(n>999)
                                             {n=0;}
                         }   		


       if(digit%40==0)
                          {key1judge();key2judge();key3judge();key4judge();key5judge();}
        if(key1_is_l==1)
                           {state=0;key1_is_l=0;}

switch(state)
{
case 0:
           P0=0;
           TR1=0;
           if(m==0)
          { m=1;l=0;}
          if(key1_is_s==1)
          {state=1;key1_is_s=0;}
          a=0;b=0;c=0;d=0;
           break;

case 1:

          Display(0,0,0,0,17,0,0,0);
          if(m==1)
                             {l=0;m=0;}
          if(key1_is_d==1)
                            {state=2;e=1;j=0;key1_is_d=0;}
         break;

case 2:
         flash4();

        if(key2_is_s==1)
                        {state=3;key2_is_s=0;}
        if(key3_is_s==1)
                        {state=5;key3_is_s=0;}
       if(key4_is_s==1)
                        {d++;key4_is_s=0;}
       if(key5_is_s==1)
                       {  key5_is_s=0;
                          if(d>0)
                          {d--;}
                       }
       if(key1_is_d==1&&j==0)
                       {state=6;key1_is_d=0;}
      if(key1_is_d==1&&j==1)
                       {state=7;key1_is_d=0;}
      break;

case 3:
           flash3();

       if(key2_is_s==1)
                       {state=4;key2_is_s=0;}
       if(key3_is_s==1)
                        {state=2;key3_is_s=0;}
       if(key4_is_s==1)
                        {c++;key4_is_s=0;}
       if(key5_is_s==1)
                       {key5_is_s=0;
                         if(c>0)
                          {c--;}
                       }
      if(key1_is_d==1&&j==0)
                        {state=6;key1_is_d=0;}
      if(key1_is_d==1&&j==1)
                        {state=7;key1_is_d=0;}
       break;

case 4:
        flash2();
     
	 if(key2_is_s==1)
                     {state=5;key2_is_s=0;}
     if(key3_is_s==1)
                     {state=3;key3_is_s=0;}
     if(key4_is_s==1)
                     {b++;key4_is_s=0;}
      if(key5_is_s==1)
                     {key5_is_s=0;
                       if(b>0)
                       {b--;}
                     }
     if(key1_is_d==1&&j==0)
                    {state=6;key1_is_d=0;}
     if(key1_is_d==1&&j==1)
                    {state=7;key1_is_d=0;}
      break;

case 5:
        flash1();
       if(key3_is_s==1)
                      {state=4;key3_is_s=0;}
       if(key2_is_s==1)
                      {state=2;key2_is_s=0;}
       if(key4_is_s==1)
                       {a++;key4_is_s=0;}
       if(key5_is_s==1)
                      {key5_is_s=0;
                        if(a>0)
                        {a--;}
                       }
       if(key1_is_d==1&&j==0)
                      {state=6;key1_is_d=0;}
       if(key1_is_d==1&&j==1)
                      {state=7;key1_is_d=0;}
       break;

case 6:
     
	   a1=a;b1=b;c1=c;d1=d;a=0;b=0;c=0;d=0;e=2;
 
       j=1;state=2;
       break;

case 7:
       a2=a;b2=b;c2=c;d2=d;
       a=0;b=0;c=0;d=0;e=3;
       state=8;
       break;

case 8:
       TR1=1;
                    Display(a,b,c,d,3,f,f,0);
                    
					if(a==a1&&b==b1&&c==c1&&d==d1)
                                                   {f=2;}
                    if(a==a2&&b==b2&&c==c2&&d==d2)
                                                    {f=0;}
       break;
}
}
}	

  总结就是,51还是具有很大可玩性的,其次就是要锻炼大项目能力,实验过程中发现这种程度的项目debug就要花很长时间了,是因为c语言编程能力还是较弱,不过加深了对硬件的理解,从根本上知道了代码的作用。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

is llong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值