[DIY制作] 给小功率功放加装遥控装置

[复制链接] 查看: 7196|回复: 175

13

主题

0

好友

575

积分
     

职业侠客 当前离线

Rank: 5Rank: 5

UID
3264
帖子
496
精华
0
经验
575 点
金钱
512 ¥
注册时间
2005-3-5
 楼主| 发表于 2024-2-29 10:16 | 显示全部楼层
eeprom.h代码,是从stc15的说明书中摘抄的,如果想深入了解,请参考stc的说明书,非常详细。

#ifndef __EEPROM_H__
#define __EEPROM_H__

#define CMD_IDLE    0               //空闲模式
#define CMD_READ    1               //IAP字节读命令
#define CMD_PROGRAM 2               //IAP字节编程命令
#define CMD_ERASE   3               //IAP扇区擦除命令

//#define ENABLE_IAP 0x80           //if SYSCLK<30MHz
//#define ENABLE_IAP 0x81           //if SYSCLK<24MHz
//#define ENABLE_IAP 0x82           //if SYSCLK<20MHz
#define ENABLE_IAP 0x83                   //if SYSCLK<12MHz
//#define ENABLE_IAP 0x84           //if SYSCLK<6MHz
//#define ENABLE_IAP 0x85           //if SYSCLK<3MHz
//#define ENABLE_IAP 0x86           //if SYSCLK<2MHz
//#define ENABLE_IAP 0x87           //if SYSCLK<1MHz

//读写地址
#define IAP_ADDRESS 0x0000

/*----------------------------
关闭IAP
----------------------------*/
void IapIdle()
{
    IAP_CONTR = 0;                  //关闭IAP功能
    IAP_CMD = 0;                    //清除命令寄存器
    IAP_TRIG = 0;                   //清除触发寄存器
    IAP_ADDRH = 0x80;               //将地址设置到非IAP区域
    IAP_ADDRL = 0;
}

/*----------------------------
从ISP/IAP/EEPROM区域读取一字节
----------------------------*/
u8 IapReadByte(u16 addr)
{
    u8 dat;                       //数据缓冲区

    IAP_CONTR = ENABLE_IAP;         //使能IAP
    IAP_CMD = CMD_READ;             //设置IAP命令
    IAP_ADDRL = addr;               //设置IAP低地址
    IAP_ADDRH = addr >> 8;          //设置IAP高地址
    IAP_TRIG = 0x5a;                //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                //写触发命令(0xa5)
    _nop_();                        //等待ISP/IAP/EEPROM操作完成
    dat = IAP_DATA;                 //读ISP/IAP/EEPROM数据
    IapIdle();                      //关闭IAP功能

    return dat;                     //返回
}

/*----------------------------
写一字节数据到ISP/IAP/EEPROM区域
----------------------------*/
void IapProgramByte(u16 addr, u8 dat)
{
    IAP_CONTR = ENABLE_IAP;         //使能IAP
    IAP_CMD = CMD_PROGRAM;          //设置IAP命令
    IAP_ADDRL = addr;               //设置IAP低地址
    IAP_ADDRH = addr >> 8;          //设置IAP高地址
    IAP_DATA = dat;                 //写ISP/IAP/EEPROM数据
    IAP_TRIG = 0x5a;                //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                //写触发命令(0xa5)
    _nop_();                        //等待ISP/IAP/EEPROM操作完成
    IapIdle();
}

/*----------------------------
扇区擦除
----------------------------*/
void IapEraseSector(u16 addr)
{
    IAP_CONTR = ENABLE_IAP;         //使能IAP
    IAP_CMD = CMD_ERASE;            //设置IAP命令
    IAP_ADDRL = addr;               //设置IAP低地址
    IAP_ADDRH = addr >> 8;          //设置IAP高地址
    IAP_TRIG = 0x5a;                //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                //写触发命令(0xa5)
    _nop_();                        //等待ISP/IAP/EEPROM操作完成
    IapIdle();
}

#endif

13

主题

0

好友

575

积分
     

职业侠客 当前离线

Rank: 5Rank: 5

UID
3264
帖子
496
精华
0
经验
575 点
金钱
512 ¥
注册时间
2005-3-5
 楼主| 发表于 2024-2-29 10:18 | 显示全部楼层
ir.h代码,红外解码原理请参考网上相关内容

#ifndef _IR_H_
#define _IR_H_

