找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 7732|回复: 27
收起左侧

简述STC15408AS单片机模拟38khz格力空调红外遥控 源程序

  [复制链接]
ID:296975 发表于 2019-8-7 12:06 | 显示全部楼层 |阅读模式
本帖最后由 ccccc5321c 于 2019-8-9 00:42 编辑
用单片机做了个自动切换空调模式的电路,就顺便简化了下程序共大家参考:
1、红外解码
首先你需要一个红外分析的基本工具 http://www.360doc.com/content/15/0416/18/54462_463694797.shtml
刚开始毫无头绪,摸索之后发现红外分析很重要,虽然网上有些讲原理的帖子,但都有些漏洞,而且在调整高低电平间的延迟时,红外信号的波形是必须有的。
再给一个格力空调的原理讲解 https://blog.csdn.net/dddxxxx/article/details/53033748
我的遥控器型号为YB0FB2,所以说验证码的计算有些不一样:模式(低3位逆序)+温度(低4位逆序)+左右(1位)+换气(1位)-开关(左移3位)+12,得到的二进制数据取低四位取反
定时部分有2段67位码,前段测试家里的柜机能用,挂机必须2段相加,第二段验证码部分太复杂,没分析出来。不过我设想可以把48个验证码的差值找出来列成数组的形式来编码(值得注意的是验证码只有低4位,屏蔽掉的高4位要加上16的整数倍)

2、程序
网络上能搜索到不少相关资源,不过不测试你还真不知道哪些是骗分的,有些甚至连38khz载波都没有就发出来了。不多说了,比较简单,因为我的板子只做了3个按键和2个led,功能只做了模式切换和温度+-,不过最核心复杂的部分我已经做出来了。如果你的单片机是STCW408AS频率调到22.1184MHZ,或许你可以直接使用。当然啦如果不是,你需要先完成第一步,然后根据波形调整延迟到准确值(简单漫长),最后建议用高频率速度快的单片机,因为编码延迟要求比较精确。定时部分我用不上也有点复杂,哪位高人做出来记得分享。
附上验证码计算的excel和我得keil程序
附件默认扣分,不会设置,所以来个百度云:
游客,本帖隐藏的内容需要积分高于 1 才可浏览,您当前积分为 0

全部资料51hei下载地址:
38khz红外模拟.rar (46.39 KB, 下载次数: 93)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:296975 发表于 2020-12-10 17:12 | 显示全部楼层
统一回复一下吧。今天找资料 无意间又来了,看到调试不成功的,于是我又把代码编译测试了一下。结果是可以控制空调的。至于调试失败,我能想到的有几点:
1、编程的时候要设置IRC频率22.1184Mhz,并且注意编程的时候频率有没有设置成功。我的测试版波特率选太大的时候频率设置会失败。
2.没有载波?,载波是按键触发函数,打开定时器中断程序发出的,我想到的是应该检查红外收发电路。
3、电路图?我用洞洞板做的,没画。几个相关引脚的是这样的。芯片16脚输出,串1k电阻用8050三极管驱动5mm940红外三极管发射,14脚为模式切换开关,13、10脚为温度+-按键(都是拉低触发),1脚LED串1个适当电阻,或则接三极管驱动led。
4.不同批次的单片机可能有差异,代码里的HighCode()和LowCode(),也就是逻辑1和0里的延迟数值就需要调整。这就需要从第1步开始,用空调原装遥控器的波形对比做微调。
5、这玩意儿纯属分享,而且本人很少逛论坛说以说回复基本随缘,或者说基本不回复。相信只要仔细一定能调试成功

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:296975 发表于 2019-8-7 12:36 | 显示全部楼层
本帖最后由 ccccc5321c 于 2019-8-8 21:33 编辑

