;;;;;;;;;;;;;;;;;;; 源代码开始 ;;;;;;;;;;;;;;;;;;;;;;;
; 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
;;;;;;;;;;;;;;;;;;; 源代码结束 ;;;;;;;;;;;;;;;;;;;;;;
用户409556 2010-12-6 14:48
用户409556 2010-12-1 09:42
用户409556 2010-12-1 09:37
用户409556 2010-12-1 09:30