我的账户
中国电子DIY

科技成就未来

亲爱的游客,欢迎!

已有账号,请

如尚未注册?

多图杀猫,胆小勿入!资料开源

[复制链接]
9396 52
苗条的猩猩 发表于 2016-11-15 14:33:10 | 只看该作者 |只看大图 |阅读模式 打印 上一主题 下一主题
本帖最后由 苗条的猩猩 于 2016-11-15 14:33 编辑

好久没发帖了,本来早就想发这篇帖的,但是怕软件运行不稳定被人喷,现在已经工作3个多月了,
非常稳定。
本人发帖一向追求原创和图文并茂,像某些朋友直接从网上复制几段文字图片那种事我做不来。
首先,简单说明下,这是一个4路??丶影醇刂频牟遄?,第一路可定时,开启时间和关闭时间可
独立定时。定时范围999(分钟),四位数码管显示。
既然是改装插座,肯定先要有个现成插座板,于是我从超市买了个带开关的。

外观还不错,主要看中他内部独立的模组结构,方便改装。

拆开的样子,不错吧?一分钱一分货,这玩意要40多大洋
我准备在两头空缺的区域放置电路板,不过空间太小,有些挑战。
我采用的是stc的单片机,便宜,哈哈哈哈,推荐配置:
4K以上空间,8—12M晶振,最小io数目22,上拉电阻10K(省电与稳定的平衡点),
首先单片机是5V的,所以要个电源,本来想用阻容降压,但考虑到要驱动4个继电器,
怕功率达不到,加上阻容降压本身不安全不稳定,万一调试的时候不小心触电我就挂了。
所以我打算用手机适配器的电路板


但是苯宝宝很快发现一个问题,这电源太大了,放不进插座,但是厚度到是轻薄,要是能把长度变到厚度上就好了。
我发现这对于天生爱思考的我根本不是事,我把所有元件拆了下来,然后抄板,于是有了下面的作品。

这是我根据原来的电路重新设计的电源。

很紧凑有木有?
好了,主角该出场了,当当当当!

这是主板,PLCC封装89C52.外形经过了我一天两夜的严格设计


这是整合在背面的升压系统,因为继电器是12V驱动的,所以要把5V升到12V。

侧面来一张。

从汽车主板上拆的12V继电器。(哥以前是修车的)

继电器装好的样子,用胶水稍微粘下好些。

放入主板和电源的样子。用泡沫棉固定一下走线方便装壳,话说这走线有点乱,没办法,想线太多。

当当当当??!写好软件的成品。
开机后全部继电器关闭。
第一位数码管显示第一路继电器状态,第二位数码管显示。。。
F表示关闭,n表示接通,第一个按键控制第一路,第二个控制。。。。
长按第一个按键进入定时界面,这时短按第一个按键选择定时开启时间还是关闭时间,并由第一个数码管显示状态
第二个按键选择调整个位十位百位,第三个按键数字加一,第四个按键数据保存,长按第四个按键退出并开始定时,
定时过程中,另外三路照常工作,并由小数点显示状态。此过程中长按第四个按键取消定时并回到初始界面。
看下视频吧。

原理图文件开放,要的拿走。

话说我做项目从来不用原理图,嫌麻烦,这个图是我为了发帖画的,全部元件都是临时建的。
下面是代码。此代码不包含红外接收程序,为的是不想便宜游客,要的留邮箱。



/* 通用头文件 */
#include <REGX52.H>
#include <intrins.h>
#define SYS_MCLK   (11059387/12)  //系统主时钟频率,即振荡器频率÷12
/* 数据类型定义 */
typedef  signed    char    int8;    // 8位有符号整型数
typedef  signed    int     int16;   //16位有符号整型数
typedef  signed    long    int32;   //32位有符号整型数
typedef  unsigned  char    uint8;   // 8位无符号整型数
typedef  unsigned  int     uint16;  //16位无符号整型数
typedef  unsigned  long    uint32;  //32位无符号整型数

bit Longkey_f=0;//长按键触发标志

uint8 l=0;           //.....
uint8 e=0;          //.....
uint8 d=0;          //.....

bit  s_onaf=0;//选择通断方式
uint8 s_timedi=0;//个位时间调整
uint8 s_timete=0;//十位时间调整
uint8 s_timehu=0;//百位时间调整
uint8 s_loca=0;//个位,十位,百位选择

uint8 Longkey=0; //界面切换

uint16 varn=0; //保存导通时间的变量(最大值999)
uint16 varf=0;//保存关断时间的变量(最大值999)
uint16 min=0;