#include "STC15W408AS.h"
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
uchar c_code[9]={0x98,0x70,0x04,0x8a,0x40,0x08,0x80,0x00,0x40};
uchar mode_code[5]={0x00,0x80,0x40,0xc0,0x20};
short lev,led_delay,key_delay,mode;
sbit key1=P3^7;
sbit key2=P3^6;
sbit key3=P3^1;
sbit out=P1^1;
sbit led1=P1^2;
void Delay5us(int t)        //@22.1184MHz
{
    unsigned char i;
    while(t--)
    {
        _nop_();
        i = 25;
        while (--i);
    }
}
void Delay100us(int t)        //@22.1184MHz
{
    unsigned char i, j;
    while(t--){
        i = 3;
        j = 35;
        do
        {
            while (--j);
        } while (--i);
    }
}
void Delay1ms(int t)        //@22.1184MHz
{
    uchar i, j;
    while(t--){
        _nop_();
        _nop_();
        i = 22;
        j = 128;
        do
        {
            while (--j);
        } while (--i);
    }
}
void HighCode()//逻辑1
{
    lev=1;
    Delay5us(44);
    lev=0;
    Delay5us(122);
}
void LowCode()//逻辑0
{
    lev=1;
    Delay5us(44);
    lev=0;
    Delay5us(44);
}
void StartCode()
{
    lev=1;
    Delay100us(78);
    lev=0;
    Delay100us(40);
}
void EndCode()
{
    lev=1;
    Delay5us(44);
    lev=0;
}
void ConnectCode()
{
    lev=1;
    Delay5us(44);
    lev=0;
    Delay1ms(18);
}
void SendCode()
{
    int i,j;
    uchar c_data;
    IE2 |=0xAF;//打开定时器2中断(38khz载波)
    StartCode();//起始码
    for(i=1;i<5;i++)//1-32位
    {   
        c_data=c_code[i-1];
        for(j =1;j<9;j++)
        {
            if(c_data&0x80)
                HighCode();
            else
                LowCode();
            c_data=c_data<<1;
        }
    }
    c_data=c_code[4];
    for(j =1;j<4;j++)//33-35位
    {
        if(c_data&0x80)
            HighCode();
        else
            LowCode();
        c_data=c_data<<1;
    }
    ConnectCode();//连接部分
    for(j =4;j<9;j++)//36-40位
    {
        if(c_data&0x80)
            HighCode();
        else
            LowCode();
        c_data=c_data<<1;
    }
    for(i=6;i<9;i++)//41-64位
    {   
        c_data=c_code[i-1];
        for(j =1;j<9;j++)
        {
            if(c_data&0x80)
                HighCode();
            else
                LowCode();
            c_data=c_data<<1;
        }
    }
    c_data=c_code[8];
    for(j =1;j<4;j++)//65-67位
    {
        if(c_data&0x80)
            HighCode();
        else
            LowCode();
        c_data=c_data<<1;
    }
    EndCode();//结尾
    IE2 |=0x04;//发送完成关闭定时器2(38khz载波)   
}
void Timer2Init(void)        //13微秒@22.1184MHz
{   
    EA=1;            //开总中断
    AUXR |= 0x04;        //定时器时钟1T模式
    T2L = 0xE0;        //设置定时初值
    T2H = 0xFE;        //设置定时初值
    AUXR |= 0x10;        //定时器2开始计时
}
void Timer2(void) interrupt 12
{
    if(lev)    //每13us触发生成38khz载波。将数据调制到载波,lev高电平发送载波,lev低电平时空闲即完成调制发送
        out=~out;
    else
        out=0;            
}
uchar reverse(uchar dat)//8位逆序
{
    dat=(dat<<4)|(dat>>4);
    dat=((dat << 2)&0xcc)|((dat>>2)&0x33);
    dat=((dat << 1)&0xaa)|((dat>>1)&0x55);
    return dat;
}
void CodeCheck(void)//校验码计算
{//注:模式(低3位逆序)+温度(4位逆序)+左右(1位)+换气(1位)-开关(左移3位)+定时数据(低4位逆序)+12,得到的二进制数据取低四位取反
    uchar ckcode;
    ckcode=(reverse(c_code[0])&0x07)+reverse(c_code[1])+(c_code[4]&0x01)+(c_code[3]>>7)-((c_code[0]>>1)&0x08)+reverse(c_code[2]&0xf0)+12;
    ckcode = reverse(ckcode);
     c_code[7]=(c_code[7]&0xfe)+(ckcode>>7);
    c_code[8]=(ckcode<<1)&0xe0;//共67位,后5位用不到
}
void ModeChange()//改变模式和校验码
{
    if(mode<4)
        mode++;
    else
        mode=0;
    c_code[0]=(c_code[0]&0x1f)+mode_code[mode];
    CodeCheck();//重算校验码
    SendCode();//发送
}
void TempAdd()
{   
    uchar temputer=reverse(c_code[1]&0xf0);
    if(temputer<14)
    {
        temputer=temputer+1;
        c_code[1]=(c_code[1]&0x0f)+(reverse(temputer)&0xf0);
    }
    CodeCheck();
    SendCode();
}
void TempReduce()
{   
    uchar temputer=reverse(c_code[1]&0xf0);
    if(temputer>0)
    {
        temputer=temputer-1;
        c_code[1]=(c_code[1]&0x0f)+(reverse(temputer)&0xf0);
    }
    CodeCheck();
    SendCode();
}
void LedControl()
{
    if(led_delay==0)
    led1=0;           
    else
    {
    led_delay--;
    led1=~led1;
    }
}
void KeyScan()
{
    if(key_delay>=0)
        key_delay--;
    else
    {
        if(key1==0)//改变模式
        {
            ModeChange();
            key_delay=1;//按键间隔时间及消抖            
            led_delay=15;//按键后LED短暂闪烁
        }
        else if(key2==0)//温度+
        {
            TempAdd();
            key_delay=1;//按键间隔时间及消抖                        
            led_delay=15;//按键后LED短暂闪烁
        }
        else if(key3==0)//温度-
        {
            TempReduce();   
            key_delay=1;//按键间隔时间及消抖                        
            led_delay=15;//按键后LED短暂闪烁
        }
    }        
}
void init()
{
    lev=0;//电平信号变量
    led_delay=15;//led灯初始闪烁时间
    key_delay=0;//按键间隔
    out=0;//红外输出默认置0
    mode=0;//默认自动模式
    P1M1=0x00;P1M0=0x06;//P1 1、2 强推挽输出
    P3M1=0x00;P3M0=0x00;//p3 1、6、7标准双向
    led1=0;
    key1=1;key2=1;key3=1;
}
void main()
{
    int i=0;
    init();
    Timer2Init();
    while(1)
    {   
        Delay1ms(100);
        KeyScan();        
        LedControl();//开机后LED短暂闪烁
    }
}