//红外信号输入,INT0,P3.2,设置为下沿触发

sbit IRD=P3^2;                                                                        //红外接收检测端口,外部中断0
bit b_irflag=0;                                                                        //接收到数据的标志
u8 c_ircode[4];                                                                        //存放用户码、用户码反码、键码、键码反码

void ConfigInfrared()                                                //配置红外解码,使用T0计时,外部中断0输入信号
{
        AUXR=0x15;
        TH0=0;                                                                                                //T0高位清零
        TL0=0;                                                                                                //T0低位清零
        TMOD&=0xf0;                                                                                //清零T0计数
        TMOD|=0x01;                                                                                //设置T0工作方式1,16位定时器(非重装载)
        TR0=0;                                                                                                //在没有红外信号之前,先关闭T0
        ET0=0;                                                                                                //T0溢出中断允许位:0-禁止T0中断,1-允许T0中断
        IT0=1;                                                                                                //设置外部中断0触发方式:下降沿
        EX0=1;                                                                                                //开启外部中断0
        IRD=1;                                                                                                //初始化时,IRD置高电平
}

u16 GetHighTime()                                                                //获取IRD红外检测引脚高电平时间(空闲时间)
{
        TH0=0;                                                                                                //清零T0计数
        TL0=0;                                                                                                //
        TR0=1;                                                                                                //开启T0计数
        while(IRD)                                                                                //持续高电平
        {
                if(TH0>0x23)
                {
                        break;                                                                                //中止退出
                }
        }
        TR0=0;                                                                                                //停止计数
        return (TH0*256+TL0);                                        //返回高电平计数值
}

u16 GetLowTime()                                                                //获取IRD红外引脚低电平时间(载波时间)
{
        TH0=0;                                                                                                //清零T0计数
        TL0=0;                                                                                                //
        TR0=1;                                                                                                //开始计数
        while(!IRD)                                                                                //持续低电平
        {
                if(TH0>0x23)                                                                
                {
                        break;                                                                                //终止退出
                }
        }
        TR0=0;                                                                                                //停止计数
        return (TH0*256+TL0);                                        //返回低电平计数值
}

void Int0_Routine(void) interrupt 0                        //外部中断0,接收到红外信号触发
{
        u8 byte;                                                                                                                        //接收数据(临时)
        u8 i,j;                                                                                                                                //执行4x8循环的变量
        u16 time;                                                                                                                        //脉冲时间

        EX0=0;                                                                                                                                //暂时关闭外部中断0,等待程序执行完成
       
        time=GetLowTime();                                                                                //获取低电平时间
        if(time<4250||time>4750)                                                        //引导码低电平是9ms,这里取8.5ms-9.5ms
        {
                                                                                                                                                                //如果在这个范围之外,则判断为误码
                IE0=0;                                                                                                                        //清除外部中断0的中断标志,为了下一次再进入中断
                EX0=1;
                return;                                                                                                                        //退出中断
        }
                                                                                                                                                                //否则,则判断引导码9ms低电平正常
        time=GetHighTime();                                                                                //获取高电平时间
        if(time<2000||time>2500)                                                        //引导码高电平时间为4.5ms,这里取4-5ms
        {
                                                                                                                                                                //如果在这个范围之外,则判断为误码
                IE0=0;                                                                                                                        //清零中断标志
                EX0=1;
                return;                                                                                                                        //退出中断
        }
                                                                                                                                                                //否则,则判断引导码4.5ms高电平正常
                                                                                                                                                                //开始接收用户码和键码等
        for(i=0;i<4;i++)                                                                                        //循环接收4个字节的编码
        {
                for(j=0;j<8;j++)                                                                                //每个字节的8位
                {
                        time=GetLowTime();                                                                //获取低电平时间
                        if(time<230||time>330)                                                //判断是否为560us载波,这里取460us-660us
                        {
                                IE0=0;                                                                                                        //不在这个范围内,则判断为误码,清零中断标志
                                EX0=1;
                                return;                                                                                                        //退出中断
                        }
                                                                                                                                                                //是560us载波
                        time=GetHighTime();                                                                //获取高电平时间
                        if(time>230&&time<330)                                                //判断高电平时长是否560us
                        {
                                                                                                                                                                //如果是,则判断接收到的位(bit)='0'
                                byte>>=1;                                                                                                //低位在前,移入一位0
                        }
                        else if(time>650&&time<900)                                //判断高电平时长是否1680us,这里取值1300-1800us
                        {
                                                                                                                                                                //如果是,则判断接收到的bit='1'
                                byte>>=1;                                                                                                //移入一位
                                byte|=0x80;                                                                                        //移入的一位置1
                        }
                        else
                        {
                                                                                                                                                                //否则,判断接收到的是误码
                                IE0=0;                                                                                                        //清零中断标志
                                EX0=1;
                                return;                                                                                                        //退出中断
                        }
                }
                c_ircode[i]=byte;
        }
        /*------------------------------------------------------------
        【天猫魔盒M16遥控器】机器码:0x00,电源开关:0x57,
         静音:0x8a,音量-:0x5d,音量+:0xff,主页:0x47,返回:0x4f,菜单:0x16
         上:0x43,下:0x0a,左:0x06,右:0x0e,中:0x02
        ------------------------------------------------------------*/
        if(c_ircode[0]==0x00)                                        //比对机器码
        {
                b_irflag=1;
        }                                                                               
        IE0=0;                                                                                                //退出中断时清除中断标志
        EX0=1;                                                                                                //重新开启外部中断0
}

