器件: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十进制跳变时,放着先;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?