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.

[参考译文] 编译器/TM4C123GH6PZ:两个使用 I2C 的 Tiva 板之间的通信

Guru**** 2609955 points


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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/757464/compiler-tm4c123gh6pz-communication-between-two-tiva-board-using-i2c

器件型号:TM4C123GH6PZ

工具/软件:TI C/C++编译器

您好、先生、

我使用两个 Tiva 板、一个充当主器件、另一个充当从器件。我尝试将一些字符串从主器件发送到从器件、然后从器件将相同的数据发送回主器件并通过 UART 显示数据、 但我无法发回数据。

当我尝试从主器件向从器件发送数据时、数据通过 UART 正确读取。 但是、当我尝试将相同的数据发回主设备时、它无法正常工作。请帮助我解决问题。

下面给出了主代码、

#define SLAVE_ADDRESS 0x20
//void InitConsole (void);
unsigned long k=0;
void InitConsole (void);

uint32_t n=3、i;
char char_tx[]="abc";
CHAR Peripheral_Rx[3]、DATA;

int main ()
{
SysCtlClockSet (SYSCTL_SYSDIV_1_SYSCTL_USE_OSC | SYSCTL_8MHZ|SYSCTL_MAIN);

InitConsole ();
SysCtl_Periph_I2CPeriptl Enable (SysCtl_I2CPeriph_I2CPeriph_while
)
;SysCtlPeripheralCtl0 (SYSC_SYSC_OPTL_OPTH);SysCtlPeripheral0_0 (SYIPB_SYSC_OPTH)
while (!SysCtlPeripheralReady (SYSCTL_Periph_GPIOB));
//配置多路复用和 GPIO 设置以将 SSI 功能输出到引脚
GPIOPinTypeI2CSCL (GPIO_PORTB_BASE、GPIO_PIN_2);
GPIOPinTypeI2C (GPIO_PORTB_BASE、GPIO_PIN_C0SCL)
;GPIOPIN_PB2_GPIOP2PM_CI_CI2);配置 GPIOPIN_C0SCL
GPIOPinConfigure (GPIO_PB3_I2C0SDA);
I2CMasterEnable (I2C0_BASE);

I2CMasterInitExpClk (I2C0_BASE、SysClockGet ()、false);

while (1)
{
I2CMasterI2C SlaveAddrSet (I2CM0_BASE、SLAVE_ADDRESS、I2CMCK_ADDRESS)



;while (I2CM2CM0_PRIST0)/ PRIM_SEND/ PRIM_TO_PRIM_0_PRIM_0




)=发送完成/ I2CM0/ I2CM0/ I2CM0_PRIM_PRIM_PRIM_TO_PRIM_0_PRIM_END/(PRIM_PRIM_TO_TO_0_0_PRIM_TO_0_0_PRIM_
while (I2CMasterBusy (I2C0_BASE));

}
else{

I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_START);

//等待 MCU 完成传输。
while (I2CMasterBusy (I2C0_BASE));

I2CMasterSlaveAddrSet (I2C0_BASE、SLAVE_ADDRESS、TRUE);
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_RIVE_START);
char_Rx[0]= I2CMasterDataGet (I2CM0
);I2CMaster_BASE (I2CM0);while (I2CM0)
UARTCharPut (UART0_BASE、char_Rx[0]);

while (char_TX[I + 1]!='\0')
for (i=1;i 'j');="" }

从器件代码

int main ()
{
char data、char_rx[5]、receive;
// uint32_t pui32DataTx;
uint32_t n=3、i;
//uint32_t pui32DataRx[5];
///uint32_t ui32Period;
SysCtl_SYSDIV_1|SYSCTL_USE_OSC|SYSCTAL_XTAL_8MHZ|SYSCTL_OSC_MAIN);//seting 系统时钟为8MHz
;
//将 SysCtl_IPB0_GPIO0_PHI





引脚配置为 SYSCB_PHIL_GPIO0_PHI 引脚
;//将 SysCtl_GPIOPT_GPIO0_GPIOPT_PHIN (SYSCB_PHIN)引脚配置为 SYSCIP_PHIN_PHIL_PHIL_PHIL_PHIL_PHIL_GPIOPT_PHIN (SYSC0_GPIOPT_GPIOPT_PHIN);//