sbit KEY1 = P3^7;  //定义按键接口
sbit KEY2 = P3^6;
sbit KEY3 = P3^5;
sbit KEY4 = P3^4;

sbit RELAY_OUT1= P2^0;        //定义继电器控制输出接口                                                                                                                                          
sbit RELAY_OUT2= P2^1;                                                                                                                                                  
sbit RELAY_OUT3= P2^2;                                                                                                                                                  
sbit RELAY_OUT4= P2^3;                                                                                                                                                  

uint8 i = 0;
uint8 j = 0;        

uint8 T0RH = 0;    //T0重载值的高字节
uint8 T0RL = 0;    //T0重载值的低字节

unsigned char code LedChar[] = { 0XFA,0X22,0XB9,0XAB,0X63,0XCB,0XDB,0XA2,0XFB,0XEB,0XF2,0XD1,
0xFE,0X26,0XBD,0XAF,0X67,0XCF,0XDF,0XA6,0XFF,0XEF
}; //数码管显示字符转换表        (由于数码管的段码引脚我是乱接的,所以取模都是手动计算)
uint8 LedBuff[9] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00,0x00}; //数码管显示缓冲区
uint8 pdata out[4] = {0, 0, 0, 0}; //这是啥来着。。。太久了忘记了
const uint8 code KeyCodeMap[6] = { 1,2,3,4,5,6,}; //按键值与??丶涤成浔?
unsigned char Output[2];  //显示开关状态的数据缓冲区
extern bit irflag;         //红外接收标志
extern unsigned char ircode[4];          //接收到的红外数据
extern void InitInfrared(void);        //红外接收子函数

/* 定时器T0配置子程序 */
void ConfigTimer0(uint16 ms)
{
    uint32 tmp;

    tmp = (SYS_MCLK*ms)/1000; //计算所需的计数值
    tmp = 65536 - tmp;        //计算定时器重载值
    tmp = tmp + 34;           //补偿中断响应延时造成的误差   
    T0RH = (uint8)(tmp>>8);   //定时器重载值拆分为高低字节
    T0RL = (uint8)tmp;
    TMOD &= 0xF0;   //清零T0的控制位
    TMOD |= 0x01;   //配置T0为模式1
    TH0 = T0RH;     //加载T0重载值
    TL0 = T0RL;
    ET0 = 1;        //使能T0中断
    TR0 = 1;        //启动T0
}

/* 数码管动态扫描刷新函数,需在定时中断中调用 */
void LedScan()
{
    static unsigned char i = 0;  //动态扫描索引

    P1 = 0x00;                  //关闭所有段选位,显示消隐
    P0 = (P0 & 0xF0) | i;       //位选索引值赋值到P1口低3位
    P1 = LedBuff;            //缓冲区中索引位置的数据送到P0口
    if (i < sizeof(LedBuff)-1)  //索引递增循环,遍历整个缓冲区
        i++;
    else
        i = 0;
}
void S_pstnu() //时间调整
{
switch (s_loca)   
    {
            case 0:
                         s_timedi++; if(s_timedi>=10){s_timedi=0;};
                                 break;
        case 1:
                         s_timete++; if(s_timete>=10){s_timete=0;};
                                 break;
        case 2:
                     s_timehu++; if(s_timehu>=10){s_timehu=0;};
                                 break;
        case 3:
                         s_loca=0;
                                 break;
        default: break;
    }
}

void timetdw() //个位十位百位数据整合
{
if(s_onaf==1)
    {varn=s_timedi+s_timete*10+s_timehu*100;s_timedi=0;s_timete=0; s_timehu=0;}
else
    {varf=s_timedi+s_timete*10+s_timehu*100;s_timedi=0;s_timete=0; s_timehu=0;}       
}

void KeyAction(unsigned char keycode)        //按键值索引
{
if(Longkey==0||Longkey>=2) //界面0和界面2的按键值索引
{       
    switch (keycode)   
    {
            case 1:
                               
                                 if( Longkey==0) {RELAY_OUT1=~RELAY_OUT1;}
                         else ;
                                 break;
        case 2:
                         RELAY_OUT2=~RELAY_OUT2;
                                 break;
        case 3:
                     RELAY_OUT3=~RELAY_OUT3;
                                 break;
        case 4:
                         RELAY_OUT4=~RELAY_OUT4;
                                 break;
            case 5:
                         Longkey=1;
                                 break;
            case 6:
                             Longkey=0;
                                 break;
        default: break;
    }
}
if(Longkey==1) //界面1的按键值索引
{       
    switch (keycode)   
    {
            case 1:
                         s_onaf=~s_onaf;
                                 break;
        case 2:
                         s_loca++; if(s_loca>=3){s_loca=0;};
                                 break;
        case 3:
                     S_pstnu();
                                 break;
        case 4:
                         timetdw();min=varf;
                                 break;
            case 5:
                         Longkey=1;
                                 break;
            case 6:
                         Longkey=2;
                                 break;
        default: break;
    }
}

}

