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:2个 Tiva 板之间的 I2C 通信

Guru**** 2535750 points


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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/761409/tm4c123gh6pz-i2c-communication-between-2-tiva-board

器件型号:TM4C123GH6PZ

您好!

我是一名学生,我尝试使用 I2C 在两个 Tiva 板之间进行通信。我有两个疑问,一个与带有中断的 i2c 通信有关,另一个与使用 i2c 的来回通信有关。

疑问1.

我正在进行与中断的 I2C 通信、它正在工作。

下面给出的代码。

#include "stdio.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "hw_memmap.h"
#include "inc/hw_ints.h"
#include "driverlib/pin_map.h"
#include "inc/hw_types.h"
#include "driverlib/interrupt.h"
#include "driverlib/SysTick .h"
#include "driverlib/timer.h"
#include "inc/hw_NVIC.h"
#include "driverlib/timer.c"
#include "driverlib/SysTick .c"
#include "driverlib/adc.h"
#include "driverlib/debug.h"
#include "driverlib/uart.h"
#include "driverlib/rom.h"
#include "inc/hw_ints.h"
#include "driverlib/ssi.h"
#include "driverlib/i2c.h"
#include "inc/hw_i2c.h"
空延迟(int a);
 #define SLAVE_ADDRESS 0x20
int main()

 SysCtlClockSet (SYSCTL_SYSDIV_1_SYSCTL_USE_OSC |SYSCTL_XTAL_8MHZ|SYSCTL_OSC_MAIN);

SysCtlPeripheralEnable (SYSCTL_Periph_I2C0);
 while (!SysCtlPeripheralReady (SYSCTL_Periph_I2C0));
 SysCtlPeripheralEnable (SYSCTL_Periph_GPIOB);
 while (!SysCtlPeripheralReady (SYSCTL_Periph_GPIOB));
 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);

IntMasterEnable();
 I2CMasterIntEnable (I2C0_BASE);
 IntEnable (INT_I2C0);

while (1)
 {
I2CMasterSlaveAddrSet (I2C0_BASE、SLAVE_ADDRESS、FALSE);   
I2CMasterDataPut (I2C0_BASE、0xBB);
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_SINGLE_SEND);
  SysCtlDelay (1000);

}}

void I2C0_Handler (void){
uint32_t ui32Status;
ui32Status = I2CMasterIntStatus (I2C0_BASE、TRUE);//获取中断状态
I2CMasterSlaveAddrSet (I2C0_BASE、SLAVE_ADDRESS、FALSE);   
I2CMasterDataPut (I2C0_BASE、0xCC);
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_SINGLE_SEND);
//while (!I2CMasterBusy (I2C0_BASE));
I2CMasterIntClear (I2C0_BASE);//清除中断

我仅在主代码中使用中断。 我的疑问是 、如果我没有给出 while 循环内部或 while 循环外部突出显示的条件、那么中断处理程序函数也会执行。 如果我不使用这些命令、i2c 中断处理程序函数将不会执行、它将在 IntEnable (INT_I2C0)该命令中停止。 请告诉我发生这种情况的原因。 下面给出了从器件代码  

从器件代码

#include "stdio.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "hw_memmap.h"
#include "inc/hw_ints.h"
#include "driverlib/pin_map.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/uart.h"
#include "inc/hw_ints.h"
#include "driverlib/i2c.h"

void InitConsole (void);

int main()

 char 数据、char_rx、receive;

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) {
  
   char_rx=I2CSlaveDataGet (I2C0_BASE);
while (!(I2CSlaveStatus (I2C0_BASE)& I2C_SLAVE_ACT_RREQ));
  
   UARTCharPut (UART0_BASE、char_Rx);
  
 }}

空 InitConsole (空)
 {
 SysCtlPeripheralEnable (SYSCTL_Periph_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 ()、9600、(UART_CONFIG_WLEN_8|UART_CONFIG_STOP_ONE|UART_CONFIG_PAR_NONE));
 }

