原创 pic12f675控制音量

2010-10-9 23:40 2651 5 9 分类: MCU/ 嵌入式

;;;;;;;;;;;;;;;;;;; 源代码开始 ;;;;;;;;;;;;;;;;;;;;;;;


; PGA2310 电子音量控制


; PIC12F675,4 MHz MCU


; 2006 (c) RUU


;


; 2006.9.27 Ver0.31 : VR 位置检测和变换的错误修正


; 2006.9.5  Ver0.3  : 改变 0.5 dB增减速率,避免偶然杂音


; 2006.7.10 Ver0.2  : 控制方法的改变


; 2006.6.30 Ver0.1  : 第一个测试版本


;


;Vdd=5V


; 用0 ~Vdd的电平通过GP4实现音量控制,


; PGA2310 的增益-95.5dB~+31.5dB 的范围内,


; VR 的变化为 128级、每级的是 0.5 db 分辨率。


;


; 功能设定:


; GP3 为静音功能端子,


; 电源开启后大约 1.5 秒开启,2.5 秒后从静音状态转换到VR 的设定值,


; 音量平滑上升。


; 如果不需要静音控制,将GP3直接与Vdd连接。


;


;


; GP0 : ~CS (Output)


; GP1 : SDO (Output)


; GP2 : SCLK (Output)


; GP3 : PWR (Digital Input)


; GP4 : VOLUME (Analog Input)


; GP5 : MUTE (Output)


;


;


;;


 


 


            include    '12f675.inc'


            FUSES    _INTRC_OSC_NOCLKOUT


            FUSES    _WDT_OFF


            FUSES    _MCLRE_OFF


            FUSES    _PWRTE_ON


            FUSES    _BODEN_ON


            FUSES    _CP_OFF


            FUSES    _CPD_OFF


 


 


NOT_CS        =    gpio.0            ; Chip Select (PGA2310)


SDO           =    gpio.1            ; Serial Data (PGA2310)


SCLK          =    gpio.2            ; Serial Clock (PGA2310)


PWR           =    gpio.3            ; Power Monitor input


VR            =    gpio.4            ; Volume control analog input


MUTE          =    gpio.5            ; Mute Relay drive


 


 


               org    20h


 


cnt            ds    1                ; 等待用途计数器


cnt2           ds    1


volume8        ds    1                ; Volume 值 8 bit


old_pos        ds    1                ; 当前的 Vol 位置


vo_l           ds    1                ; Volume_Left 设定值


vo_r           ds    1                ; Volume_Right 设定值


work           ds    1                ; 工作


bitcnt         ds    1                ; 发送 bit 计数器


 


statflg        ds    1                ; 标签


VR_CHG          =    statflg.0        ; volume 变化检测


 


; 内部 EEPROM


            eeorg    0


            eedata    'PGA2310 VOL-CNTL -RUU 2006-     '


 


 


            org        0


            goto    start


               org        4


            goto    start


 


 


;; 主程序


 


start


            clr        gpio


            mov        cmcon,#00000111b            ; GP0:2 Digital, Comparator off


            mov        adcon0,#00001100b           ; ADFM=Left, Vref=VDD, A/D CH=3(GP4)


    setb    rp0


            call    3FFh                           ; 时钟脉冲发生器数据设定


            mov        osccal,w


            mov        option,#10001000b           ; GPPU无 , PS无


            mov        wpu,#00000000b              ;


            mov        trisio,#00011000b           ; GP3,4


            mov        iocb,#00000000b             ; interrupt on change


            mov        ansel,#00011000b            ; ANS3=analog ADCS=Fosc/8


            clrb    rp0


            mov     intcon,#00000000b              ; 中断禁止


 


            setb    NOT_CS                         ; Not Select


            clr        statflg


            clr        old_pos


 


:init


            call    wait_1s                        ; 1 秒延时


            jnb        PWR,:init


            clr        vo_r


            clr        vo_l


            call    send_volume                    ; PGA2310 静音


            call    wait_05s                       ; 0.5 秒延时


            setb    MUTE                           ; Relay ON


            call    wait_1s                        ; 1 秒延时


 


            call    get_vr                         ; 取得Volume 值


            call    conv_vr


:dvloop


            cjae    vo_r,volume8,:mainloop


            inc        vo_r                        ; 从静音到 VR 数值,以 0.5 dB 平滑的上升


            inc        vo_l


            call    send_volume


            call    wait_10ms


            goto    :dvloop


 