void Relay() //红外按键索引
{

                            if (ircode[0]==0X01)
                {
                  if (ircode[2]==0X01)
                  {
                     KeyAction(1);  
                  }
                }
                            if (ircode[0]==0X02)
                {
                  if (ircode[2]==0X02)
                  {
                     KeyAction(2);
                  }
                }
                            if (ircode[0]==0X03)
                {
                  if (ircode[2]==0X03)
                  {
                     KeyAction(3);  
                  }
                }
                            if (ircode[0]==0X04)
                {
                  if (ircode[2]==0X04)
                  {
                     KeyAction(4);
                  }
                }
                                    if (ircode[0]==0X05)
                {
                  if (ircode[2]==0X05)
                  {
                     KeyAction(5);
                  }
                }
                               if (ircode[0]==0X06)
                {
                  if (ircode[2]==0X06)
                  {
                     KeyAction(6);
                  }
                }
}
/* 按键扫描函数,需在定时中断中调用,推荐调用间隔1ms */
void KeyScan()
{
static uint16 ft1 = 0;  //按键脉冲计数
static uint16 ft2 = 0;
static uint16 ft3 = 0;
static uint16 ft4 = 0;
    if(!KEY1)
        {
          ft1++;
         }

          if(ft1>1050)
                {
                        ft1=1051;
                        if(KEY1)
                        {
                            KeyAction(5);
                         ft1=0;
                }
                        }
          if(ft1>40&&ft1<800)
          {
            if(KEY1)
           {
                 KeyAction(1);
                        ft1=0;
           }
          }

              if(!KEY2)
        {
          ft2++;
         }

          if(ft2>1050)
                {
                        ft2=1051;
                        if(KEY2)
                        {
                            KeyAction(2);
                         ft2=0;
                }
                        }
          if(ft2>40&&ft2<800)
          {
            if(KEY2)
           {
                 KeyAction(2);
                        ft2=0;
           }
          }

              if(!KEY3)
        {
          ft3++;
         }

          if(ft3>1050)
                {
                        ft3=1051;
                        if(KEY3)
                        {
                            KeyAction(3);
                         ft3=0;
                }
                        }
          if(ft3>40&&ft3<800)
          {
            if(KEY3)
           {
                 KeyAction(3);
                        ft3=0;
           }
          }

              if(!KEY4)
        {
          ft4++;
         }

          if(ft4>1050)
                {
                        ft4=1051;
                        if(KEY4)
                        {
                            KeyAction(6);
                         ft4=0;
                }
                        }
          if(ft4>40&&ft4<800)
          {
            if(KEY4)
           {
                 KeyAction(4);
                        ft4=0;
           }
          }

}
void displayt_timing()        //界面2下的开关状态由位点显示
{

                                 if(RELAY_OUT2)
                                         {  
                       l=12;
                                          }
                    else        if(!RELAY_OUT2)
                                          {
                                            l=0;
                                          }
                                 if(RELAY_OUT3)
                                         {
                                          e=12;
                                         }
          else  if(!RELAY_OUT3)
                                         {
                                         e=0;
                                         }
                                 if(RELAY_OUT4)
                                         {  
                                        d=12;
                                          }
                 else        if(!RELAY_OUT4)
                                          {
                                          d=0;
                                          }
}
void display() //界面0下的开关状态由数码管显示n和F表示(on and off)
{

                                 if(RELAY_OUT1)
                                         {
                                          i<<=4;
                                          i>>=4;
                                      i|=0XA0;
                                         }
              else  if(!RELAY_OUT1)
                                         {
                                          i<<=4;
                                          i>>=4;
                                      i|=0XB0;
                                         }
                                 if(RELAY_OUT2)
                                         {  
                                          i>>=4;
                                          i<<=4;
                                      i|=0X0A;
                                          }
                    else        if(!RELAY_OUT2)
                                          {
                                          i>>=4;
                                          i<<=4;
                                      i|=0X0B;
                                          }
                                 if(RELAY_OUT3)
                                         {
                                          j<<=4;
                                          j>>=4;
                                      j|=0XA0;
                                         }
          else  if(!RELAY_OUT3)
                                         {
                                          j<<=4;
                                          j>>=4;
                                      j|=0XB0;
                                         }
                                 if(RELAY_OUT4)
                                         {  
                                          j>>=4;
                                          j<<=4;
                                      j|=0X0A;
                                          }
                 else        if(!RELAY_OUT4)
                                          {
                                          j>>=4;
                                          j<<=4;
                                      j|=0X0B;
                                          }
}

