找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1518|回复: 11
打印 上一主题 下一主题
收起左侧

单片机遥控风扇控制程序,望大师优化

[复制链接]
回帖奖励 90 黑币 回复本帖可获得 3 黑币奖励! 每人限 1 次
跳转到指定楼层
楼主
ID:796012 发表于 2023-5-23 14:07 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  1. /*风扇遥控芯片:BA5104  红外遥控解码程序  晶振频率:11.0592MHZ  1帧12位,一次至少发2帧*//*历时8天成功调试,干扰码直接清零,只显示相关键值*/
  2. /*解码后的键值:关机 0xfd81; 开/风速 0xfd82; 风类 0xfd84; 定时 0xfd88; 摇头 0xfd90; 彩灯 0xfdc3; 无 0xfda0; 无 0xfdc6*/
  3. #include "STC8G.h"/*单片机:STC8G1K08-TSSOP20*//*红外端口:P33(包含外部中断1,改端口时要注意)*/
  4. unsigned char q,b,s,g,/*位选*/ir[13],j,c,dw;unsigned int r,m,d0,d1,ds,se,buz;bit off,on,sm,cd,gj,yt;
  5. unsigned char code dm[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x08,0x48,0x49,0x76,0x00};/*共阴段码*/
  6. void delayms(unsigned int i){while(i--);}/*延时函数*/void int1init(){PX1=1;/*设置中断优先级*/IT1=1;EX1=1;EA=1;}/*外部中断1初始化函数,设置成下降沿触发*/
  7. void d0init()/*定时器0 1微秒@11.0592MHz*/
  8. {AUXR |= 0x80;/*定时器时钟1T模式*/TMOD &= 0xF0;/*设置定时器模式*/TL0 = 0xF5;/*设置定时初始值*/TH0 = 0xFF;/*设置定时初始值*/TF0 = 0;/*清除TF0标志*/TR0 = 0;/*定时器0先不计时*/}
  9. void d1init()/*定时器1初始化函数*/{AUXR |= 0x40;/*1T*/TMOD &= 0x0F;TL1 = 0x70;/*初始值*/TH1 = 0xFF;/*初始值*/TF1 = 0;/*清除TF1标志*/TR1=0;/*先不启动*/ET1=1;/*开中断*/EA=1;}
  10. void kayscan()/*P1端口对地增加按键*/
  11. {
  12.         P1=0xff;
  13.         P34=1;P35=1;P36=1;P37=1;
  14.   if(P11==0){delayms(5);if(P11==0){m=0xfd90;buz=1;while(!P11);}} /*摇头*/
  15.         if(P12==0){delayms(5);if(P12==0){m=0xfd84;buz=1;while(!P12);}} /*风类*/
  16.   if(P13==0){delayms(5);if(P13==0){m=0xfd81;buz=1;while(!P13);}} /*关机*/
  17.         if(P14==0){delayms(5);if(P14==0){m=0xfd88;buz=1;while(!P14);}} /*定时*/
  18.         if(P15==0){delayms(5);if(P15==0){m=0xfd82;buz=1;while(!P15);}} /*开/风速*/
  19.         P1=0x00;
  20. }
  21. void display()/*数码管扫描*/
  22. {
  23.         unsigned char i;for(i=0;i<4;i++){switch(i)/*选择显示位置*/
  24.         {
  25.                 case(0):P34=0;P35=1;P36=1;P37=1;break;  /*千位*/
  26.                 case(1):P34=1;P35=0;P36=1;P37=1;break;  /*百位*/
  27.                 case(2):P34=1;P35=1;P36=0;P37=1;break;  /*十位*/
  28.           case(3):P34=1;P35=1;P36=1;P37=0;break;  /*个位*/
  29.         }
  30.     if(i==0){P1=dm[q];}/*千位*/
  31.                 if(i==0&se>0&sm==1){P1=dm[20];}
  32.           if(i==1){P1=dm[b]; /*百位*/
  33.                 if(ds>999&sm==1){P1=dm[b]+0x80;}}
  34.           if(i==2){P1=dm[s];}/*十位*/
  35.           if(i==3){P1=dm[g];/*个位*/
  36.                 if(yt==1){P1=dm[g]+0x80;}}
  37.           if(P33==1){delayms(50);}       /*间隔一段时间扫描*/
  38.           P1=0x00;          /*消隐*/
  39.         }
  40. }
  41. void ircl()      /*红外时间记录*/
  42. {
  43.         unsigned char c1;
  44.         if(!P33)
  45.         {
  46.     d1=0;
  47.     TR1=1;       /*启动定时器1*/
  48.     while(!P33);
  49.     TR1=0;
  50.     ir[j]=d1;
  51.         }              /*编码位置清零*/                    
  52.   if(P33==1&&j>0)/*当端口高电平时,编码位置还未清零*/
  53.         {
  54.     c1++;        /*计算一下持续时间*/
  55.    if(c1>250)    /*超过一定的时间*/
  56.   {
  57.     c++;c1=0;
  58.   }
  59.          if(c>5)       /*就要再次按遥控按键*/
  60.   {
  61.           j=0;c=0;     /*如果还有干扰码就直接清零*/
  62.         }                     
  63.         }
  64. }
  65. void kzhs()/*键值控制函数 包含主板按键和红外遥控按键*/
  66. {
  67.         unsigned char fl,zd;
  68.         if(on==1&cd==1){display();/*开数码管*/}
  69.         if(on==1&m==0xfd81){fl=0;on=0;dw=0;zd=0;se=0;ds=0;TR0=0;cd=0;j=0;}/*关机状态*/
  70.         if(m==0xfd82&fl==0){fl=0;off=0;on=1;dw=dw+1;if(dw>3){dw=1;}cd=1;gj=0;j=0;m=0;}/*开机状态*/
  71.   if(on==1&m==0xfd90){yt=~yt;cd=1;j=0;m=0;}/*摇头*/if(dw==0){P31=0;P32=0;P55=0;}
  72.   if(fl==0&dw==1){P31=1;P32=0;P55=0;q=16;}/*慢档*/
  73.   if(fl==0&dw==2){P31=0;P32=1;P55=0;q=17;}/*中档*/
  74.   if(fl==0&dw==3){P31=0;P32=0;P55=1;q=18;}/*快档*/
  75.         if(on==1&m==0xfd88){ds=ds+1800;d0=0;TR0=1;if(ds>28800){ds=0;}cd=1;gj=1;j=0;m=0;}
  76.         /*定时控制函数*//*8.0小时=480分钟=28800秒  999秒=16.65分钟=0.2775小时*/
  77.         if(ds>999){g=19;s=ds/60/6%10;b=ds/60/60;}/*g位显示H,s显示10进制的分钟,b显示小时加小数点*/
  78.         if(ds<999){g=ds%10;s=ds/10%10;b=ds/100%10;/*q=ds/1000%10;*/}/*显示剩余秒数*/
  79.         if(on==1&m==0xfd84){fl++;if(fl>2){fl=0;}zd=0;cd=1;j=0;m=0;}if(fl==0){se=0;}
  80.         /*A类自然风:高速运转10秒,中速运转10秒,低速运转10秒;进入循环*/
  81.         if(fl==1){q=10;if(se>1&se<11){zd=3;}if(se>10&se<21){zd=2;}if(se>20&se<31){zd=1;}if(se>30|se==0){se=1;}TR0=1;}
  82.         /*b类睡眠风:高速转10分钟,中速转30分钟;之后退出睡眠模式,返回长风1档*/
  83.   if(fl==2){q=11;if(se>1&se<600){zd=3;}if(se>600&se<1800){zd=2;}if(se>1800){m=0xfd84;}if(se==0){se=1;}TR0=1;}
  84.         if(zd==1){P31=1;P32=0;P55=0;}/*慢档*/if(zd==2){P31=0;P32=1;P55=0;}/*中档*/if(zd==3){P31=0;P32=0;P55=1;}/*快档*/
  85.         if(m==0xfdc3){cd=~cd;j=0;m=0;}/*彩灯开关,关机后单显示电压,开机后定时和电压切换显示*/
  86.         if(ds!=0&c==0){ET0=1;}/*定时打开时,检测有无红外信号*/if(se!=0&c==0){ET0=1;}/*自动风打开时,检测有无红外信号*/
  87. }
  88. void fmq()/*蜂鸣器*/
  89. {
  90.                 if(off==0&buz>0)
  91.           {        
  92.             buz++;
  93.                   P54=0;        
  94.           }
  95.           if(buz>800)/*延时*/
  96.           {
  97.                   P54=1;        
  98.                 if(m==0xfd81)
  99.                 {
  100.                         off=1;
  101.                         m=0;
  102.                 }
  103.                   buz=0;
  104.           }
  105. }
  106. void main()
  107. {
  108.         P1M0=0xff; P1M1=0; P3M0=0x06; P3M1=0; P5M0=0x30; P5M1=0;/*端口模式*/
  109.         P31=0;P32=0;P33=1;P54=1;P55=0;cd=1;j=0;dw=0;ds=0;gj=0;yt=0;buz=0;/*初始化*/
  110.         d0init()/*定时器0初始化*/;d1init();/*定时器1初始化*/int1init();/*外部中断1初始化*/
  111.         buz=1;fmq();/*上电蜂鸣器响一声*/
  112.         while(1)
  113.         {
  114.                 ircl();
  115.                 kayscan();
  116.                 kzhs();
  117.                 fmq();
  118.         }
  119. }
  120. /*传统51单片机具有5个中断源,中断优先级从高到低依次是:外部中断0(interrupt0)、定时器0(interrupt1)、外部中断1(interrupt2)、定时器1(interrupt3)和串口中断(interrupt4)。*/
  121. void dsq0() interrupt 1
  122. {
  123.         unsigned int ms,tu,tm;
  124.         tu=965;          /*调整微秒,建议:965*/
  125.         tm=99;           /*毫秒调整,建议:99*/
  126.   d0=d0++;         /*每约1微秒加1*/
  127.         if(buz>0)
  128.         {        
  129.           buz++;
  130.                 P54=0;        
  131.   }
  132.         if(buz>800)      /*延时*/
  133.         {
  134.                 P54=1;
  135.                 buz=0;
  136.         }
  137.         if(!P33)         /*检测到红外信号*/
  138.         {
  139.                 ET0=0;         /*返回主程序*/
  140.         }
  141.         if(d0>tu)        /*受红外信号检测影响,建议199*/
  142.         {
  143.                 ms++;          /*每约1000微秒=1毫秒*/
  144.                 d0=0;          /*us清零*/
  145.         }
  146.         if(ms>tm/2)      /*每约0.5秒*/
  147.         {
  148.           sm=0;          /*关闭闪秒*/
  149.         }
  150.         if(ms>tm)        /*每约1000毫秒=1秒 参考值:19*/
  151.         {
  152.                 if(ds>0)                        
  153.      {
  154.                  ds--;         /*定时秒数自减*/
  155.                  }            
  156.                  se++;
  157.                  sm=1;         /*点亮闪秒*/
  158.                 if(gj==1&ds==0)/*允许关机,定时时间到了*/
  159.                 {
  160.                         m=0xfd81;    /*送出关机指令*/
  161.                         gj=0;
  162.                 }
  163.                 ms=0;          /*毫秒清零*/
  164.         }
  165. }
  166. void int1() interrupt 2 /*外部中断1服务函数,低电平触发*//*受遥控中断影响,不够时间处理编码,记录时间不放在这函数*/
  167. {
  168.         unsigned char i;
  169.         j++;                  /*编码位置*/
  170.   if(m==0)              /*如果还没解码正确*/
  171.           {
  172.       for(i=1;i<13;i++) /*未捕获间隔码*/
  173.          {
  174.            r=r<<1;      /*从低位起左移1位*/
  175.            if(ir[i]>70&&ir[i]<125) /*编码为1*/
  176.              {
  177.                      r=r|0x001;/*或1*/
  178.              }
  179.           }
  180.     }
  181.         if(j>12){r=r|0xf000;} /*表示收到符合长度的编码*/
  182.   else{r=0x0000;}       /*干扰清零*/  
  183.         if(r==0xfd81|r==0xfd82|r==0xfd84|r==0xfd88|r==0xfd90|r==0xfdc3|r==0xfda0|r==0xfdc6)
  184.         {
  185.                 m=r;                /*收录合格编码*/
  186.                 buz=1;              /*启动蜂鸣器*/
  187.         }
  188.         else
  189.         {
  190.                 m=0;                /*干扰码清零*/
  191.         }
  192.         if(j>12&m==0){j=0;}   /*如果大于12位了,编码还不正确,就把位置清零,防止下一帧乱码*/
  193. }
  194. void dsqi() interrupt 3 /*定时器1 中断服务函数,每约13微秒中断1次*/{d1++;/*每约13微秒加1*/}