:mainloop


            call    wait_1ms


            jnb        PWR,:relay_off


            call    get_vr                         ; VR 位置取得 -> volume8


            call    chk_vr                         ; 检测变化量


            jb        VR_CHG,:set_volume           ; 2 阶以上变化?


            goto    :mainloop


 


:set_volume


            mov        old_pos,volume8             ; VR 位置保存


            call    conv_vr                        ; VR 位置 /Vol 值变换 -> volume8


:set_loop


            cja        vo_r,volume8,:v_down        ; 上次 Vol 值 (vo_r) 更加小


            cjb        vo_r,volume8,:v_up          ; 上次 Vol 值 (vo_r) 更加大


            goto    :mainloop                      ; 数值变化,如果是没有的话则停止


:v_down


            dec        vo_r                        ; -0.5db


            dec        vo_l


            goto    :new_volume


:v_up


            inc        vo_r                        ; +0.5db


            inc        vo_l


:new_volume


            call    send_volume


            call    wait_1ms


            goto    :set_loop


 


:relay_off


            clrb    MUTE                           ; Relay OFF


            goto    :init


 


 


;; 向 PGA2310 上发送 Volume 值,设定 (vo_r=右ch, vo_l=左ch)


send_volume


            clrb    SCLK                           ; SCLK = L


            mov        work,vo_r


            mov        bitcnt,#8


            clrb    NOT_CS                         ; ~CS = L


:loop_r


            rl        work                         ; C<- Vol 上位


            sc


            clrb    SDO                            ; SDO <- C


            snc


            setb    SDO


            nop


            setb    SCLK                           ; SCLK = H


            nop


            nop


            clrb    SCLK                           ; SCLK = L


            djnz    bitcnt,:loop_r


 


            mov        work,vo_l


            mov        bitcnt,#8


:loop_l


            rl        work


            sc


            clrb    SDO                            ; SDO <- C


            snc


            setb    SDO


            nop


            setb    SCLK                           ; SCLK = H


            nop


            nop


            clrb    SCLK                           ; SCLK = L


            djnz    bitcnt,:loop_l


 


            setb    NOT_CS                         ; ~CS = H


            ret


 


 


;;检测VR 的位置变化


chk_vr                                             ; 检测出VR 位置改变


            cjb        volume8,old_pos,:v_dec      ; 如果是 vol< old_pos 的话就减小


:v_inc


            mov        work,volume8


            sub        work,old_pos                ; work<- 变化量


            goto    :chk


:v_dec


            mov        work,old_pos


            sub        work,volume8


:chk                                               ; old_pos 2 位置变化了吗?


            cjb        work,#2,:no_chg


            setb    VR_CHG                         ; 变化有 -> VR_CHG


            ret


:no_chg


            clrb    VR_CHG                         ; 变化没有 -> VR_CHG


            ret


 


 


;; VR 位置变化→数字 VOL 值变换 (128 阶,convtbl )


conv_vr


            clc


            rr        volume8                      ; pos-> index


            call    convtbl                        ; index-> volume


            mov        volume8,w


            ret


 


 


;;; 获取 GP4 VR 位置


get_vr


            mov        adcon0,#00001101b            ; Left, Vref=VDD, CH=3, A/D=ON


            call    wait_20us


            setb    go_done                         ; A/D start


:get_wait


            jb        go_done,:get_wait


            mov        volume8,adresh               ; A/D 变换结果


            ret


 


 


 


;*** 公用程序 ***


 


wait_20us                                        ; 18(us)


            mov        cnt,#4                    ; 2


:loop


            djnz    cnt,:loop                    ; 3*4+2


            ret                                  ; 2


 


 


wait_1ms                                         ; 998(us)


            mov        cnt,#124


:loop


            nop


            nop


            nop


            nop


            nop


            djnz    cnt,:loop


            ret


 


wait_5ms                                         ; 5(ms)


            mov        cnt2,#5


:loop


            call    wait_1ms


            djnz    cnt2,:loop


            ret


 


wait_10ms                                        ; 10(ms)


            mov        cnt2,#10


:loop


            call    wait_1ms


            djnz    cnt2,:loop


            ret


 


wait_20ms                                        ; 20(ms)


            mov        cnt2,#20


:loop


            call    wait_1ms


            djnz    cnt2,:loop


            ret


 


wait_250ms                                       ; 0.25(s)


            mov        cnt2,#250


:loop


            call    wait_1ms


            djnz    cnt2,:loop


            ret


 