void main()
{
P1 = 0X00;  //初始化数码管全灭

RELAY_OUT1= 0;        //初始化继电器全关                                                                                                                                          
RELAY_OUT2= 0;                                                                                                                                                  
RELAY_OUT3= 0;                                                                                                                                                  
RELAY_OUT4= 0;

Output[0]=0XBB;        //显示开关状态的数据待命在FFFF
Output[1]=0XBB;
InitInfrared();         //初始化红外接收
ConfigTimer0(1); //定时器给1毫秒初值
EA = 1;                 //总中断允许
PT0 = 1;        //配置T0中断为高优先级,启用本行可消除接收时的闪烁
while(1)
{
  if(Longkey==0)  //界面0  (正常按键和??兀?br />   {
     display();
           varn=0;
           varf=0;
            min=0;       
  }

if(Longkey==1)         //界面1          (时间调整的显示处理)
  {
if(s_onaf)
{
i<<=4;
i>>=4;
i|=0XA0;

}
else if(!s_onaf)
{
i<<=4;
i>>=4;
i|=0XB0;
}
                                          j>>=4;
                                          j<<=4;
                                      j|=s_timedi;        //个位显示数据处理

                                          j<<=4;
                                          j>>=4;
                                      j|=(s_timete<<4);        //十位显示数据处理

                                          i>>=4;
                                          i<<=4;
                                      i|=s_timehu; //百位显示数据处理
                                                
  }
   if(Longkey>=2)         //界面2(倒计时的显示处理)
  {
                displayt_timing();
                                LedBuff[1] = LedChar[Output[0] >> 4];
                            LedBuff[2] = LedChar[min%10+d];
                                LedBuff[8] = LedChar[min/10%10+e];
                                LedBuff[4] = LedChar[min/100%10+l];       
  }


        if (irflag)  //红外接收功能实时查询
        {
            irflag = 0;
                   Relay();
                }
        if (Longkey<=1)  //         把界面0和1的显示数据加载到缓冲区
        {
                                Output[0]=i;
                     Output[1]=j;
            LedBuff[1] = LedChar[Output[0] >> 4];  //第一位
            LedBuff[4] = LedChar[Output[0]&0x0F]; //第二位
            LedBuff[8] = LedChar[Output[1] >> 4]; //第三位
            LedBuff[2] = LedChar[Output[1]&0x0F]; //第四位
                          
        }
}
}
/* T0中断服务函数,实现系统定时和按键扫描 ,数码管扫描显示 */
void InterruptTimer0() interrupt 1
{
    static uint8 tmr10s = 0;
    static uint8 tmr100ms = 0;
    static uint8 st = 0;
    static uint16 tin = 0;
        static bit a = 0;
            
    TH0 = T0RH;  //重新加载重载值
    TL0 = T0RL;
    tmr100ms++;  //定时100ms

    if (tmr100ms >= 100)
    {
        tmr100ms = 0;
        tmr10s++;  //定时10s
                //这里可以放标志位控制其他程序,比如不需要频繁执行的程序     
        if (tmr10s >= 100)
        {
            tmr10s = 0;
                    st++;          //定时一分钟
                   //这里可以放标志位控制其他程序
                     if (st>=6)
           {
                    st=0;
                        if(Longkey==2&&varn>=0) //检测到界面2且导通时间不为0进入倒计时       
          {       
                        if(!a)
                                {
                            i<<=4; //状态置为F         
                i>>=4;
                i|=0XB0;
                                Output[0]=i;
                                }
                        //        min=varf;        按键处理时已经赋值,这步不要,不然出错
                                  tin++; //计时器加1
                            min--; //关断时间减1
           if (tin>=999) //超程限制,不要也行
           {
                        tin=0;
           }               
        if(varf<=tin&&a==0)        //关断定时时间到
           {
              tin=0;                 //计时器清0
           varf=0;                 //关断时间清0,界面0已处理,这里不用也行
           min=varn;         //把导通时间赋值给min
           a=1;                         //执行完后不再进入
           i<<=4;                  //开关显示状态切换到n
       i>>=4;
       i|=0XA0;
           Output[0]=i;
           RELAY_OUT1= 1;  //继电器开启
        }
                if(varn<=tin&&a==1)         //导通定时时间到
           {
              tin=0;                           //所有有关数据清0,方便下次进入
           varn=0;
           a=0;
           RELAY_OUT1= 0;           //关闭继电器
           Longkey=0;                  //回到界面0
        }
  }
           }
        }
    }

    KeyScan();   //执行按键扫描
LedScan();   //数码管扫描显示        
}