GPIOPinConfigure (GPIO_PB3_I2C0SDA);
I2CSlaveAddressSet (I2C0_BASE、0、0x20);
I2CSlaveInit (I2C0_BASE、0x20);
I2CSlaveEnable (I2C0_BASE);
while (1){
//
//////将要发送的数据放置在 I2Cslave+寄存器中

、


直到接收到 I2+(I2+);I2Cslave+(I2+= 0);I2+= I2+= I2+(I = I = I = I = I = I = I = I = I = I = I = I = I = I = 0)。
while (!(I2CSlaveStatus (I2C0_BASE)& I2C_SLAVE_ACT_RREQ);

I2CSlaveDataPut (I2C0_BASE、CHAR_Rx[i]);
while (!(I2CSlaveStatus (I2C0_BASE)& I2C_SLAVE_ACT_TREQ))))));

}

}} 

谢谢、

Alphy

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

    您是否在两个 LaunchPad 中的一个上拉电阻器上安装了外部上拉电阻器? I2C 需要上拉电阻器才能工作。

    此外、我没有看到从器件的任何 UART 代码、所以您能否共享该代码以便我可以使用 UART 输出对其进行测试?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Alphy、

    我知道您可能因为假期而被带走、但请在下周之前告知我们、如果需要在您休假回来之前继续讨论此主题、或者我们是否可以在问题得到解决后将其关闭。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、先生、

    我上个星期休假了,所以我无法回复。 很抱歉耽误你的回答。

    1.您是否在两个 LaunchPad 的其中一个上安装了外部上拉电阻器? I2C 需要上拉电阻器才能工作。

    是的、先生、我使用 的是外部上拉电阻器。

    2、 我没有看到任何从器件的 UART 代码、所以您可以共享该代码、以便我可以使用 UART 输出对其进行测试吗?

    没有、SIR、我没有在从设备中添加任何 UART 代码、因为我要将 UART 连接到主设备。

    我要做的是将数据从主器件发送到从器件、从器件将相同的数据发送回主器件、并且 UART 连接到主器件、因此通过 UART 应该显示任何数据、我将从从从器件发回主器件。 因此、在这种情况下、我没有将 UART 连接到从器件。

    我单独尝试了主设备到从设备的通信 、不管我从主设备发送的数据是什么 、它都可以正常工作、在从设备中正确接收并通过 UART 显示。 我所面临的问题是从从器件将相同的数据发送回主器件。

    谢谢、

    Alphy

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

    您好、先生、

    我正在等待您的回复。请帮助我解决问题。

    我尝试从器件向主器件发送数据、这也很正常。我在从主器件向从器件发送数据并将相同数据发送回从器件时遇到问题。请帮助我尽快解决问题。

    谢谢、

    Alphy

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

    我必须自行设置具有上拉电阻的 LaunchPad、才能运行您的代码。 遗憾的是、您发布的代码甚至不能从主器件正确发送到从器件。 您能否上传验证主设备到从设备通信的代码? 从这里、我们可以添加将接收到的从器件数据发送回主器件、这将是最快的方法、因为您以前确实进行了主器件到从器件的通信。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、先生、

    非常感谢您提供最快的回复。

    是的、主席先生、修改工作代码很容易。

    工作代码如下所示。

    主器件代码

    #define SLAVE_ADDRESS 0x20
    int main()

    uint32_t n=3、i;
    char char tx[]="abcd";


    SysCtlClockSet (SYSCTL_SYSDIV_1_SYSCTL_USE_OSC |SYSCTAL_XTAL_8MHZ|SYSCTL_OSC_MAIN);//将系统时钟设置为8MHz

    SysCtlPeripheralEnable (SYSCTL_Periph_I2C0);
    while (!SysCtlPeripheralReady (SYSCTL_Periph_I2C0));
    SysCtlPeripheralEnable (SYSCTL_Periph_GPIOB);
    while (!SysCtlPeripheralReady (SYSCTL_Periph_GPIOB));
    //配置多路复用和 GPIO 设置、将 SSI 功能输出到引脚
    GPIOPinTypeI2CSCL (GPIO_PORTB_BASE、GPIO_PIN_2);
    GPIOPinTypeI2C (GPIO_PORTB_BASE、GPIO_PIN_3);
    GPIOPinConfigure (GPIO_PB2_I2C0SCL);
    GPIOPinConfigure (GPIO_PB3_I2C0SDA);
    I2CMasterEnable (I2C0_BASE);

    I2CMasterInitExpClk (I2C0_BASE、SysCtlClockGet ()、false);

    while (1)

    I2CMasterSlaveAddrSet (I2C0_BASE、SLAVE_ADDRESS、FALSE);

    if (char_TX[1]='\0')

    //从 MCU 发起数据发送
    I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_SINGLE_SEND);

    //等待 MCU 完成传输。
    while (I2CMasterBusy (I2C0_BASE));

    否则{

    I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_START);

    //等待 MCU 完成传输。
    while (I2CMasterBusy (I2C0_BASE));

    for (i=1 <n;i++)

    //将下一段数据放入 I2C FIFO 中
    I2CMasterDataPut (I2C0_BASE、char_TX[i]);

    //发送刚刚放置到 FIFO 中的下一个数据
    I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_CONT);
    //
    ////等待 MCU 完成传输。
    while (I2CMasterBusy (I2C0_BASE));
    // i++;

    I2CMasterDataPut (I2C0_BASE、char_TX[n]);

    //发送刚刚放置到 FIFO 中的下一个数据
    I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_FINISH);
    while (I2CMasterBusy (I2C0_BASE));

    }}}

    从器件代码

    int main()

    char 数据、char_rx[5]、接收;
    // uint32_t pui32DataTx;
    uint32_t n=5、i;
    //uint32_t pui32DataRx[5];
    //uint32_t ui32Period;
    SysCtlClockSet (SYSCTL_SYSDIV_1_SYSCTL_USE_OSC|SYSCTL_XTAL_8MHZ|SYSCTL_OSC_MAIN);//将系统时钟设置为8MHz
    InitConsole();

    SysCtlPeripheralEnable (SYSCTL_Periph_I2C0);
    while (!SysCtlPeripheralReady (SYSCTL_Periph_I2C0));
    SysCtlPeripheralEnable (SYSCTL_Periph_GPIOB);
    while (!SysCtlPeripheralReady (SYSCTL_Periph_GPIOB));
    //配置多路复用和 GPIO 设置、将 SSI 功能输出到引脚
    GPIOPinTypeI2CSCL (GPIO_PORTB_BASE、GPIO_PIN_2);
    GPIOPinTypeI2C (GPIO_PORTB_BASE、GPIO_PIN_3);
    GPIOPinConfigure (GPIO_PB2_I2C0SCL);
    GPIOPinConfigure (GPIO_PB3_I2C0SDA);
    I2CSlaveAddressSet (I2C0_BASE、0、0x20);
    I2CSlaveInit (I2C0_BASE、0x20);
    I2CSlaveEnable (I2C0_BASE);

    while (1){
    //
    //将要发送的数据放在数据寄存器中
    //
    for (i=0;i<=n;i++){
    //pui32DataRx[i]= I2CSlaveDataGet (I2C0_BASE);
    char_rx[i]= I2CSlaveDataGet (I2C0_BASE);
    //等待从机接收并确认数据。
    while (!(I2CSlaveStatus (I2C0_BASE)& I2C_SLAVE_ACT_RREQ));
    UARTCharPut (UART0_BASE、char_rx[i]);
    }}}

    //

    //UART 功能、用于显示从主器件发送的数据

    //

    空 InitConsole (空)

    //
    //启用 UART0模块。
    //
    SysCtlPeripheralEnable (SYSCTL_Periph_UART0);
    //
    //等待 UART0模块准备就绪。
    //
    while (!SysCtlPeripheralReady (SYSCTL_Periph_UART0));
    SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA);
    while (!SysCtlPeripheralReady (SYSCTL_Periph_GPIOA));
    GPIOPinConfigure (GPIO_PA0_U0RX);
    GPIOPinConfigure (GPIO_PA1_U0TX);
    GPIOPinTypeUART (GPIO_Porta_base、GPIO_PIN_0 | GPIO_PIN_1);
    UARTConfigSetExpClk (UART0_BASE、SysCtlClockGet ()、115200、(UART_CONFIG_WLEN_8|UART_CONFIG_STOP_ONE|UART_CONFIG_PAR_NONE));
    UARTCharPut (UART0_BASE、"J");

    谢谢、

    Alphy

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

    感谢您共享工作代码、让您更容易看到您最初发布的代码发生了什么情况。

    问题的核心是您为尝试来回发送数据而设置的逻辑与您使用的命令不匹配。 您正在尝试突发发送、但在尝试突发接收之前、一次只发送一个字节。 但是、这些命令的目的是一次发送或接收多个字节、它们的使用方式不正确。 从器件最终看不到突发命令的正确结束、而是 NAK 是发送的数据的第一个字节、这会停止传输。 当我更改您发布的第一个代码以不中断突发发送时、它能够再次正确传输。

    为了完成回送接收数据的实施、您有两个可用选项。 我将对其进行描述、以便您可以选择最适合您的选项。

    1) 1)以突发方式发送所有数据、然后以突发方式接收所有数据。 如果完成此操作、我建议使用标头字节将预期的字节数告知从器件、这样您就可以确保接收到所有需要的数据。

    2) 2)使用 I2C_MASTER_CMD_SINGLE_SEND 和 I2C_MASTER_CMD_SINGLE_Receive、且当前逻辑为 SEND 1、接收1 (将需要一些微调)。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、先生、  

    感谢您的快速回复。

    我对您提到的更改有一些疑问。

    从器件最终看不到突发命令的正确结束、而是 NAK 是发送的数据的第一个字节、这会停止传输。

    主席先生,请向我解释我需要在从代码中做些什么来使它正常工作。

    2.用猝发发送所有数据,然后用猝发接收所有数据。 如果完成此操作、我建议使用标头字节将预期的字节数告知从器件、这样您就可以确保接收到所有需要的数据。

    我正在尝试使用此方法。 主席先生、请说明我如何实现标头字节逻辑。

    谢谢、

    Alphy

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

    我建议您阅读我们有关 I2C 的应用手册、以更好地了解您需要做的事情、其中介绍了如何使用突发模式以及其他事项: www.ti.com/.../spma073.pdf

    标头字节逻辑很简单、发送的每个数据包中只有第一个字节或两个字节是发送的数据量。 如果发送的字节不超过255、则为一个字节;如果超过该字节、则为两个字节(0xFF = 255、因此在不使用两个字节的情况下无法指示更大的传输)。 然后在从器件上、一旦接收到该字节、从器件将在接收到完整数据包之前知道需要更多的字节、以便它可以知道传输何时完成、并允许它回显数据。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、先生、

    非常感谢您支持我解决该问题。

    我用红色标记了您提供的文档、使我更好地理解了它。 阅读完文档后、我清楚地了解了我需要遵循的正确沟通步骤。

    再次感谢您的帮助。

    在不使用标头字节逻辑的情况下、我进行了通信。 但我仍然不理解如何实现标头字节逻辑。

    标头字节逻辑很简单、发送的每个数据包中只有第一个字节或两个字节是发送的数据量。 这是我感到困惑的地方。我不知道如何发送标头字节中的数据量。

    如果您不介意、请使用示例进行说明。

    谢谢、

    Alphy

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

    其背后的想法是、如果您是主器件、则应该知道要从缓冲区发送多少字节的数据。 假设您有一个宽度为50个空格的缓冲区。 如果您的进程需要发送该缓冲区的前15个字节、您就知道了。 因此、在发送缓冲区字节之前、您开始 I2C 通信、然后发送一个字节来表示您首先发送的数据的长度。 "15"(或十六进制、0x0F)。

    然后、在发送该'header'字节后、您立即发送缓冲区数据。 因此、从器件总共接收16个字节。 "header"字节为"15"、表示接下来将跟随15个字节的数据、然后是预期的15个字节的数据。

    这也使您能够防止丢失的数据字节、就像您仅接收到14个字节一样、您知道发生了错误、然后从器件可以向主器件指示这种情况。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、先生、

    现在、我更好地了解了标头字节概念。 我在我的代码中尝试过它、它工作正常。

    非常感谢您花宝贵的时间进行详细的解释。 我不熟悉嵌入、这就是为什么标头字节概念对我来说很困难的原因。

    主席先生,再次感谢你。

    谢谢、

    Alphy