wait_1s                                          ; 1.00(s)


            call    wait_250ms


            call    wait_250ms


            call    wait_250ms


            call    wait_250ms


            ret


 


wait_05s                                         ; 0.50(s)


            call    wait_250ms


            call    wait_250ms


            ret


 


 


;; Volume data conversion table


 


            org        100h


convtbl


            mov        PCLATH,#1


            mov        w,volume8


            jmp        pc+w


 


; 听音曲线补偿


; -95.5dB~+3.0dB 变化范围


            retw      0,  8, 14, 20, 24, 30, 34, 40, 44, 48, 50, 54, 58, 62, 64


            retw     68, 72, 74, 78, 80, 84, 86, 90, 92, 94, 96,100,102,104,106


            retw    108,110,112,114,117,119,121,123,124,126,128,130,132,133,135


            retw    137,138,140,142,143,145,146,148,149,151,152,153,154,156,157


            retw    158,160,161,162,163,164,166,167,168,169,170,171,172,173,174


            retw    175,176,176,177,178,179,180,180,181,182,183,184,184,185,186


            retw    186,187,188,188,188,189,189,190,190,191,192,192,193,193,194


            retw    194,194,195,195,196,196,196,197,197,197,198,198,198,198,198


            retw    199,199,199,199,199,200,200,200


 


; 音量变化为直线型


;-95.5 dB~+31.0dB 变化范围


;            retw      0,  2,  4,  6,  8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28


;            retw     30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58


;            retw     60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88


;            retw     90, 92, 94, 96, 98,100,102,104,106,108,110,112,114,116,118


;            retw    120,122,124,126,128,130,132,134,136,138,140,142,144,146,148


;            retw    150,152,154,156,158,160,162,164,166,168,170,172,174,176,178


;            retw    180,182,184,186,188,190,192,194,196,198,200,202,204,206,208


;            retw    210,212,214,216,218,220,222,224,226,228,230,232,234,236,238


;            retw    240,242,244,246,248,250,252,254


 


 


;;;;;;;;;;;;;;;;;;; 源代码结束 ;;;;;;;;;;;;;;;;;;;;;;

PARTNER CONTENT

文章评论4条评论)

登录后参与讨论

用户409556 2010-12-6 14:48

可否把这个程序转成HEX(BIN)的烧录格式发到我的Mail:chowmug@qq.com。 谢谢!!!

用户409556 2010-12-1 09:42

好像我乎略了音量大小是由VR电位来控制了(我当作是译码开关了),那之前的与功放瓦数匹配的问题就不存在了。哈哈!

用户409556 2010-12-1 09:37

我有用过MAX5440音量IC,开机的默认输出音量“相对输入-12db”,比较适合用于控2-5W的功放IC;而我却用来控制10W的功放,开机时很大声,后来只能不用。所以想找个通用性强些的来用,因此有此问!

用户409556 2010-12-1 09:30

不知道此程序的在每次开机的默认音量是多少? 开机的默认音量适合应用于多少功率输出的功放? 如和5W/10W/20/50W/100W的功放呢!如何匹配, 有个小小建议,可否通过一个端口电位高低值来 设置不同的开机默认音量值以匹配不同的功放功率!
相关推荐阅读
用户579257 2010-10-09 23:47
辉光管电子时钟源程序
;*******************************************; 定时器溢出周期为50MS; P3.4为显示开关按钮,P3.5为调整时钟,P3.6为调整分钟; 70-71H ...
用户579257 2010-10-09 23:46
语音温度计
//使用AT89C2051单片机,12MHz晶体,用共阳LED数码管//P1口输出段码,P3口扫描,P3.4接DS18B20//#Pragma src(d:\aa.asm)#include <r...
用户579257 2010-10-09 23:45
机动车尾号限行提示器
#include  <reg51.h>                        sbit  LCD_CLK    = P1^0;   /*LCD时钟线引脚 */sbit  LCD_S...
用户579257 2010-10-09 23:42
智能救援车
#include"reg52.h"#include<intrins.h>     //调用汇编指令    #include<stdio.h>       #include<...
用户579257 2010-10-09 23:38
水位控制器
AIRD BIT P3.0WLD BIT P3.1WHD BIT P3.3WOVD BIT P3.4BZ BIT P3.5FRD BIT P1.2FR BIT P3.7WOV BIT P1.3WH B...
EE直播间
更多
我要评论
4
5
关闭 站长推荐上一条 /3 下一条