复制代码
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:94031 发表于 2023-5-23 16:09 | 只看该作者
你13微秒中断1次,造成cpu一直不停处理中断,根本没时间干别的,定时器1 应该有一个合理中断时间间隔。
回复

使用道具 举报

板凳
ID:744809 发表于 2023-5-23 17:06 | 只看该作者
1、代码没对齐,风格较差
2、中断中代码过长,可能导致下个中断进来了都没处理完
3、51的栈空间太小,不建议中断太多代码
4、函数名太短,且为拼音首字母,难以理解
5、中断间隔太短了
回复

使用道具 举报

地板
ID:123289 发表于 2023-5-24 11:23 | 只看该作者
不要急于写程序。先规划一下方案。
再出个程序流程图,先走通流程图而后再写程序。
如沙发提出的问题,你如果规划过方案,就不犯。
例如:列出风扇的功能,一个给出实现的方式。切换的方法,条件,检测的方式,显示的方式……。
这此都在事先做规划。至少罗列于EXCEL表中吧。

评分

参与人数 1黑币 +5 收起 理由
yueguang3048 + 5 很给力!

查看全部评分

回复

使用道具 举报

5#
ID:796012 发表于 2023-5-24 12:21 | 只看该作者
123156fsadf 发表于 2023-5-23 17:06
1、代码没对齐,风格较差
2、中断中代码过长,可能导致下个中断进来了都没处理完
3、51的栈空间太小,不 ...

