这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » wenyangzeng的功放DIY进程帖 (进程7 试听 TPK3110 PK

共9条 1/1 1 跳转至

wenyangzeng的功放DIY进程帖 (进程7 试听 TPK3110 PK TDA2030)

工程师
2015-03-10 11:14:09     打赏

高工
2015-03-10 15:07:00     打赏
2楼


 这次发的电容都有写值了吧。


工程师
2015-03-10 21:53:56     打赏
3楼
电容值有写在封装上。

工程师
2015-03-12 15:03:07     打赏
4楼

进程2:焊接

焊接工作完成:

焊接完成


工程师
2015-03-12 22:45:35     打赏
5楼

进程3:代码下载 

   代码下载使用RS232串口方式,手头刚好有1块RS232转换板可利用,连接方法见下图。转接板的5V供电直接取自功放板的+5V,所以那只R21电阻就不再是NC(未连接),而是要短接,5V供电才能输出。点击STC-ISP-15XX-V6.28H.EXE,在”打开程序“栏里输入版主提供的TEST.HEX,点击”下载/编程“,然后接通功放板电源。代码很顺利地下载到板上。

 原理图

                                    图1    下载器原理图


连接方法

                                  图2  连接图


下载成功

                                   图3 下载成功





工程师
2015-03-18 17:35:28     打赏
6楼

进程4:按键音量控制

使用MDK4-C51开始写代码,第一阶段实现按键音量控制,为后续的红外线遥控打好基础:

#include "config.h"

#include "GPIO.h"
#include "delay.h"
static struct {
                   unsigned        Key:1;
                   unsigned   Mute:1
                 }  Flag;
#define BIT0 0x01
#define BIT1 0x02
#define BIT2 0x04
#define BIT3 0x08
#define BIT4 0x10
#define BIT5 0x20
#define BIT6 0x40
#define BIT7 0x80
#define Get_CHECK ((P1 & BIT0)^BIT0)
#define Get_MUTE ((P1 & BIT1)^BIT1)
#define Get_Dn ((P1 & BIT2)^BIT2)
#define Get_Up ((P1 & BIT3)^BIT3)
#define MUTE_H P1 |= BIT4
#define MUTE_L  P1  &= ~BIT4
#define CLOCK_H P3  |= BIT3
#define CLOCK_L P3  &=~BIT3

void GPIO_config(void)

GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Pin  = GPIO_Pin_5|GPIO_Pin_4;
GPIO_InitStructure.Mode = GPIO_OUT_PP;
GPIO_Inilize(GPIO_P1,&GPIO_InitStructure);

GPIO_InitStructure.Pin  = GPIO_Pin_3|GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStructure.Mode = GPIO_OUT_PP;
GPIO_Inilize(GPIO_P3,&GPIO_InitStructure);

GPIO_InitStructure.Pin  = GPIO_Pin_2;
GPIO_InitStructure.Mode = GPIO_PullUp;
GPIO_Inilize(GPIO_P3,&GPIO_InitStructure);

GPIO_InitStructure.Pin  = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
GPIO_InitStructure.Mode = GPIO_PullUp;
GPIO_Inilize(GPIO_P1,&GPIO_InitStructure);
}

void Volume_Dn(void)
{ P1 &= ~BIT5;
P3 &=~BIT6;
  CLOCK_H;
  delay_ms(100);
  CLOCK_L;
P1 |=BIT5;
}
 void Volume_Up(void)
{ P1 &= ~BIT5;
P3 |=BIT6;
  CLOCK_H;
  delay_ms(100);
  CLOCK_L;
P1 |=BIT5;
}
void Scan_Key(void)
{  if(Get_Dn||Get_Up||Get_MUTE)
{
  delay_ms(20);
  if(Get_Dn||Get_Up||Get_MUTE)
    Flag.Key=1;
 }
}
void Key_Server(void)
{
  Flag.Key=0;
if(Get_Dn)  Volume_Dn();
if(Get_Up)  Volume_Up();
if(Get_MUTE)
    { 
    Flag.Mute++;
    if(Flag.Mute)
           MUTE_H;
        else
            MUTE_L;
    }
}
 void main(void)
 { unsigned char i;
  GPIO_config();
   
  while(1)
  { 
  Scan_Key();
  if(Flag.Key)
  Key_Server();
 }
 }
    按键处理过程采用软件延时方式去除干扰,每按一次按键,红色LED闪亮一次。以上代码实现了按键控制和静音功能。


工程师
2015-03-20 20:35:02     打赏
7楼

进程5 EEPROM存储数据

利用STC15W204S内部EEPROM存储音量控制数据。对EEPROM的读写并不复杂,STC推出的例程稍加修改即可。写入数据前要先进行删除才能写入。

EEPROM_SectorErase(IAP_Address);
EEPROM_write_n(IAP_Address,buffer,2);
读出数据:

 EEPROM_read_n(IAP_Address,buffer,2);