#endif

13

主题

0

好友

575

积分
     

职业侠客 当前离线

Rank: 5Rank: 5

UID
3264
帖子
496
精华
0
经验
575 点
金钱
512 ¥
注册时间
2005-3-5
 楼主| 发表于 2024-2-29 10:19 | 显示全部楼层
map1.h代码:

#ifndef __MAP1_H__
#define __MAP1_H__

//========================================================================
// 函数: void delay_ms(u16 ms)
// 描述: 延时函数。
// 参数: ms,要延时的ms数, 自动适应主时钟.
// 返回: none.
// 版本: VER1.0
// 日期: 2013-4-1
// 备注:
//========================================================================
void delay_ms(u16 ms)
{
         u16 i;
         do{
                        i=FOSC/10000;
                        while(--i);   //10T per loop
         }while(--ms);
}

//LED闪烁一下,表示接收到遥控信号
void Led_shanshuo()
{
        LED1=1;
        delay_ms(20);
        LED1=0;
}
       
//开机
void Kaiji()
{
        u8 y;
        LED1=0;
        delay_ms(20);
        LED1=1;
        J_power=0;                                                                                                                                        //打开主电源
        delay_ms(200);
        c_vol=IapReadByte(IAP_ADDRESS);                                                        //读取音量值
        if(c_vol==0x00||c_vol==0xff)c_vol=0x7a;                        //如果读取到的音量值有误,则设为适中音量值0x7a(-35dB)
        if(c_vol>0x8e)c_vol=0x8e;                                                                                //如果上次保存的音量值大于0x8e(-25dB),则开机音量值设为0x8e
        delay_ms(100);
        y=IapReadByte(IAP_ADDRESS+1);                                                                //读取音源值
        if(y==0x00){J_yinyuan=0;}else{J_yinyuan=1;}        //切换音源
        delay_ms(1000);                                                                                                                        //延时1000毫秒,等待主控板、功放板上电稳定
        J_shuchu=0;                                                                                                                                        //音频输出OK
        Vol_danchu();                                                                                                                                //音量淡出
        b_kaiji=1;                                                                                                                                        //开机标识
        LED1=0;
}

//关机
void Guanji()
{
        u8 y;
        Led_shanshuo();
        IapEraseSector(IAP_ADDRESS);//擦除扇区
        delay_ms(100);
        IapProgramByte(IAP_ADDRESS,c_vol);//写音量值
        delay_ms(100);
        if(J_yinyuan==1){y=0x01;}else{y=0x00;}
        IapProgramByte(IAP_ADDRESS+1,y);//写音源值
        delay_ms(100);
        Vol_danru();
        J_shuchu=1;
        J_yinyuan=1;
        J_power=1;
        b_kaiji=0;
        b_ledhuxi=0;
        LED1=1;
}

