This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TFP410:通过 I2C 配置 HDMI/DVI 发送器时出现问题

Guru**** 2386020 points
Other Parts Discussed in Thread: TFP410, MSP430G2230
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/interface-group/interface/f/interface-forum/851103/tfp410-issues-configuring-hdmi-dvi-transmitter-over-i2c

器件型号:TFP410
主题中讨论的其他器件: MSP430G2230

我使用 TFP410连接外部 HDMI 监视器、该监视器设置为在上电时由 MSP430G2230微控制器通过 I2C 连接进行配置(请参阅原理图片段)。 我当前遇到的问题是、TFP410不会 ACK 任何命令(请参阅示波器屏幕截图)。 我的 SCL 以大约11kHz 的频率运行、我对 I2C 引脚进行了位拆裂。 我的代码如下:

main.c:

/*
* main.c
*
*创建日期:2019年9月26日
*
/

#include 
#include 

/* TFP410的子地址*/
#define CTL_1_MODE 0x08
#define CTL_2_MODE 0x09
#define CTL_3_MODE 0x0A
#define DE_DLY 0x32
#define DE_CTL 0x33
#define DE_TOP 0x34
#define DE_CNT_L 0x36 #define DE_CNT_MODE

0x37 #define


0x39 #define ADDR_CL_CL_#define 0x37 #define 0x39 #define 0x37 #define 0x39 #define ADDR_CL_CL_CL_CL_IN_CL_CL_#define 0x //写入地址

unsigned char sData = 0; //要写入从

器件的数据 int main (void){

WDTCTL = WDTPW | WDTHOLD; //停止看门狗

/*初始化时钟*/
BCSCTL3 |= LFXT1S_2; //选择 VLO 作为低频率时钟
if (CALBC1_1MHz == 0xFF){ //如果校准常数被擦除
while (1); //不加载,陷阱 CPU!!
}
DCOCTL = 0; //选择最低 DCOx 和 MODx 设置
BCSCTL1 = CALBC1_1MHz; //设置 DCO
DCOCTL = CALDCO_1MHz;

//等待 FPGA 初始化
_delay_cycles (10000);

/*配置 TFP410数字发送器*/

// 0x37、T.M.D.S.使能状态由 PD 确定
sData = 0x37;
I2C_WriteData (&sData、SLV_ADDR、CTL_1_MODE、1);
// 0x39、MSEN 输出被禁用、来自 HTPLG 的 MDI、MDI 逻辑电平保持不变
sData = 0x39;
I2C_WriteData (&sData、SLV_ADDR、CTL_2_MODE、1);
// 0x80、sData 去偏斜被禁用
sData = 0x80;
I2C_WriteData (&sData、SLV_ADDR、CTL_3_MODE、1);
// 0xD8、216像素(HSYNC +后沿)
sData = 0xD8;
I2C_WriteData (&sData、SLV_ADDR、DE_DLY、1);
// 0x70、DE 发生器启用、VSYNC 和 HSYNC 高电平有效
sData = 0x70;
I2C_WriteData (&sData、SLV_ADDR、DE_CTL、1);
// 0x1B、27像素(VSYNC +后沿)
sData = 0x1B;
I2C_WriteData (&sData、SLV_ADDR、DE_TOP、1);
// 0x20、0x03、800像素宽
sData = 0x20;
I2C_WriteData (&sData、SLV_ADDR、DE_CNT_L、1);
sData = 0x03;
I2C_WriteData (&sData、SLV_ADDR、DE_CNT_H、1);
// 0xE0、0x01 480行高
sData = 0xE0;
I2C_WriteData (&sData、SLV_ADDR、DE_LIN_L、1);
sData = 0x01;
I2C_WriteData (&sData、SLV_ADDR、DE_LIN_H、1);

//_delay_cycles (10000);

/*配置后的陷阱*/;
while (1);

} 

I2C_SW.c:

/*
i2c_sw.c
*
*创建时间:2019年10月1日
*
*/

