TDA7541&&TDA7415调试小结

简介:   前两天看了下一个名为TDA7541的收音机芯片,这两天又在看一个名为TDA7415的音效芯片。把这两个芯片放在一起说,有点拗口,很容易弄混。但越是容易弄混的东西,又越得放在一起说,否则会越搞不清楚谁是谁。

  前两天看了下一个名为TDA7541的收音机芯片,这两天又在看一个名为TDA7415的音效芯片。把这两个芯片放在一起说,有点拗口,很容易弄混。但越是容易弄混的东西,又越得放在一起说,否则会越搞不清楚谁是谁。

  这两个看起来有点像双胞胎的片子都出自ST,或许不是双胞胎,没准还有一个TDA7451在哪里。它们弟兄两个都提供SPI或IIC接口,实际应用中可配置成使用SPI或者IIC。它们内部都有一堆寄存器,用于配置各种工作状态。需要小心的是,它们的这堆寄存器是只能写,不能读的。在调试7541时就想当然的以为可读可写。于是先写一把,再读出来看看,是否写进去了,结果读出来的值纹丝不动,又想当然的以为是IIC通讯有问题。IC有问题。结果仔细查看文档,发现它的读取似乎就只会返回一个值而已。误会了人家IIC那两根线。另外跟这个TDA7541配合使用的一个E2PROM也需要注意,是只能读不能写的,一写就坏事了。实践出真知,凡事可不能再想当然了。

  简单说一下TDA7541的使用流程,MCU读取与之配套使用的EEPROM,将读出的数据写到TDA7541里,算作初始化。接下来根据具体的情况修改7541内部几个寄存器实现相应的功能。csdn里有它的实例代码,可以参考一下。

  TDA7415内部的寄存器比较少,共32个,实际只会使用0~23和31这25个。其中0~23是功能寄存器,31寄存器是用于测试的。调试这个片子,建议先从测试寄存器入手,在其内部写入0x3E,这样就可以在相应的引脚上测得一个200KHz的信号。如果顺利到这一步,基本可以放心了,IIC通讯没有问题,写寄存器没有问题。千万记住,不要想当然的通过读取寄存器的方法来确定IIC通讯是否有问题。接下来就是按照它的文档配置那24个寄存器。

  这24个寄存器上电会被POR成0xFE,很多unused的bit保持它原来的状态,不要去动它。把能改的都改好了,基本上就能出声了。刚开始配置这些寄存器有点摸着石头过河的感觉,还好有浦工、林工、还有晓峰的支持,基本上还算顺利的就搞出声来了。当然出声只是初级阶段,它还能做很多事。过了这条河就是阳关道了,大胆往前走吧。

  为了调试方便,做了一个小工具,通过它可以快速配置内部各寄存器,也能假模假式的读取当前那些寄存器的值,截图如下。

                     image 

  截图中显示的那32个值,是成功初始化后的值。配置成如此这般,大概就能出声了。

  调试这两个芯片总觉得不太顺,有点点7451的意思。问题在哪里?首先是犯了经验主义的错误。经验有时的确能帮助解决问题,但迷信经验,反而会走弯路,比没有那些经验还要弯。其次是犯了投机主义的错误。偷懒惯了,总以为还能继续偷懒下去。总想着有别人现成的东西,拿来就用好了。事实上,没那么多投机取巧的好事。最后还犯了教条主义的错误。他们说是,其实未必就是,说不是,也未必真的不是。尽信书尚不如无书,何况是流言飞语,怎能奉为教条?凡事得实事求是才是。否则他一会儿说是,一会儿说不是,那到底是还是不是呢,自己只能晕头转向了。

  吃一堑,长一智。吸取教训,总结经验。过而能改,善莫大焉。

  最后贴上相关代码,仅供需要的同志参考。

 1  HANDLE ghTDAI2C  =  INVALID_HANDLE_VALUE;
 2  BOOL OpenTDAI2C();
 3  BOOL CloseTDAI2C();
 4  BOOL TDAInit();
 5  BOOL TDAI2CWrite(BYTE iOffset,BYTE iCount,BYTE  * pBuffer);
 6  BOOL TDAPseudoReadAllReg(BYTE  * pBuffer);
 7 
 8  static  BYTE TDA_REG_BUF_RESET[ 32 =  {
 9       0xFF , 0x00 , 0x0E , 0x3F ,
10       0xBF , 0x5E , 0xFF , 0xFF ,
11       0xFF , 0x3E , 0x7D , 0xDD ,
12       0x00 , 0x10 , 0x10 , 0x10 ,
13       0x10 , 0x1E , 0x10 , 0x10 ,
14       0x80 , 0x38 , 0x0E , 0xF0 ,
15       0xFE , 0xFE , 0xFE , 0xFE ,
16       0xFE , 0xFE , 0xFE , 0xFE
17  };
18 
19  static  BYTE TDA_REG_BUF[ 32 =  {
20       0xFF , 0x00 , 0x0E , 0x3F ,
21       0xBF , 0x5E , 0xFF , 0xFF ,
22       0xFF , 0x3E , 0x7D , 0xDD ,
23       0x00 , 0x10 , 0x10 , 0x10 ,
24       0x10 , 0x1E , 0x10 , 0x10 ,
25       0x80 , 0x38 , 0x0E , 0xF0 ,
26       0xFE , 0xFE , 0xFE , 0xFE ,
27       0xFE , 0xFE , 0xFE , 0xFE
28  };
29 
30  BOOL OpenTDAI2C()
31  {
32      ghTDAI2C  =  CreateFile(_T( " I2C1: " ),GENERIC_READ  |  GENERIC_WRITE, 0 , 0 ,OPEN_EXISTING, 0 , 0 );
33       return  (ghTDAI2C  !=  INVALID_HANDLE_VALUE);
34  }
35 
36  BOOL CloseTDAI2C()
37  {
38       if  (ghTDAI2C  !=  INVALID_HANDLE_VALUE)
39      {
40           return  CloseHandle(ghTDAI2C);
41      }
42       return  FALSE;
43  }
44 
45  BOOL TDAInit()
46  {
47       return  TDAI2CWrite( 0x0 , 32 ,TDA_REG_BUF_RESET);
48  }
49 
50  BOOL TDAI2CWrite(BYTE iOffset,BYTE iCount,BYTE  * pBuffer)
51  {
52      BOOL nRet = 0 ;
53      DWORD returned_bytes;
54      I2C_Param sendParam;
55      BYTE  * pWriteBuf;
56 
57      pWriteBuf  =   new  BYTE[iCount + 1 ];
58      pWriteBuf[ 0 =  iOffset;
59 
60       if  (iCount  >   1 )
61      {
62          pWriteBuf[ 0 +=   0x20 ;//超过一个字节需配置为连续写
63      }
64      
65      memcpy(pWriteBuf + 1 ,pBuffer,iCount);
66 
67      sendParam.DeviceAddr  =   0x8C ;
68      sendParam.nWriteByte  =  iCount + 1 ;
69      sendParam.pWriteBuffer  =  pWriteBuf;
70      sendParam.nPort  =   0 ;
71      sendParam.nMode  =   0 ;
72      sendParam.nTimeout      =   100 ;
73      
74      nRet  =  DeviceIoControl(ghTDAI2C,IOCTL_I2C_WRITE, & sendParam, sizeof (I2C_Param), 0 , 0 , & returned_bytes, 0 );
75      delete[] pWriteBuf;
76       if  (nRet)
77      {
78          iOffset  =  iOffset  &   0x1F ;//有效地址位
79          memcpy(TDA_REG_BUF + iOffset,pBuffer,iCount);
80           return  TRUE;
81      }
82       return  FALSE;
83  }
84 
85  BOOL TDAPseudoReadAllReg(BYTE  * pBuffer)
86  {
87       if  (pBuffer)
88      {
89          memcpy(pBuffer,TDA_REG_BUF, 32 );
90           return  TRUE;
91      }
92       else
93      {
94           return  FALSE;
95      }
96  }
目录
相关文章
|
1月前
|
C++
VS调试技巧
VS调试技巧
14 0
|
7月前
|
网络协议 C++
继续分享 5 个实用的 vs 调试技巧
继续分享 5 个实用的 vs 调试技巧
|
6月前
|
编译器
实用调试技巧(2)
实用调试技巧(2)
|
1天前
|
程序员
调试技巧vs2022
调试技巧vs2022
|
3月前
|
程序员
关于MSVS的实用调试技巧
关于MSVS的实用调试技巧
30 0
|
5月前
|
程序员 编译器
实用调试技巧(上)
实用调试技巧
|
6月前
|
程序员 Windows
实用调试技巧(1)
实用调试技巧(1)
|
8月前
|
程序员 编译器
|
数据采集 安全 程序员
实用调试技巧——“C”
实用调试技巧——“C”