//红外信号控制
void Ir_kongzhi()
{
        EX0=0;
        b_irflag=0;
        switch(c_ircode[2])                            //判断红外遥控码值
        {
                case 0x57:                                                                //电源开关
                        if(b_kaiji){Guanji();}else{Kaiji();}
                        break;                               
                case 0x8a:                                                                //静音
                        if(b_kaiji){Led_shanshuo();Vol_mute();}
                        break;                               
                case 0x5d:                                                                //按键-
                        if(b_kaiji&&b_jingyin==0){Vol_down();Led_shanshuo();}
                        break;       
                case 0xff:                                                                //按键+
                        if(b_kaiji&&b_jingyin==0){Vol_up();Led_shanshuo();}
                        break;       
                case 0x16:                                                                //切换音源
                        if(b_kaiji){J_yinyuan=~J_yinyuan;Led_shanshuo();}
                        break;                 
                default:
                        break;
        }
        EX0=1;
}

#endif

13

主题

0

好友

575

积分
     

职业侠客 当前离线

Rank: 5Rank: 5

UID
3264
帖子
496
精华
0
经验
575 点
金钱
512 ¥
注册时间
2005-3-5
 楼主| 发表于 2024-2-29 10:23 | 显示全部楼层
hex文件,大小为3477字节,已通过stc-isp写入单片机,单片机工作频率设为6MHz



代码02.PNG
代码03.PNG

gfyk1.rar

1.59 KB, 下载次数: 36

15

主题

3

好友

828

积分

职业侠客 当前离线

Rank: 5Rank: 5

UID
880770
帖子
846
精华
0
经验
828 点
金钱
800 ¥
注册时间
2020-7-14
发表于 2024-2-29 10:53 | 显示全部楼层
向无私分享者致敬!

15

主题

3

好友

828

积分

职业侠客 当前离线

Rank: 5Rank: 5

UID
880770
帖子
846
精华
0
经验
828 点
金钱
800 ¥
注册时间
2020-7-14
发表于 2024-2-29 11:27 | 显示全部楼层
mapeng 发表于 2024-2-29 10:12
ec11.h代码:

#ifndef __EC11_H__

直到看完后面的,才明白ec11这里的0xff是按键+、0x5d是按键-、0x57是电源开关 选择语句的值

13

主题

0

好友

575

积分
     

职业侠客 当前离线

Rank: 5Rank: 5

UID
3264
帖子
496
精华
0
经验
575 点
金钱
512 ¥
注册时间
2005-3-5
 楼主| 发表于 2024-2-29 15:30 | 显示全部楼层
zhaojunsong9986 发表于 2024-2-29 11:27
直到看完后面的,才明白ec11这里的0xff是按键+、0x5d是按键-、0x57是电源开关 选择语句的值

是的,本来按照更符合逻辑的方法,EC11最好写独立的代码,但是STC15W204S的程序空间才4K字节,当前HEX文件已3.39K,就把EC11操作的代码与红外操作代码合并了。

7

主题

0

好友

128

积分

论坛游民 当前离线

Rank: 3Rank: 3

UID
447576
帖子
163
精华
0
经验
128 点
金钱
94 ¥
注册时间
2011-11-30
发表于 2024-2-29 19:37 | 显示全部楼层
我也做过用新唐的003MCU加上NJW1194音量芯片,蓝牙芯片用杰里的AC6905A,还用数码管做显示,MCU和蓝牙的程序都是自己写的。

15

主题

3

好友

828

积分

职业侠客 当前离线

Rank: 5Rank: 5

UID
880770
帖子
846
精华
0
经验
828 点
金钱
800 ¥
注册时间
2020-7-14
发表于 2024-2-29 23:22 来自手机端 | 显示全部楼层
qjy822 发表于 2024-2-29 19:37
我也做过用新唐的003MCU加上NJW1194音量芯片,蓝牙芯片用杰里的AC6905A,还用数码管做显示,MCU和蓝牙的程 ...

可否把数码管显示的代码分享学习下。

0

主题

0

好友

356

积分
     

业余侠客 当前离线

Rank: 4

UID
422782
帖子
375
精华
0
经验
356 点
金钱
336 ¥
注册时间
2012-3-4
发表于 2024-2-29 23:52 | 显示全部楼层
zhaojunsong9986 发表于 2024-2-29 23:22
可否把数码管显示的代码分享学习下。

同问,请楼主分享数码管显示的代码学习下。

7

主题

0

好友

128

积分

论坛游民 当前离线

Rank: 3Rank: 3

UID
447576
帖子
163
精华
0
经验
128 点
金钱
94 ¥
注册时间
2011-11-30
发表于 2024-3-1 17:04 | 显示全部楼层
zhaojunsong9986 发表于 2024-2-29 23:22
可否把数码管显示的代码分享学习下。