#include "msp430.h"
#include "i2c_sw.h"

unsigned char read_scl (void);
unsigned char read_SDA (void);
void clear_scl (void);
void clear_SDA (void);

void I2C_Init (void);
void I2C_Start (void);
void I2C_Stop (void);

void I2C_Writebit (unsigned char bit);
unsigned char I2C_ReadByte

(unsigned char Data);
unsigned char I2C_ReadByte (void

I2C_WriteData);unsigned char Addr
* Data、unsigned char Addr、unsigned char DeviceRegister Addr、unsigned char DeviceRegister、unsigned char DeviceRegister、unsigned char DeviceLength (unsigned char Data、unsigned char Devicechar DeviceRegister、unsigned、unsigned char Devicechar DeviceRegister、Devicechar DeviceData)--

--------------/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/
函数:READ_SCL
用途 :将 SCL 设置为 SCL 的输入和返回电流逻辑电平(0或1)
NORMAL 为1,因为它由电阻器上拉
参数:无
返回 :SCL 引脚的逻辑电平-------------------------------------------------------
*/
unsigned char read_scl (void)
{
I2C_PxDIR &=~SCL;
return ((I2C_PxIN & SCL)!= 0);

}
/*---------------
函数:READ_SDA
用途 :将 SDA 设置为 SDA 的输入和返回电流逻辑电平(0或1),
NORMAL 为1,因为它由电阻器上拉
参数:无
返回 :SDA 管脚的逻辑电平
--------------------------- */
unsigned char read_SDA (void)
{
I2C_PxDIR &=~SDA;
return ((I2C_PxIN & SDA)!= 0);
}

/*---------------
函数:CLEAR_SCL
用途 :将 SCL 设置为输出,逻辑低
电平参数:无
返回 无:无
------------------------------------------------------------ */
void clear_SCL (void)
{
I2C_PxDIR |= SCL;
I2C_PxOUT &=~SCL;
}/*---------------

函数:clear_SDA
用途 :将 SDA 设置为输出,逻辑低
电平参数:无
返回 无:无
------------------------------------------------------------ */
void clear_SDA (void)
{
I2C_PxDIR |= SDA;
I2C_PxOUT &=~SDA;
}/*---------------

函数:I2C_Init
用途 :初始化 I2C 块
参数:
无返回 无:无
------------------------------------------------------------ */
void I2C_Init (void)
{
//将 SCL 和 SDA 配置为 GPIO
I2C_PxSEL &=~(SCL + SDA);
//将 SCL 和 SDA 设置为输入、通过电阻器将逻辑高电平拉高
I2C_PxDIR &=~(SCL + SDA);
I2C_PxOUT &=~(SCL + SDA);
}/*---------------

函数:I2C_Start
用途 :发送启动信号
参数:无
返回 无:无
------------------------------------------------------------ */
void I2C_Start (void)
{
READ_SDA(); //将 SDA 设置为1
I2C_DELAY ();
CLEAR_SDA(); //将 SDA 设置为0、当前 SCL 为1
I2C_DELAY ();
CLEAR_SCL (); //set SCL to 0 }/*--><!--kadov_tag{</spaces>}}-->将 SCL 设置为0
}/--><!--kadov_tag{</spaces>}--><!--kadov_tag{</spaces>}--><!--kadov_tag{</spaces>}}-->

