【发布时间】:2014-07-09 17:14:45
【问题描述】:
在 Tiva(Texas Instruments Cortex M4F ARM)TM4C129XNCZAD 上,我的 I2C 接口有问题。我通过端口 K 启用了 I2C 模块 4 上的主设备和通过端口 B 启用 I2C 模块 6 上的从设备。我已将两个 I2C 模块互连。使用德州仪器驱动程序库,我尝试使用 I2C_MASTER_CMD_SINGLE_SEND 命令发送 1 个字节。我花了很多时间让它工作,但 SCK 线保持低逻辑电平。我完全按照 TivaWare™ Peripheral Driver Library USER'S GUIDE 进行操作,但通信不起作用。有人有这方面的经验吗?
这是我的代码:
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_i2c.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/i2c.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#include "inc/tm4c129xnczad.h"
#define SLAVE_ADDRESS 0x3C
void delay (void)
{
volatile uint32_t ui32Loop;
for(ui32Loop = 0; ui32Loop < 200000; ui32Loop++);
}
volatile uint32_t result;
int main (void)
{
SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
//
// Enable the GPIO port that is used for the on-board LED.
//
SYSCTL_RCGCGPIO_R = SYSCTL_RCGCGPIO_R3 | SYSCTL_RCGCGPIO_R9 | SYSCTL_RCGCGPIO_R1;
//
// Do a dummy read to insert a few cycles after enabling the peripheral.
//
result = SYSCTL_RCGCGPIO_R;
//
// Enable the GPIO pin for the LED (PD3). Set the direction as output, and
// enable the GPIO pin for digital function.
//
GPIO_PORTD_AHB_DIR_R = 0x8;
GPIO_PORTD_AHB_DEN_R = 0x8;
GPIO_PORTK_DEN_R = 0xC0; // Enable Port K for I2C module 4
GPIO_PORTB_AHB_DEN_R = 0xC0; // Enable Port B for I2C module 6
SYSCTL_RCGCI2C_R = (1 << 4) | (1 << 6); // Mode Clock Gating Control for I2C modules 4 and 6
GPIO_PORTK_AFSEL_R = 0xC0; // Alternate Function Select PK6, PK7
GPIO_PORTB_AHB_AFSEL_R = 0xC0; // Alternate Function Select PB6, PB7
GPIOPinConfigure(GPIO_PK6_I2C4SCL);
GPIOPinConfigure(GPIO_PK7_I2C4SDA);
GPIOPinConfigure(GPIO_PB6_I2C6SCL);
GPIOPinConfigure(GPIO_PB7_I2C6SDA);
GPIOPinTypeI2C(GPIO_PORTK_BASE, 7); // Configurtes SDA
GPIOPinTypeI2CSCL(GPIO_PORTK_BASE, 6); // Configurtes SCL
GPIOPinTypeI2C(GPIO_PORTB_BASE, 7); // Configurtes SDA
GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, 6); // Configurtes SCL
I2CMasterInitExpClk(I2C4_BASE, SysCtlClockGet(), false);
I2CSlaveEnable(I2C6_BASE);
I2CSlaveInit(I2C6_BASE, SLAVE_ADDRESS);
I2CMasterSlaveAddrSet(I2C4_BASE, SLAVE_ADDRESS, false);
//
// Loop forever.
//
while(1)
{
//
// Turn on the LED.
//
GPIO_PORTD_AHB_DATA_R |= 0x8;
I2CMasterDataPut(I2C4_BASE, 0x33);
I2CMasterControl(I2C4_BASE, I2C_MASTER_CMD_SINGLE_SEND);
//
// Wait until the slave has received and acknowledged the data.
//
while(!(I2CSlaveStatus(I2C6_BASE) & I2C_SLAVE_ACT_RREQ));
//
// Read the data from the slave.
//
result = I2CSlaveDataGet(I2C6_BASE);
//
// Wait until master module is done transferring.
//
while(I2CMasterBusy(I2C4_BASE));
//
// Delay for a bit.
//
delay ();
//
// Turn off the LED.
//
GPIO_PORTD_AHB_DATA_R &= ~(0x8);
//
// Delay for a bit.
//
delay ();
}
}
【问题讨论】:
-
你在 I2C 线上加了上拉电阻吗? I2C 是一个集电极开路信号系统,因此总线需要上拉电阻才能工作。对于您的测试,您可能可以启用 GPIO 的内部上拉(如果可用)。
-
程序 GPIOPinTypeI2C() 打开内部上拉电阻,但 SDA 线在高电平等待。问题出在我的 SCL 方面。
-
函数
GPIOPinTypeI2CSCL呢?为两个 SCL 引脚(主/从)调用它。这可以解释为什么 SDA 可以,但 SCL 不行。 -
如果这些函数被轮询,那么您可能无法按照您希望的方式执行此操作。 I2C 从机可能会延长时钟,直到您调用
I2CSlaveDataGet函数,但您的代码可能会在等待能够发送的早期 I2C 主机调用之一上被阻塞。我对这部分的 I2C 驱动程序不够熟悉,无法诊断是否是问题所在。 -
还要考虑到 I2C 操作的软件精度非常重要。 I2C 是一种反复无常的总线,设备也是。如果您说将错误的地址推送到 BUS 并且没有从机应答,那么在您的主机端,它是一些错误状态,它会立即卡在某个地方,直到状态/错误得到正确处理。请注意这样的事情。
标签: c embedded arm microcontroller