回复

使用道具 举报

ID:386381 发表于 2019-8-8 13:58 来自手机 | 显示全部楼层
谢谢楼主分享,好资料,51黑有你更精彩!!!
回复

使用道具 举报

ID:385637 发表于 2019-8-8 17:30 | 显示全部楼层
谢谢楼主分享,我刚好用的就是STC15W408AS这款芯片
回复

使用道具 举报

ID:128463 发表于 2019-8-9 17:06 | 显示全部楼层
谢谢楼主分享!!
回复

使用道具 举报

ID:371958 发表于 2019-8-23 22:25 | 显示全部楼层
谢谢楼主分享!!
回复

使用道具 举报

ID:495323 发表于 2019-10-19 03:03 来自手机 | 显示全部楼层
请问下,发射红外的模块是什么?
回复

使用道具 举报

ID:663108 发表于 2019-12-13 10:56 | 显示全部楼层
用PWM生成载波是不是更方便些?
回复

使用道具 举报

ID:398219 发表于 2020-1-15 17:59 | 显示全部楼层
我调试后没成功,你们有成功的吗
回复

使用道具 举报

ID:684349 发表于 2020-2-4 16:58 | 显示全部楼层
你好,大佬 我想问下您用的芯片STCW408AS是STC15W408AS的全称吗?谢谢
回复

使用道具 举报

ID:72652 发表于 2020-8-5 14:20 | 显示全部楼层
我用VS1838做接收,用示波器和逻辑分析仪都没有看到38K载波。
回复

使用道具 举报