疑问2.

我想使用 i2c 在2个 Tiva 板之间来回发送数据、而不使用中断、我正在这样做。 我能够实现主机到从机的通信、但 AIM 是将相同的数据发送回主机并通过 UART 显示。 在串行监视器中、我得到了垃圾值。

代码如下所示

主器件代码  

#define SLAVE_ADDRESS 0x20
 void InitConsole (void);
 字符数据;
 
int main()

SysCtlClockSet (SYSCTL_SYSDIV_1_SYSCTL_USE_OSC |SYSCTAL_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);
 I2CMasterEnable (I2C0_BASE);

I2CMasterInitExpClk (I2C0_BASE、SysCtlClockGet ()、false);

while (1)
 {
I2CMasterSlaveAddrSet (I2C0_BASE、SLAVE_ADDRESS、FALSE);   
I2CMasterDataPut (I2C0_BASE、0xBB);
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_SINGLE_SEND);
//while (!I2CMasterBusy (I2C0_BASE));
while (I2CMasterBusy (I2C0_BASE));
I2CMasterSlaveAddrSet (I2C0_BASE、SLAVE_ADDRESS、TRUE);  
 I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_SINGLE_Receive);
 Data= I2CMasterDataGet (I2C0_BASE);
 while (I2CMasterBusy (I2C0_BASE));
 UARTCharPut (UART0_BASE、DATA);

}}

空 InitConsole (空)
 {
 SysCtlPeripheralEnable (SYSCTL_Periph_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));
 }  

从器件代码

int main()

 char 数据、char_rx、receive;

SysCtlClockSet (SYSCTL_SYSDIV_1_SYSCTL_USE_OSC|SYSCTL_XTAL_8MHZ|SYSCTL_OSC_MAIN);  
 InitConsole();

SysCtlPeripheralEnable (SYSCTL_Periph_I2C0);
 while (!SysCtlPeripheralReady (SYSCTL_Periph_I2C0));
 SysCtlPeripheralEnable (SYSCTL_Periph_GPIOB);
 while (!SysCtlPeripheralReady (SYSCTL_Periph_GPIOB));
 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) {

char_rx=I2CSlaveDataGet (I2C0_BASE);
 while (!(I2CSlaveStatus (I2C0_BASE)& I2C_SLAVE_ACT_RREQ));
  I2CSlaveDataPut (I2C0_BASE、char_Rx);
  
 }}

请告诉我问题是什么以及如何将其作为工作代码。 我是一名学生、在嵌入式 C 和 Tiva 方面也没有太多经验。 请帮帮我。 我希望有人能帮助我解决这些问题。

非常感谢您、

