最好的电子音响科技diy制作网站

haoDIY_音响电子电脑科技DIY小制作发明

当前位置: 主页 > 音响DIY > 功放DIY > 前级DIY >

单片机的应用例子--多功能红外线遥控前级

时间:2012-10-04 16:08来源:hifidiy.net论坛 作者:JiangWZ 点击:
#define anti 0x0E; // 左声道反相 mode 按键 #define agc 0x1C; // 自动音量 audio 按键 #define off_tmr 0x49; // 自动关机 timer 按键 请注意接收管输出必须接到有下降沿中断功能的 I/O 引脚, 附件是俺目前正在
打算设计一台单片机控制的红外线遥控前级

设计构想如下:

直流化的设计,完全没有交藕电容,即使音源带有数十毫伏的直流也能保证输出端直流电压接近零。
模拟开关芯片选择输入信号,最多八组二声道音源。
平衡或非平衡输入缓冲级。
音量控制采用12位元带反相功能的四象限乘法(four quadrant multiplication) 数字/模拟转换器 DAC。
可以用遥控以数码方式把信号反相来纠正一些错误的录音。
对不同平均幅度的音源进行数码自动音量调整(ALC),因为俺受够了不同电视节目音量忽大忽小的折腾,当然此功能在不需要时可以关闭。
开机延时和音源信号消失超于设定时间有自动关机功能(包括外接机器如功放,CD机,DVD 等)。
七画LED屏显示音源选择和音量位置,不需要时可以自动把扫描关闭以降低数码噪音。
有自学能力的红外线接收器,方便不同编码的各类型不同牌子的遥控器使用。
PWM 测试信号发生器,方便测试和观察放大器的输出波形。
使用ZILOG Encore!XP Z8F 单片机控制。

希望有兴趣跟帖的朋友可以从整个制作过程中学到一些新的知识,如
1.        模拟开关芯片的应用
2.        乘法数字/模拟转换器当音量调节使用(不是一般常用的数字电位器芯片如PGA2310, CS3310 等)
3.        数码自动音量调整
4.        信号消失自动关机功能
5.        自学功能的红外线接收
6.        用程序和PWM 当函数发生器
7.        单片机在音响的应用和如何编写单片机语言等等。

在未来几个月之内俺会依据进度把各部分已完成的程序发上来与各位共享。

图看不全的话清按着<Ctrl> 再用老鼠的滚轮

遥控前级_1.GIF

遥控前级_2.GIF

因为手头上刚好有几个十多年前用剩的 AD 芯片,AD 芯片的最大好处是里面的电阻是薄膜的,质量应该比专用电子电位器里的半导体电阻优秀。
音源切换不用继电器因为担心在大音量超低音震动下会出现触点弹跳,用芯片切换另一好处是体积小而外部噪音干扰较低。

也考虑过用液晶显示,不过几米以外就看不清楚了,所以最后决定用LED。

俺是海外的,这个前级也是为上海的一个朋友设计的,开板子的事就由国内的朋友来办吧,俺会尽全力配合。

俺认为输入400欧姆的导通电阻影响是很微小的,假设它本身带给了0.01%的失真,但是在66K的总输入阻抗中只占有不到百分之一的比例,所以最后影响还不到0.0001%。它对输入阻抗和增益的影响也因为是平衡输入的切换而大部分被抵消了。
输入端的钳位二极管是必须的,否则芯片会轻易的被外面的静电或脉冲干扰所击毁,不过这二极管是钳位到正负15伏电源的,对峰值顶多是5伏的输入信号是不产生作用的,二极管几个pF的极电容还可以对射频过滤有一定的帮助。

开始动手


在俺这儿开电路板需费一百多美金,这里又没有烧友同好分享,所以就找了一块两年前工程用剩的LED显示板,用洞洞板把主要元件焊了上去,再加上电源和外部接线就可以了。先写了LED屏的扫描部分,过些日子有空时再编写控制程序,然后就可以测试各种功能了。

前级1.jpg

前级2.jpg

前级4.jpg

显示屏扫描子程序


;每一毫秒调用一次
;江文正,2007-08-15

        .include "eZ8.inc"

        segment        code

                xref        _readbut        ;读取按键

                                xref          _DigCtr        ;位数计
                xref        _DplDuty        ;亮度占空比
                xref        _DplFlag        ;bit0 = 闪烁, bit1 = 自动音量, bit2 = 切换, bit3 = 测试,bit4 = 设置遥控码
                xref        _FuncNr        ;功能选择
                xref        _Volume        ;音量
                xref        _ChNr        ;输入切换号码

                xdef        _shiftdpl        ;移位刷屏