再说一遍,要红外接收程序的留邮箱。
声明:文章内容为作者“苗条的猩猩”原创,仅作为学习讨论使用,严禁商业用途。
如需转载,引用全部或部分内容请注明出处。谢谢各位的配合。
特别鸣谢:1,感谢“中国电子diy之家”论坛提供分享平台。
2,感谢“宋雪江”老师提供的开源学习视频。
参与人数 4下载币 +25 刀币 +40 收起 理由
黎明之光 + 10 + 10 赞一个!
看门查水表 + 5 + 10 继电器的线是不是太细了,过流就不好玩了
疯爱 + 10 支持DIY精神!
diyhome + 10 + 10 支持DIY精神!

查看全部评分总评分 : 下载币 +25 刀币 +40

收藏
收藏8
分享
分享
支持
支持0
反对
反对0

精彩评论52

跳转到指定楼层
2#
GT2014 发表于 2016-11-15 16:07:14 | 只看该作者
支持DIY精神楼主继续加油,分享好作品
3#
王栋春 发表于 2016-11-15 20:23:12 | 只看该作者
动手能力超强呀           就是程序不能打包开源吗  
4#
1399109998 发表于 2016-11-15 21:33:26 | 只看该作者
厉害了我的哥竟然用plcc封装,还有继电器加光耦隔离了吗有没有?;ざ?/td>
5#
石头的旅行 发表于 2016-11-16 09:50:13 | 只看该作者
楼主,网上有卖小米拆机电源??榈?,折叠以后2.5*2.5*2.5,打开以后是5.0*2.5*1.4cm,标称1A,应该能满足你的要求。
6#
FSLTKJ 发表于 2016-11-16 13:11:14 | 只看该作者
不错,谢谢楼主分享+开源。
7#
670712150 发表于 2016-11-16 14:14:07 | 只看该作者
谢谢楼主分享??!
8#
jwb天若有情526 发表于 2016-11-17 09:28:01 | 只看该作者
楼主用的什么东西焊接的电路板  黑不溜秋的  
9#
 楼主| 苗条的猩猩 发表于 2016-11-17 11:50:05 | 只看该作者
jwb天若有情526 发表于 2016-11-17 09:28
楼主用的什么东西焊接的电路板  黑不溜秋的

松香              
10#
涟漪 发表于 2016-11-18 09:39:26 | 只看该作者
感谢楼主分享。                        
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关注0

粉丝5

帖子11

发布主题
推荐阅读
关注我们
中国电子DIY官方微信

客服电话:000-000-0000

客服邮箱:1684057167@qq.com

周一至周五 9:00-18:00

公司地址:深圳市南山区美丽湾大厦B座

Powered by Discuz! X3.4@ 2001-2013 Comsenz Inc.

  • 凯斯娱乐诚 2018-05-22
  • 澳门银河 2018-05-22
  • 博彩信用网 2018-05-21
  • 东方心经121期资料 2018-05-21
  • 网络博彩评级 2018-05-21
  • e路发网上开户 2018-05-20
  • 澳门丽都棋牌 2018-05-20
  • 威尼斯赌场 2018-05-19
  • 威廉希尔信誉棋牌 2018-05-19
  • 澳门皇冠游戏 2018-05-19
  • tt娱乐 2018-05-19
  • 新濠天地 2018-05-18
  • 永利平台玩法 2018-05-18
  • 澳门葡京娱乐场开户 2018-05-18
  • 实战百家乐 2018-05-18
  • hg1232 2018-05-17
  • 信用网 2018-05-17
  • 天地人娱 2018-05-17
  • 11澳门葡京官网 2018-05-17
  • 真人网上娱乐城 2018-05-16
  • 世界十大赌场排行 | | 博三公真人现金赌场 | hg体育果博足球赌场 | 澳门银河国际赌场 | 波音投注 | 足球外围赌球 |