谢谢建议。我这是业余爱好的
回复

使用道具 举报

6#
ID:796012 发表于 2023-5-24 12:21 | 只看该作者
xuyaqi 发表于 2023-5-23 16:09
你13微秒中断1次,造成cpu一直不停处理中断,根本没时间干别的,定时器1 应该有一个合理中断时间间隔。

试了,刚好可以识别红外信号
回复

使用道具 举报

7#
ID:796012 发表于 2023-5-24 12:22 | 只看该作者
yzwzfyz 发表于 2023-5-24 11:23
不要急于写程序。先规划一下方案。
再出个程序流程图,先走通流程图而后再写程序。
如沙发提出的问题,你 ...

嗯嗯。专业的手法就是不一样。
回复

使用道具 举报

8#
ID:526543 发表于 2023-5-24 12:27 | 只看该作者
先给你来一段
#include "STC8G.h"

// 定义红外解码键值
#define KEY_POWER     0xFD81
#define KEY_MODE      0xFD82
#define KEY_WIND      0xFD84
#define KEY_TIMER     0xFD88
#define KEY_SWING     0xFD90
#define KEY_LIGHT     0xFDC3

// 定义数码管段码
unsigned char code SEGMENT[] = {
    0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07,
    0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71,
    0x08, 0x48, 0x49, 0x76
};