底层代码:

#include "config.h"
#include "eeprom.h"




//========================================================================
// 函数: void ISP_Disable(void)
// 描述: 禁止访问ISP/IAP.
// 参数: non.
// 返回: non.
// 版本: V1.0, 2012-10-22
//========================================================================
void DisableEEPROM(void)
{
ISP_CONTR = 0; //禁止ISP/IAP操作
ISP_CMD   = 0; //去除ISP/IAP命令
ISP_TRIG  = 0; //防止ISP/IAP命令误触发
ISP_ADDRH = 0xff; //清0地址高字节
ISP_ADDRL = 0xff; //清0地址低字节,指向非EEPROM区,防止误操作
}


//========================================================================
// 函数: void EEPROM_read_n(u16 EE_address,u8 *DataAddress,u16 number)
// 描述: 从指定EEPROM首地址读出n个字节放指定的缓冲.
// 参数: EE_address:  读出EEPROM的首地址.
//       DataAddress: 读出数据放缓冲的首地址.
//       number:      读出的字节长度.
// 返回: non.
// 版本: V1.0, 2012-10-22
//========================================================================


void EEPROM_read_n(u16 EE_address,u8 *DataAddress,u16 number)
{
EA = 0; //禁止中断
ISP_CONTR = (ISP_EN + ISP_WAIT_FREQUENCY); //设置等待时间,允许ISP/IAP操作,送一次就够
ISP_READ(); //送字节读命令,命令不需改变时,不需重新送命令
do
{
ISP_ADDRH = EE_address / 256; //送地址高字节(地址需要改变时才需重新送地址)
ISP_ADDRL = EE_address % 256; //送地址低字节
ISP_TRIG(); //先送5AH,再送A5H到ISP/IAP触发寄存器,每次都需要如此
//送完A5H后,ISP/IAP命令立即被触发启动
//CPU等待IAP完成后,才会继续执行程序。
_nop_();
*DataAddress = ISP_DATA; //读出的数据送往
EE_address++;
DataAddress++;
}while(--number);


DisableEEPROM();
EA = 1; //重新允许中断
}




//========================================================================
// 函数: void EEPROM_SectorErase(u16 EE_address)
// 描述: 把指定地址的EEPROM扇区擦除.
// 参数: EE_address:  要擦除的扇区EEPROM的地址.
// 返回: non.
// 版本: V1.0, 2013-5-10
//========================================================================
void EEPROM_SectorErase(u16 EE_address)
{
EA = 0; //禁止中断
//只有扇区擦除,没有字节擦除,512字节/扇区。
//扇区中任意一个字节地址都是扇区地址。
ISP_ADDRH = EE_address / 256; //送扇区地址高字节(地址需要改变时才需重新送地址)
ISP_ADDRL = EE_address % 256; //送扇区地址低字节
ISP_CONTR = (ISP_EN + ISP_WAIT_FREQUENCY); //设置等待时间,允许ISP/IAP操作,送一次就够
ISP_ERASE(); //送扇区擦除命令,命令不需改变时,不需重新送命令
ISP_TRIG();
_nop_();
DisableEEPROM();
EA = 1; //重新允许中断
}


//========================================================================
// 函数: void EEPROM_write_n(u16 EE_address,u8 *DataAddress,u16 number)
// 描述: 把缓冲的n个字节写入指定首地址的EEPROM.
// 参数: EE_address:  写入EEPROM的首地址.
//       DataAddress: 写入源数据的缓冲的首地址.
//       number:      写入的字节长度.
// 返回: non.
// 版本: V1.0, 2012-10-22
//========================================================================
void EEPROM_write_n(u16 EE_address,u8 *DataAddress,u16 number)
{
EA = 0; //禁止中断


ISP_CONTR = (ISP_EN + ISP_WAIT_FREQUENCY); //设置等待时间,允许ISP/IAP操作,送一次就够
ISP_WRITE(); //送字节写命令,命令不需改变时,不需重新送命令
do
{
ISP_ADDRH = EE_address / 256; //送地址高字节(地址需要改变时才需重新送地址)
ISP_ADDRL = EE_address % 256; //送地址低字节
ISP_DATA  = *DataAddress; //送数据到ISP_DATA,只有数据改变时才需重新送
ISP_TRIG();
_nop_();
EE_address++;
DataAddress++;
}while(--number);


DisableEEPROM();
EA = 1; //重新允许中断
}



工程师
2015-03-20 20:59:22     打赏
8楼

进程6:红外线遥控

   红外线遥控确实是有一定难度的进程了。由于红外接收对延时精度要求很高,且DIY板没有显示外设,调试工作难度很大。

    参考了STC官方例程,决定采用STC-ISP-15XX-V6.83.EXE自带的串口助手来调试。我的下载器是通过RS232电平转换器和PC机连接的,正好可以利用,硬件也无需做任何修改,就直接通过下载线返回串口助手。误打误着。