ID:296975 发表于 2020-12-10 14:06 | 显示全部楼层
本帖最后由 ccccc5321c 于 2020-12-10 15:44 编辑
licong 发表于 2020-8-5 14:20
我用VS1838做接收,用示波器和逻辑分析仪都没有看到38K载波。
我想你可能是没细看代码,载波是在按下按键的时候打卡定时器中断,然后在中断的执行程中间断输出高低电平来发送的,如果你看明白代码,那么你就应该知道问题出在哪里。
我觉得你应该先检查下发射电路,我没有那么些仪器,用的只是一个洞洞板做的简单的电路通过电脑上的音频分析软件看的波形,接收管用的和你一样。发射电路我用接的是一个SS8050和1k电阻驱动5mm940红外发射管

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:296975 发表于 2020-12-10 14:07 | 显示全部楼层
淮风烟火 发表于 2020-2-4 16:58
你好,大佬 我想问下您用的芯片STCW408AS是STC15W408AS的全称吗?谢谢

是的,某一个宝上最便宜的那个
回复

使用道具 举报

ID:296975 发表于 2020-12-10 14:11 | 显示全部楼层
efan0 发表于 2019-12-13 10:56
用PWM生成载波是不是更方便些?

我没想到和pwm能有啥关系 不是发送0 和 1吗
回复

使用道具 举报

ID:296975 发表于 2020-12-10 14:12 | 显示全部楼层
有心插花花木兰 发表于 2019-10-19 03:03
请问下,发射红外的模块是什么?

纠正一下 发射用的时候5mm 940 二极管 也就是遥控器上用的比较多的那个型号 某一个宝很便宜的
回复

使用道具 举报

ID:296975 发表于 2020-12-10 14:13 | 显示全部楼层
有心插花花木兰 发表于 2019-10-19 03:03
请问下,发射红外的模块是什么?

5mm 940 红外LED 某一个宝上 很便宜 和遥控器上的一样
对了 我觉得有必要说一下 接了一个三极管来驱动它

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:296975 发表于 2020-12-10 14:16 | 显示全部楼层
本帖最后由 ccccc5321c 于 2020-12-10 15:39 编辑
herui2128 发表于 2020-1-15 17:59
我调试后没成功,你们有成功的吗

我看到好几个都没成功,代码都是我之前自己用过的 我想你们应该检查一下电路,我的电路比较简单 就没发图,发射管我用了一个8050 接一个1k电阻 驱动 5mm 940红外发射管

我想到还有一种可能 单片机的频率有差异 导致延迟函数不准确,波形也就不准确

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:296975 发表于 2020-12-10 14:41 | 显示全部楼层
淮风烟火 发表于 2020-2-4 16:58
你好,大佬 我想问下您用的芯片STCW408AS是STC15W408AS的全称吗?谢谢

是全称 很便宜的那款
回复

使用道具 举报

ID:819974 发表于 2020-12-15 13:01 | 显示全部楼层
能问一下如果我要发送开/关,安照表格是不是只要在数据码第四位置1或置0
回复

使用道具 举报

ID:860558 发表于 2020-12-15 14:28 | 显示全部楼层
写的好!
回复

使用道具 举报

ID:818895 发表于 2021-1-17 23:09 | 显示全部楼层
格力空调可以用这样的遥控编程啊。
回复

使用道具 举报

ID:201160 发表于 2021-9-26 23:30 | 显示全部楼层

谢谢楼主分享,好资料,51黑有你更精彩!!!
回复

使用道具 举报

ID:136485 发表于 2021-9-27 08:50 | 显示全部楼层
刚好我们办公室的是格力空调下载下来学习测试下
回复

使用道具 举报

ID:965189 发表于 2021-10-4 20:44 | 显示全部楼层
看看能不能利用。
回复

使用道具 举报

ID:1109276 发表于 2024-6-17 13:19 | 显示全部楼层
真的能用。不过怎么关机呢?
回复

使用道具 举报

ID:1109276 发表于 2024-6-18 09:39 | 显示全部楼层
doodigen 发表于 2024-6-17 13:19
真的能用。不过怎么关机呢?

c_code[0]=(c_code[0]&0x0f)+mode_code[mode];
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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