;=================================================
; 引脚定义
data1        equ        PBOUT                ort B
data1_0        equ        11111110B        B0
data1_1        equ        00000001B        B0
stb1        equ        PBOUT                ort B
stb1_0        equ        11111101B        B1
stb1_1        equ        00000010B        B1
clk1        equ        PCOUT                ort C
clk1_0        equ        01111111B        C7
clk1_1        equ        10000000B        C7

minus_0        equ        00010000B        ;-0
minus_1        equ        00111000B        ;-1

;7 段显示笔画定仪表指针
seg_ptr:;                     FABGCD.E
                .BYTE    11101101B        ;0
        .BYTE    00101000B        ;1
        .BYTE    01110101B        ;2
        .BYTE    01111100B        ;3
        .BYTE    10111000B        ;4
        .BYTE    11011100B        ;5
        .BYTE    11011101B        ;6
        .BYTE    01101000B        ;7
        .BYTE    11111101B        ;8
        .BYTE    11111100B        ;9
        .BYTE    11111001B        ;A
        .BYTE    11000101B        ;C
        .BYTE    00111101B        ;d
        .BYTE    10010101B        ;t
        .BYTE    10101101B        ;U
        .BYTE    10100100B        ;V


SegBuf        equ                R5
DigPos        equ                R4

;======================================
_shiftdpl:
        CP      _DigCtr,#05
                JR        ULT,$F
                inc        _DplDuty
                cp        _DplDuty,#4        ;此数用于调节亮度
                JR        ugt,$F
                ret#p#分页标题#e#
$$:                clr        _DplDuty
;                call        __readbut

                push        R0                ;如果只有 C 语言调用此子程序,进栈和退栈部分可以抹掉
                push        R1                ;
                push        R2                ;
                push        R3
                push        R4
                push        R5                ;

                                LD            DigPos,#00000001B
                CPX          _DigCtr,#05
                JR            ULT,NX_DIG
                LDX        _DigCtr,#0
NX_DIG  ADDX     _DigCtr,#1
                LDX        R0,_DigCtr
$$:                RR            DigPos
                djnz        R0,$B
                                LDX          SegBuf,_Volume
                cpx        _DigCtr,#03
                jr        ult,$F
                        LDX          SegBuf,_ChNr
$$:
                TMX        _DigCtr,#1
                JR        NZ,LSD
                SWAP        SegBuf                ;若是偶数,左右四比特对换
LSD                           AND         SegBuf,#0FH        ;淹没左四比特
                LD         R0, #high(seg_ptr)        ;画段指针
                LD         R1, #low(seg_ptr)        ;
                ADD          R1,SegBuf                  ;加上错位
                ADC          R0,#0
                LDC          SegBuf,@RR0               ;从画段表获取数据                           
                cpx        _FuncNr,#0
                jr        ne,$F
                cpx        _DigCtr,#3                ;显示音量时第三位数空白
                jr        eq,blank
$$:                cpx        _DigCtr,#05
                jr        ult,$F
blank                         clr            SegBuf                        ;灭显示
$$:
                                LD            R3,SegBuf              ;输出画段
                COM         R3                ;低电平驱动
                                CALL         OUT_BYTE
                                LD            R3,DigPos                ;输出位数
                                CALL         OUT_BYTE
                ORX        stb1,#stb1_1        ;转移数据
                NOP
                NOP
                NOP
                                ANDX        stb1,#stb1_0
                ANDX        data1,#data1_0
                andx        _DplFlag,#%FE        ;标记处理完毕

                pop        R5                ;如果只有 C 语言调用此子程序,进栈和退栈部分可以抹掉
                pop        R4
                pop        R3
                pop        R2
                pop        R1
                pop        R0
                                RET

OUT_BYTE        ;串移数据
                                LD            R2,#08        ;8 比特
SFT_LP       
                ANDX        data1,#data1_0
                RL             R3
                JR             NC,CLKING
                ORX          data1,#data1_1
CLKING        ;输出一个时钟脉冲
                NOP
                NOP
                NOP
                ORX          clk1,#clk1_1
                NOP
                NOP
                NOP
                ANDX         clk1,#clk1_0
                DJNZ          R2,SFT_LP
                RET