函数:I2C_Stop
用途 :发送停止信号
参数:无
返回 无:无
------------------------------------------------------------ */
void I2C_Stop (void)
{
CLEAR_SDA(); //将 SDA 设置为0
I2C_DELAY ();
READ_SCL (); //将 SCL 设置为1
I2C_DELAY ();
READ_SDA(); //set SDA to 1 }/*--><!--kadov_tag{</spaces>}}-->将 SDA 设置为1 }/*--><!--kadov_tag{</spaces>}--><!--kadov_tag{</spaces>}--><!--kadov_tag{</spaces>}--><!--kadov_tag{</spaces>}}-->


函数:I2C_Writebit
用途 :将位写入 I2C 总线
参数:要写入
的位返回 无:无
------------------------------------------------------------ */
void I2C_Writebit (unsigned char bit)
{
if (位)
READ_SDA();
其他
CLEAR_SDA();
I2C_DELAY ();
READ_SCL ();
I2C_DELAY ();
CLEAR_SCL ();}/*--><!--kadov_tag{</spaces>}}-->


函数:I2C_Readbit
用途 :I2C 总线
参数上的读取位:无
返回 :无符号字符
------------------------------------------------------- */
unsigned char I2C_Readbit (void)
{
unsigned char 位;
//让从器件驱动数据
READ_SDA();
I2C_DELAY ();
READ_SCL ();
位= READ_SDA ();
I2C_DELAY ();
CLEAR_SCL ();
返回位;}/*--><!--kadov_tag{{</spaces>}--><!--kadov_tag{</spaces>}}-->


函数:I2C_WriteByte
用途 :将一个字节写入 I2C 总线
参数:unsigned char 数据
返回 无:无
------------------------------------------------------------ */
void I2C_WriteByte (unsigned char Data)
{
unsigned char nBit;

对于(nBit = 0;nBit < 8;nBit++)
{
I2C_Writebit ((Data & 0x80)!= 0);
数据<<= 1;
}
I2C_Readbit();// Write NACK
}
/*-->---------------
函数:I2C_ReadByte
用途 :读取 I2C 总线
参数上的字节:无
返回 :无符号字符
------------------------------------------------------- */
unsigned char I2C_ReadByte (void)
{
unsigned char buff = 0;
unsigned char nBit;

对于(nBit = 0;nBit < 8;nBit++)
{
buff =(buff << 1)| I2C_Readbit();
}
返回缓冲区;}/*--><!--kadov_tag{{</spaces>}--><!--kadov_tag{</spaces>}}-->


函数:I2C_WriteData
用途 :将 n 个字节写入 I2C 总线
参数:数据 -要写入的数据的指针
DeviceAddr -器件地址
寄存器 -寄存器地址
n 长度 -
要写入的字节数返回值 无:无
------------------------------------------------------------ //
void I2C_WriteData (unsigned char *数据、unsigned char DeviceAddr、unsigned char 寄存器、unsigned char nLength)
{
unsigned char nIndex;
I2C_Start();
I2C_WriteByte (DeviceAddr << 1);// DeviceAddr 为7位且命令为写入
I2C_WriteByte (寄存器);
for (nIndex = 0;nIndex < nLength;nIndex++)
{
I2C_WriteByte (*(数据+ nIndex));
}
I2C_Readbit();
I2C_Stop();}/*--><!--kadov_tag{</spaces>}}-->


函数:I2C_ReadData
用途 :从 I2C 总线
参数中读取 n 个字节:buff -用于存储值的缓冲区指针
视频地址-器件地址
寄存器 -寄存器地址
n 长度 -
要读取的字节数返回值 无:无
------------------------------------------------------------ //
空 I2C_ReadData (unsigned char *缓冲区、unsigned char DeviceAddr、unsigned char 寄存器、unsigned char nLength)
{
unsigned char nIndex;
I2C_Start();
I2C_WriteByte (DeviceAddr << 1);
I2C_WriteByte (寄存器);
I2C_Stop ();
_NOP(); //短延迟
I2C_Start();
_NOP(); //短延迟
I2C_WriteByte ((DeviceAddr << 1)| 1);
for (nIndex = 0;nIndex < nLength;nIndex++)
{
*(buff + nIndex)= I2C_ReadByte ();
if (nIndex > 0) I2C_Writebit (ACK);
}
I2C_Writebit (NACK);
I2C_Stop();
} 

原理图片段:


 


示波器屏幕截图:


 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Isaiah、

    您似乎缺少 SCL/SDA 上所需的5k 外部上拉电阻器。 您可以尝试添加它们吗?

    此外、您的应用是否确实需要此器件的 i2c? 对该器件使用 i2c 的主要原因是当 DVI/HDMI 源不生成 DE 时、DE 发生器。 其他一切都是引脚可配置的。

    此致、

    I.K.  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 I.K.:

    微控制器旁边的 I2C 信号上有两个4.53k 上拉电阻(请参阅原理图片段)。  

    我的控制器没有可用的 DE 信号、因此我需要使用 I2C 来配置内置的 DE 发生器。 否则、我会按照您的建议在硬件中进行配置、这是我在意识到没有 DE 信号之前最初计划的配置。  

    谢谢你

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Isaiah、

    我的错误是、我查看了电平转换器、错过了 MCU 侧的上拉电阻。  

    当电平转换器位于总线上时、我以前见过与其他器件的 i2c 通信问题。 您是否可以在没有电平转换器的情况下尝试 TFP410的 i2c 通信?  

    此外、下面是一个有关排除 i2c 问题的有用文档: http://www.ti.com/lit/an/scaa106/scaa106.pdf

    此致、

    I.K.  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用 user="I.K. 阿尼亚姆"]

    您好 Isaiah、

    我的错误是、我查看了电平转换器、错过了 MCU 侧的上拉电阻。  

    当电平转换器位于总线上时、我以前见过与其他器件的 i2c 通信问题。 您是否可以在没有电平转换器的情况下尝试 TFP410的 i2c 通信?  

    此外、下面是一个有关排除 i2c 问题的有用文档: http://www.ti.com/lit/an/scaa106/scaa106.pdf

    此致、

    I.K.  

    [/报价]

    尊敬的 I.K.:

    我今天下午能够删除电平转换器(我实际上没有在该版本中使用它)。 遗憾的是、它没有任何影响-我仍然没有收到来自 TFP410的任何 ACK。 此外、我发布的示波器快照可以直接查看 TFP410的引脚、因此它肯定会接收 I2C 通信。 然而,出于某种原因,它似乎忽略了它。 无论是地址问题、硬件问题还是其他问题、我都不确定、这就是我发布代码和原理图的原因。 在我继续之前、您或 TI 的其他人能否确认这两项中的任何一项或两项都正确?

    非常感谢、
    Isaiah Washburn

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我对这篇双篇文章表示歉意、但我只是注意到一些看起来非常奇怪的事情。 如果您看一下示波器屏幕截图、在波形之后、我觉得我发送的是地址0xE0 (0b11100000)而不是0x70。 但是、示波器串行解码器仍将其读取为0x70。 我在这里错过了什么?  

    我认为 i2c_sw.c 中的第201行可能存在故障:

    I2C_WriteByte (DeviceAddr << 1);// DeviceAddr 为7位且命令为写入 

    我的 DeviceAddr 已配置为0x70、其中包括 WRITE 位。 这意味着它已经有效地向左移位一个位置、因此再次向左移位将地址更改为0xE0。 当然、TFP410不会对此做出响应。 我将在今晚进行更改(将器件地址更改为0x38或0x00111000)、看看它是否解决了问题。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Isaiah、

    我同意您的评估。 波形显示为0xE0、因为地址有一个额外的左移位。 这似乎是问题的根本原因。 尽管如此、我不确定解码器为什么会将其视为0x70。 请告诉我您的更改是否解决了问题。  

    此致、

    I.K.  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    将 SLV_ADDR (main.c 中的第23行)更改为0x38 (7位地址、末尾没有 R/W 位)似乎已经解决了问题-我现在正在从 TFP410接收 ACK! 仍然没有视频输出、但我认为这是另一个线程的问题。 感谢您的支持!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    很高兴看到这解决了问题。 我怀疑无视频输出问题可能与 DE 或 HPD 有关。 但是、如果您仍然遇到问题、请随时打开另一个主题。

    此致、

    I.K.

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我在此处创建了有关"无信号"问题的后续主题:

    https://e2e.ti.com/support/interface/f/138/t/852086