Mariya

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

    您好 Mariya、

    我并不真正理解您的疑问1、您能否尝试进一步解释、或者只发布工作版本和非工作版本、以便我进行比较?

    对于第2个问题、这是一个足够简单的解决方法。 您在这里拥有大多数正确的逻辑、但有几件事情是不符合顺序的、您缺少一个用于从器件的关键行。

    针对主端的修复:

    交换以下行、以便先等待、然后获取数据:

    Data= I2CMasterDataGet (I2C0_BASE);
    while (I2CMasterBusy (I2C0_BASE)); 

    针对从器件侧的修复:

    在 while (1)循环内使用以下4行:

    while (!(I2CSlaveStatus (I2C0_BASE)& I2C_SLAVE_ACT_RREQ);
    char_rx=I2CSlaveDataGet (I2C0_BASE);
    
    while (!(I2CSlaveStatus (I2C0_BASE)& I2C_SLAVE_ACT_TREQ)));
    I2CSlaveQ_Pus_DataBase;I2CslaveQ_I2Cx_Pus_Datapit_0
    

    这将使传输在板之间进行。

    此外、我建议发送一个 ASCII 字符、如0x41、这是'A'、以便您可以验证它是收到的实际数据。 由于您还没有任何错误处理、当主设备通电且从设备未通电时、它将读取垃圾数据、直到从设备通电、然后读取实际数据。

    顺便说一下、本应用手册可能对您有所帮助: www.ti.com/.../spma073.pdf

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

    您好!

    非常感谢您的回复。

    我在 I2C 中进行了这些更改(怀疑2)。但它仍然不在通信、并且在 while (!(I2CSlaveStatus (I2C0_BASE)& I2C_SLAVE_ACT_RREQ))处停止; 在从器件中执行此命令。请告诉我将出现什么问题。我们如何解决它。

    我并不真正理解您的疑问1、您能否尝试进一步解释、或者只发布工作版本和非工作版本、以便我进行比较?

    我将再次解释我的疑问。

    我首先给出的代码仅是工作代码。

    下面给出了不起作用的代码。

    #include "stdio.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/gpio.h"
    #include "hw_memmap.h"
    #include "inc/hw_ints.h"
    #include "driverlib/pin_map.h"
    #include "inc/hw_types.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/SysTick .h"
    #include "driverlib/timer.h"
    #include "inc/hw_NVIC.h"
    #include "driverlib/timer.c"
    #include "driverlib/SysTick .c"
    #include "driverlib/adc.h"
    #include "driverlib/debug.h"
    #include "driverlib/uart.h"
    #include "driverlib/rom.h"
    #include "inc/hw_ints.h"
    #include "driverlib/ssi.h"
    #include "driverlib/i2c.h"
    #include "inc/hw_i2c.h"
    空延迟(int a);
     #define SLAVE_ADDRESS 0x20
    int main()

     SysCtlClockSet (SYSCTL_SYSDIV_1_SYSCTL_USE_OSC |SYSCTL_XTAL_8MHZ|SYSCTL_OSC_MAIN);

    SysCtlPeripheralEnable (SYSCTL_Periph_I2C0);
     while (!SysCtlPeripheralReady (SYSCTL_Periph_I2C0));
     SysCtlPeripheralEnable (SYSCTL_Periph_GPIOB);
     while (!SysCtlPeripheralReady (SYSCTL_Periph_GPIOB));
     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);

    IntMasterEnable();

    I2CMasterIntEnable (I2C0_BASE);
     IntEnable (INT_I2C0);

    while (1)
     {

    void I2C0_Handler (void){
    uint32_t ui32Status;
    ui32Status = I2CMasterIntStatus (I2C0_BASE、TRUE);//获取中断状态
    I2CMasterSlaveAddrSet (I2C0_BASE、SLAVE_ADDRESS、FALSE);   
    I2CMasterDataPut (I2C0_BASE、0xCC);
    I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_SINGLE_SEND);
    //while (!I2CMasterBusy (I2C0_BASE));
    I2CMasterIntClear (I2C0_BASE);//清除中断

    我认为这将更好地了解工作代码和非工作代码之间的区别。 我怀疑第一个代码中突出显示的部分、如果我将其放置在 while 循环中、那么只有中断处理程序函数执行。 请解释发生这种情况的原因。

    两个从器件代码相同。

    非常感谢您、

    Mariya

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

    您好 Mariya、

    不起作用的代码没有执行任何操作、因为您在完成初始化后没有触发任何操作。 当您的 while 循环为空时、它就会位于那里。

    同时、工作代码会获取由 while (1)循环内的内容触发的第一个 I2C 事务、并从该操作开始运行。

    关于我提出的不起作用的建议、让我们简化一下、我将根据您的代码发布我已经拥有的.c 文件、以便您只需下载它们即可正确获取项目中的所有代码。

    主设备: e2e.ti.com/.../i2c_5F00_master.c

    从站: e2e.ti.com/.../i2c_5F00_slave.c

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

    您好、先生、

    非常感谢您的澄清。 现在、我了解了差异、并更好地了解了中断。  

    您发送的代码 与我的最新代码类似。 我重新接线了所有器件、再次刷写电路板的两个、现在它正在通信。

    非常感谢您帮助解决我的问题。

    谢谢、

    Mariya