// 全局变量
bit fanOn = 0;             // 风扇开关状态
unsigned char fanSpeed = 0; // 风扇速度
bit fanSwing = 0;          // 风扇摇头状态
bit fanLight = 0;          // 风扇彩灯状态
unsigned int fanTimer = 0; // 风扇定时器

// 延时函数
void delayms(unsigned int ms) {
    unsigned int i, j;
    for (i = 0; i < ms; i++) {
        for (j = 0; j < 1000; j++);
    }
}

// 数码管显示函数
void display(unsigned char digit) {
    unsigned char segment = SEGMENT[digit];
    P1 = segment;
}

// 控制风扇函数
void controlFan() {
    // 根据风扇状态进行相应操作
    if (fanOn) {
        // 控制风扇开关
        P3 &= 0xF8;
        P3 |= fanSpeed;
        // 控制风扇摇头
        P1 &= 0xDF;
        P1 |= (fanSwing << 5);
        // 控制风扇彩灯
        P5 &= 0xDF;
        P5 |= (fanLight << 5);
    } else {
        // 关闭风扇
        P3 &= 0xF8;
    }
}

// 外部中断1中断服务函数
void int1() interrupt 2 {
    // 延时一段时间,避免按键抖动
    delayms(10);
    if (P3_2 == 0) { // 检测外部中断1触发
        // 解码键值
        unsigned int keyValue = (P1 << 8) | P0;
        
        // 根据键值执行相应操作
        switch (keyValue) {
            case KEY_POWER:
                fanOn = !fanOn; // 切换风扇开关状态
                break;
            case KEY_MODE:
                fanSpeed++; // 切换风扇速度
                if (fanSpeed > 3) {
                    fanSpeed = 0;
                }
                break;
            case KEY_WIND:
                fan
回复

使用道具 举报

9#
ID:796012 发表于 2023-5-24 16:06 | 只看该作者
123456ZXC1 发表于 2023-5-24 12:27
先给你来一段
#include "STC8G.h"

嗯。还行,有点逻辑性
回复

使用道具 举报

10#
ID:1079725 发表于 2023-5-25 23:36 | 只看该作者
配合原理图调试理清,会好些吧
回复

使用道具 举报

11#
ID:1040201 发表于 2023-5-26 17:06 | 只看该作者
能实现功能就是一大步,其它的慢慢累积,多看、多练再过段时间会头看一下,就会发现很多问题
回复

使用道具 举报

12#
ID:796012 发表于 2023-5-28 09:54 | 只看该作者
liucan2020 发表于 2023-5-26 17:06
能实现功能就是一大步,其它的慢慢累积,多看、多练再过段时间会头看一下,就会发现很多问题

牛逼!这就是成功的奥秘。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表