器件:PT2258音量控制器

1 序

  PT2258为台湾普诚电子于2000年7月开发出的由iic总线控制的音量控制IC;音量调节范围[-79,0]dB,调节步长1dB;

2 硬件原理

  2.1 这个PT2258是啥东西呢?

    PT2258内部集成了可编程电阻网络,即滑动变阻+运放,通过对Vin进行分压处理后输出Vout,实现音量控制;

    10dB每步长和1dB每步长的滑动变阻,通过iic将数值写入controlUnit来控制;code1,code2用来修改iic地址;

    当音量放大倍数为0dB时,Vin=Vout音量最大;当音量放大倍数为-79dB时,Vout音量最小;

    这么一看,很简单嘛,简单的匪夷所思;

    

  2.2 这个PT2258的外围电路是咋样的呢?

    

    这个pt2258有20pin引脚,12pin输入输出,4pin电源,4pin的iic控制;

    工作电压5-9V,工作电流8mA;Cref=10uF,iic的Tmaxinit =300ms,可能就是pt2258上电稳定时间(page11);

    pt2258在调节步长的时候有bongbong声是因为在通道和10uF电容之间加了0Ω电阻,替换0Ω电阻为电容就改善了;

3 软件原理

  3.1 这个PT2258的滑动变阻是咋通过iic来控制的呢?

    但凡使用iic的器件数据手册都习惯把iic的时序给大伙重新过一遍,这里就不过了;

    已经知道pt2258的iic其实就控制几个滑动变阻,所以只要往pt2258写滑动变阻的dB增益就行啦,完全不需要读操作;

    这个pt2258只有一条iic协议格式如下,一个iic首地址+n数据字节;如果收到ack不为0,需要始终发送stop后重新start开始;

    如图可知addr的MSB[7]=1b,bit[3:2]为[code1:code2],所以下图的pt2258的addr为88h;

    

  3.2 对于data数据字节而言,那又是咋实现的呢?翻翻数据手册Data Bytes Description就可以知道,

    对于数据字节的固定bit已经标出1,0了;而剩下的A3-A0和B2-B0的值见下图可知;

    

    

4 软件例程