;--------------------------------------------

刚完成了采用 NEC 波形的读码部分,改天再写飞利浦波形的。

; 汇编部分,中断子程序

vector        C3=_isr_C3; 红外线, 下降沿,
_isr_C3:
        tmx                PCIN,#%08                ; 只取下降沿
        jr                nz,c3_x
        ldx                _width,T1H                ; 一次 = 92.23uS#p#分页标题#e#
        ldx                T1H,#%0                        ; 定时器重新置零
        orx                _ir_flag,#1                ; 标记收到红外线信号
c3_x
        iret


;=============================================================

vector        TIMER1=_isr_T1                        ;23.52mS
_isr_T1:                ;
        ldx                _step_ctr,#0        ; 无红外线信号空挡,步骤置零
        iret                                       


//C 语言部分
////////////////////////////////////////////////////////
// NEC uPD6121 波形 红外线读码 2007-08-23 江文正
// 方法 : 接收管输出下降沿触发中断子程序,读取下降沿之间的时间 width 后把定时器重新置零
// width 单位= 92.23uS, 前提是 定时器时钟 = 5.5296 MHz, prescale = 2
// 两个下降沿之间时段: 引导码, >11.81mS : width=128
// 重复码, >9mS : width=97
// >1.69mS : width=18 = 高电平数据,  <1.69mS : width=18 = 低电平数据


IR_decode()
{       
char rcv_8bit=0;
int rcv_16bit=0;

        ir_flag &= 0xFE;        //标记已处理
        if (step_ctr ==0)
        {
                step_ctr=1;        //开始
        }
        else
        {
                if (width > 128)        //引导码
                {
                        step_ctr=2;
                        user_code=0;        // 清0
                        cmd_code=0;        // 清0
                }
                else
                {
                        if (width > 97)        //重复码
                        {
                                step_ctr=34;        //
                        }
                    else
                        {
                                if (width > 18)        //高电平
                                {
                                        rcv_8bit=1;
                                        rcv_16bit=1;
                                }

                                if (step_ctr<18)        //用户码
                                        {
                                                rcv_16bit = rcv_16bit << (step_ctr-1);
                                                user_code |= rcv_16bit;
                                        }
                                else
                                {
                                        if (step_ctr<26)        //控制码
                                        {
                                                rcv_8bit = rcv_8bit << (step_ctr-17);
                                                cmd_code |= rcv_8bit;
                                        }
                                }
                                if (step_ctr>25)                //反码
                                {
                                        rcv_8bit = rcv_8bit << (step_ctr-25);
                                        comp_code |= rcv_8bit;
                                }
                       
                                step_ctr++;
                                if (step_ctr>33)                //有效码
                                {
                                        comp_code ^= 0xFF;        //2反位,2'complement
                                        comp_code--;
                                    if (cmd_code != comp_code)
                                        {
                                                step_ctr = 0;        //错码,无效
                                        }
                                }
                        }
                }
        }
}




大部分国内生产的遥控器都使用NEC码,你先按照提示找出你手中遥控器的用户码,然后再找出你所想使用的那几个按键的功能码,再把这些码取代以下的部分

//所用遥控器的控制码, 不同遥控器的码会不一样
#define user         0xFF00;// 用户码
#define vol_up         0x58;        // 增音量 <vol +> 按键
#define vol_dn         0x59;        // 减音量 <vol -> 按键
#define ch_up         0x4A;        // 下一个切换位置 <tune +> 按键
#define ch_dn         0x1E;        // 前一个切换位置 <tune -> 按键
#define mute         0x46;        // 静音 <mute> 按键
#define pwr                 0x40;        // 电源开关 <pwr> 按键#p#分页标题#e#
#define anti         0x0E;        // 左声道反相 <mode> 按键
#define agc          0x1C;        // 自动音量 <audio> 按键
#define off_tmr         0x49;        // 自动关机 <timer> 按键

请注意接收管输出必须接到有下降沿中断功能的 I/O 引脚,

附件是俺目前正在使用的源代码,有些部分俺同时写了C和汇编的,只需选用需要的部分就可以了,俺是使用荧光真空显示模块(VFD)的.LED显示部分的代码也有了,如果要使用LCD模块,俺可以替你们写,不过I/O接线会多一些,18 或 20 条腿的单片机也许不够用,要用28条腿以上的。

遥控前级.rar
(责任编辑:admin)
织梦二维码生成器
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
推荐内容