我的显示是加了显示驱动芯片FD650的,应该参考意义不大!

52

主题

4

好友

1万

积分

青铜剑侠 当前离线

Rank: 8Rank: 8

UID
800669
帖子
12893
精华
0
经验
12892 点
金钱
12771 ¥
注册时间
2015-9-21
发表于 2024-3-1 20:32 | 显示全部楼层
高手,估计LZ没花几天就编写玩了。

如果能上示波器就更牛了,不过只有极少数有。毕竟意义不会大

15

主题

3

好友

828

积分

职业侠客 当前离线

Rank: 5Rank: 5

UID
880770
帖子
846
精华
0
经验
828 点
金钱
800 ¥
注册时间
2020-7-14
发表于 2024-3-2 00:30 来自手机端 | 显示全部楼层
qjy822 发表于 2024-3-1 17:04
我的显示是加了显示驱动芯片FD650的,应该参考意义不大!

数码管用驱动,可减少对单片机输出口数量要求,愿意共享很好的

13

主题

0

好友

575

积分
     

职业侠客 当前离线

Rank: 5Rank: 5

UID
3264
帖子
496
精华
0
经验
575 点
金钱
512 ¥
注册时间
2005-3-5
 楼主| 发表于 2024-3-2 21:29 | 显示全部楼层
qjy822 发表于 2024-2-29 19:37
我也做过用新唐的003MCU加上NJW1194音量芯片,蓝牙芯片用杰里的AC6905A,还用数码管做显示,MCU和蓝牙的程 ...

请问NJW1194好驱动吗?音质也不错吧

7

主题

0

好友

128

积分

论坛游民 当前离线

Rank: 3Rank: 3

UID
447576
帖子
163
精华
0
经验
128 点
金钱
94 ¥
注册时间
2011-11-30
发表于 2024-3-5 15:11 | 显示全部楼层
zhaojunsong9986 发表于 2024-3-2 00:30
数码管用驱动,可减少对单片机输出口数量要求,愿意共享很好的

这个是FD650的显示驱动。

FD650.rar

3.4 KB, 下载次数: 15

7

主题

0

好友

128

积分

论坛游民 当前离线

Rank: 3Rank: 3

UID
447576
帖子
163
精华
0
经验
128 点
金钱
94 ¥
注册时间
2011-11-30
发表于 2024-3-5 15:12 | 显示全部楼层
mapeng 发表于 2024-3-2 21:29
请问NJW1194好驱动吗?音质也不错吧

NJW1194好驱动的,音质也还好吧

15

主题

3

好友

828

积分

职业侠客 当前离线

Rank: 5Rank: 5

UID
880770
帖子
846
精华
0
经验
828 点
金钱
800 ¥
注册时间
2020-7-14
发表于 2024-3-5 17:18 | 显示全部楼层
qjy822 发表于 2024-3-5 15:11
这个是FD650的显示驱动。

感谢分享!

13

主题

0

好友

575

积分
     

职业侠客 当前离线

Rank: 5Rank: 5

UID
3264
帖子
496
精华
0
经验
575 点
金钱
512 ¥
注册时间
2005-3-5
 楼主| 发表于 2024-3-18 09:36 | 显示全部楼层
抱歉,近段时间有事耽搁了,继续更新...

13

主题

0

好友

575

积分
     

职业侠客 当前离线

Rank: 5Rank: 5

UID
3264
帖子
496
精华
0
经验
575 点
金钱
512 ¥
注册时间
2005-3-5
 楼主| 发表于 2024-3-18 09:41 | 显示全部楼层
购买的机箱到了,大小为240(宽)x90(高)x271(深),内部大小为200(宽)x82(高)x260(深),两侧的散热器虽然不大,但散热器基板为7mm,还是比较厚的。

机箱01.jpg
机箱02.jpg

13

主题

0

好友

575

积分
     

职业侠客 当前离线

Rank: 5Rank: 5

UID
3264
帖子
496
精华
0
经验
575 点
金钱
512 ¥
注册时间
2005-3-5
 楼主| 发表于 2024-3-18 09:48 | 显示全部楼层
PCB安装前再测试一下,不能正常出声,经过检查,发现1个稳压IC安装时拿错了,本来应该为79L05,但是安装成了78L09,更换后声音正常。
测试01.jpg
测试02.jpg
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Powered by Discuz! X3.4

© 2001-2012 Comsenz Inc.

返回顶部