助手

这部分代码是STC官方发布的,拿来就用,希望对你也有帮助:

#include "reg52.h"
extern void BitTime(void);
sfr INT_CLKO = 0x8F;
sbit P_TXD1 = P3^1;
void Tx1Send(unsigned char dat);
//模拟串口发送
void Tx1Send(unsigned char dat) //9600,N,8,1 发送一个字节
{
unsigned char i;
P_TXD1 = 0;
BitTime();
i = 8;
do
{
dat >>= 1;
P_TXD1 = CY;
BitTime();
}while(--i);
P_TXD1 = 1;
BitTime(); //stop bit
BitTime(); //stop bit
}

调用方法就是:Tx1Send( dat);

红外解码:

#include "Exti.h"
#define Get_INT0  ((P3 & 0x04)^0x04)
#define testbit(var,bit) ((var)&(1<<(bit)))
#define setbit(var,bit)  ((var)|=(1<<(bit)))
#define clrbit(var,bit)  ((var)&=~(1<<(bit)))
sbit IRIN = P3^2;  
sbit led = P1^5; 
unsigned char IRCOM[4]=0;
bit flag=0;
bit flagcom=0; 
void delay014ms(unsigned char x);
void IR_init(void);
void delay014ms(unsigned char x) 
{
unsigned char i;
while(x--)
{
for (i = 0; i<125; i++) //13
     {;}
}
}
void IR_init(void)
{
   EA=1;
   EX0=1;                //允许总中断中断,使能 INT0 外部中断
   IT0=1;               //触发方式为脉冲负边沿触发   
   IRIN=1;               //I/O口初始化
}

void IR_CODE(void) interrupt 0 
{
unsigned char j,k,N=0;
     EX0 = 0;
delay014ms(15);
if (IRIN==1)
     { EX0 =1;
    return;
   }                    
while (!IRIN)           
    {delay014ms(1);}
for (j=0;j<4;j++)        
{
for (k=0;k<8;k++)   
{
   while (IRIN)           
     {delay014ms(1);}
    while (!IRIN)         
     {delay014ms(1);}
     while (IRIN)          
      {
    delay014ms(1);
    N++;        
    if (N>=30)
{ EX0=1;
return;}             
      }                                
     IRCOM[j]=IRCOM[j] >> 1;     
     if (N>=8) {IRCOM[j] = IRCOM[j] | 0x80;}
     N=0;
}
}
   if (IRCOM[2]!=~IRCOM[3]) 
   {
IRCOM[4]=0;
EX0=1;
      return;
    }
   flagcom = 1;   
   flag = !flag;//pro();
EX0=1;
return;
}

主程序调用红外接收数据:

if(flagcom!=0)
{  if( IRCOM[2]==0x01)Volume_Up();
 if( IRCOM[2]==0x07)Volume_Dn();
 if( IRCOM[2]==0x17)Volume_Mute();
      Tx1Send(IRCOM[0]);        //顺便把接收到的4Byte数据回显到串口助手
       Tx1Send(IRCOM[1]);
    Tx1Send(IRCOM[2]);
      Tx1Send(IRCOM[3]);
 flagcom=0;
  }

我的遥控器见下图,音量加的代码是:0X01,音量减的代码是0X07,静音的代码是0X17。

遥控器

EEPROM存储了音量和静音2个数据,如果当前状态是静音,关机后将保持静音状态。

点击下载DIY.rar


工程师
2015-03-22 16:16:54     打赏
9楼

进程7:试听 TPA3110  PK TDA2030

     今天开始试听。为了比较效果,使用功放DIY板 PK TDA2030功放板,耳机采用发烧级HD650,片源选择CD唱片电影《泰坦尼克号》配乐之1:《NEVER AN ABSOLUTION》。

DIY功放

                                                    PK

TDA2030


耳机

                                                HD650发烧耳机

      先试听功放DIY板,0:51“时出现的低音鼓声浑厚有劲。接下来的中音感觉圆浑,1:16”后的女高声清脆透亮,不足之处是歌手吸气时的口音略带细沙似的爆裂声。这可能与数字功放在处理ADC和DAC时转换速率不足有关吧。另外在播放过程调整音量时有时会出现点爆裂声响,这可能与LM4811数字音量控制有关吧?

    再听听TDA2030这款传统模拟功放的效果,它的低频力度感觉比TPA3110要差点,中音感觉平平,但是歌手吸气时的口音明显就没有那个爆裂声了。

    小结:

   TPA3110 数字功放效率高,虽然未装散热器,但温升很小,在低中频时力度不错,高音略显不足。

   TDA2030模拟功放效率低,没有散热片根本无法工作,低中频力度稍差,但高频时的失真明显要小些。

  水平有限,以上只是个人观点,不当之处请指正。

视频链接

视频中的声音只能是手机录制来自音箱的声音效果,与HD650耳机的听音效果是无法相比的。




共9条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]