//前4表示通道,后4表示db; datasheet p9; xxxx取值:1001=9,1000=8,...,0001=1,0000=0
#define PT2258_Reg_6CH_1db_STEP 0xE0 // 1110 xxxx all-Channel, -1dB/step
#define PT2258_Reg_6CH_10db_STEP 0xD0 // 1101 0xxx all-Channel, -10dB/step
#define PT2258_Reg_CH1_1db_STEP 0x90 // 1001 xxxx Channel No. 1, -1dB/step
#define PT2258_Reg_CH1_10db_STEP 0x80 // 1000 0xxx Channel No. 1, -10dB/step
#define PT2258_Reg_CH2_1db_STEP 0x50 // 0101 xxxx Channel No. 2, -1dB/step
#define PT2258_Reg_CH2_10db_STEP 0x40 // 0100 0xxx Channel No. 2, -10dB/step
#define PT2258_Reg_CH3_1db_STEP 0x10 // 0001 xxxx Channel No. 3, -1dB/step
#define PT2258_Reg_CH3_10db_STEP 0x00 // 0000 0xxx Channel No. 3, -10dB/step
#define PT2258_Reg_CH4_1db_STEP 0x30 // 0011 xxxx Channel No. 4, -1dB/step
#define PT2258_Reg_CH4_10db_STEP 0x20 // 0010 0xxx Channel No. 4, -10dB/step
#define PT2258_Reg_CH5_1db_STEP 0x70 // 0111 xxxx Channel No. 5, -1dB/step
#define PT2258_Reg_CH5_10db_STEP 0x60 // 0110 0xxx Channel No. 5, -10dB/step
#define PT2258_Reg_CH6_1db_STEP 0xB0 // 1011 xxxx Channel No. 6, -1dB/step
#define PT2258_Reg_CH6_10db_STEP 0xA0 // 1010 0xxx Channel No. 6, -10dB/step
#define PT2258_Reg_6CH_MUTE_OFF 0xF8 // 1111 100x all-Channel, Mute When M= 0, MUTE OFF
#define PT2258_Reg_6CH_MUTE_ON 0xF9 // 1111 100x all-Channel, Mute When M= 1, MUTE ON
#define IIC_ADDR_PT2258 0x80 //CODE[1:2]都接GND时的iicAddr;
//用户可调节音量范围[1,100](percent)
uint8_t pt2258_volPercentMap[101]={
0,
1, 3, 4, 5, 6, 8, 9, 10,11,13,
14,15,16,18,19,20,21,23,24,25,
26,28,29,30,31,33,34,35,36,38,
39,40,41,43,44,45,46,48,49,50,
51,53,54,55,56,58,59,60,61,63,
64,65,66,68,69,70,71,73,74,75,
76,78,79,80,81,83,84,85,86,88,
89,90,91,93,94,95,96,98,99,100,
};
//PT2258可调节音量范围[-79,0](dB)
uint8_t pt2258_dBMap[81]={
80,
79,78,77,76,75,74,73,72,71,70,
69,68,67,66,65,64,63,62,61,60,
59,58,57,56,55,54,53,52,51,50,
49,48,47,46,45,44,43,42,41,40,
39,38,37,36,35,34,33,32,31,30,
29,28,27,26,25,24,23,22,21,20,
19,18,17,16,15,14,13,12,11,10,
9, 8, 7, 6, 5, 4, 3, 2, 1, 0
};
void pt2258_iic_writeByte(eIIC_BUS_ID busId,uint8_t iicAddr,uint8_t data1, uint8_t data2){
PRT_PT2258("pt2258_iic_writeByte() ");
eRESULT eResult = rcSUCCESS;
uint32_t regData = (uint32_t)((data1<<8)|data2);
uint32_t pLen = 0;
uint8_t *pBuff = NULL;
uint32_t regIs2Flag = FLG_IIC_WADDR;
eResult = dvDeviceBusWrite(busId,iicAddr,regData,pLen,pBuff,regIs2Flag);
if(eResult){
PRT_PT2258("PT2258 iic fail. ");
}
}
void PT2258_AdjustFunction(u8 busID,u8 ch,u8 dBValue)
{
u8 VolumeVaule_10db = 0;
u8 VolumeVaule_1db = 0;
switch(ch){
case 1:
VolumeVaule_1db = PT2258_Reg_CH1_1db_STEP|((pt2258_dBMap[dBValue]%10)&0xF);
VolumeVaule_10db = PT2258_Reg_CH1_10db_STEP|((pt2258_dBMap[dBValue]/10)&0x7);
break;
case 2:
VolumeVaule_1db = PT2258_Reg_CH2_1db_STEP|((pt2258_dBMap[dBValue]%10)&0xF);
VolumeVaule_10db = PT2258_Reg_CH2_10db_STEP|((pt2258_dBMap[dBValue]/10)&0x7);
break;
case 3:
VolumeVaule_1db = PT2258_Reg_CH3_1db_STEP|((pt2258_dBMap[dBValue]%10)&0xF);
VolumeVaule_10db = PT2258_Reg_CH3_10db_STEP|((pt2258_dBMap[dBValue]/10)&0x7);
break;
case 4:
VolumeVaule_1db = PT2258_Reg_CH4_1db_STEP|((pt2258_dBMap[dBValue]%10)&0xF);
VolumeVaule_10db = PT2258_Reg_CH4_10db_STEP|((pt2258_dBMap[dBValue]/10)&0x7);
break;
case 5:
VolumeVaule_1db = PT2258_Reg_CH5_1db_STEP|((pt2258_dBMap[dBValue]%10)&0xF);
VolumeVaule_10db = PT2258_Reg_CH5_10db_STEP|((pt2258_dBMap[dBValue]/10)&0x7);
break;
case 6:
VolumeVaule_1db = PT2258_Reg_CH6_1db_STEP|((pt2258_dBMap[dBValue]%10)&0xF);
VolumeVaule_10db = PT2258_Reg_CH6_10db_STEP|((pt2258_dBMap[dBValue]/10)&0x7);
break;
default:
VolumeVaule_1db = PT2258_Reg_6CH_1db_STEP|((pt2258_dBMap[dBValue]%10)&0xF);
VolumeVaule_10db = PT2258_Reg_6CH_10db_STEP|((pt2258_dBMap[dBValue]/10)&0x7);
break;
}
//不确定这个指令为什么要发两遍,只发一遍听感不对,没用仪器测,先放着把;发2遍就不会;
pt2258_iic_writeByte(busID, IIC_ADDR_PT2258, VolumeVaule_1db, VolumeVaule_10db);
pt2258_iic_writeByte(busID, IIC_ADDR_PT2258, VolumeVaule_1db, VolumeVaule_10db);
}
void PT2258_VolumeAdjust(uint8_t busID, uint8_t ch, float vol){
uint8_t dBPercent = (uint8_t)(vol*0.8);
if(dBPercent<1){
dBPercent=1;
}
PRT_PT2258("PT2258_VolumeAdjust()------ch:%d db:%d",ch,dBPercent);
PT2258_AdjustFunction(busID,ch,dBPercent);
}
void PT2258_VolumeMute(uint8_t busID,uint8_t muteFlag){
PRT_PT2258("PT2258_VolumeMute() ");
if(muteFlag){
pt2258_iic_writeByte(busID, IIC_ADDR_PT2258, PT2258_Reg_6CH_MUTE_ON,PT2258_Reg_6CH_MUTE_ON);
}
else{
pt2258_iic_writeByte(busID, IIC_ADDR_PT2258, PT2258_Reg_6CH_MUTE_OFF,PT2258_Reg_6CH_MUTE_OFF);
}
}

5 小结

  PT2258的软件还是比较简单的,因为软件需要调节的也不多,只需要通过iic发送3个字符就完了;

  如果调节声音就通过iic总线发送对应dB值给到PT2258;如果静音就通过iic总线发送对应静音或不静音指令给到PT2258;

  如果调节2258旋钮有pongpong声,那就看看电阻电容取值位置对不对,可能会有轻微pongpong声;

  如果断上电时有pongpong声,那就在断上电之前先mute了PT2258;

  ques:发现iic的音量调节需要发两遍,发一遍声音听起来不对,主要是dB十进制跳变时,放着先;

  参考文档:PT2257在数字音量控制系统中的应用

posted @   rls_v  阅读(388)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示