主题中讨论的其他器件:TM4C1292NCPDT、 TM4C123、 TCA6416、
您好!
在原理图中、我将 通过 I2C 时钟和数据线 SCL 和 SDA 将 TM4C1292NCPDT 连接到 IO 扩展器 IC TCA9555PWR。
我尝试运行以下代码、将3个地址行都设置为高电平、这意味着地址为0x27:
#include
#include
#include
#include "inc/hw_i2c.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "driverlib/i2c.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "XDC/STD.h"
#include
uint32_t g_ui32SysClock;
bool bDiInitialized = false;
#define DI_SLAVEADDRESS 0x27
//初始化 I2C 模块0
空隙 InitI2C0 ( 空隙 )
{
//启用 I2C 模块0
SysCtlPeripheralEnable (SYSCTL_Periph_I2C0);
//重置模块
SysCtlPeripheralReset (SYSCTL_Periph_I2C0);
//启用包含 I2C 0的 GPIO 外设
SysCtlPeripheralEnable (SYSCTL_Periph_GPIOB);
// 为端口 B2和 B3上的 I2C0功能配置引脚多路复用。
GPIOPinConfigure 寄存器 (GPIO_PB2_I2C0SCL);
GPIOPinConfigure 寄存器 (GPIO_PB3_I2C0SDA);
//为这些引脚选择 I2C 功能。
GPIOPinTypeI2CSCL (GPIO_PORTB_BASE、GPIO_PIN_2);
GPIOPinTypeI2C (GPIO_PORTB_BASE、GPIO_PIN_3);
//启用并初始化 I2C0主机模块。 使用 I2C0模块的系统时钟。 最后一个参数设置 I2C 数据传输速率。
//如果为 false,则数据速率设置为100kbps,如果为 true,则数据速率 设置为400kbps。
//I2CMasterInitExpClk (I2C0_BASE、SysCtlClockGet ()、true);//用于400kbps tm4c123
I2CMasterInitExpClk (I2C0_BASE、 SysCtlClockFreqSet ((SYSCTL_XTAL_25MHz | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480)、120000000)、true);//对于400kbps tm4c129
//清除 I2C FIFO
//HWREG (I2C0_BASE + I2C_O_FIFOCTL)= 80008000;
}
//I2C Send 函数
//向指定的从设备发送 I2C 命令
空隙 I2CSend (uint8_t slave_addr、uint8_t num_of_args、...)
{
uint8_t i;
//告诉主模块什么时候它会在总线上放置什么地址
//正在与从器件通信。
I2CMasterSlaveAddrSet (I2C0_BASE、slave_addr、false);
//存储可变数量参数的列表
va_list vargs;
//指定 va_list 为"open"和最后一个固定参数 ,以便 vargs 知道开始查找的位置
va_start (vargs、num_of_args);
//将要发送的数据放入 FIFO 中
I2CMasterDataPut (I2C0_BASE、va_arg (vargs、uint32_t));
//如果只有一个参数,我们只需要使用 单个 send I2C 函数
如果 (num_of_args == 1)
{
//开始从 MCU 发送数据
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_SINGLE_SEND);
//等待 MCU 完成传输。
while 循环 (!( I2CMasterBusy (I2C0_BASE)));
while 循环 ( I2CMasterBusy (I2C0_BASE));
//"关闭"变量参数列表
va_end (vargs);
}
//否则,我们将在 I2C 总线上开始传输多个字节
方案
{
//开始从 MCU 发送数据
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_START);
//等待 MCU 完成传输。
while 循环 (!( I2CMasterBusy (I2C0_BASE)));
while 循环 ( I2CMasterBusy (I2C0_BASE));
//使用发送 num_of_args-2段数据
//I2C 模块的 BURST_SEND_CONT 命令
表示 (i = 1;i <(num_of_args - 1);i++)
{ //将下一段数据放入 I2C FIFO 中
I2CMasterDataPut (I2C0_BASE、va_arg (vargs、uint32_t));
//发送刚放入 FIFO 的下一个数据
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_CONT);
//等待 MCU 完成传输。
while 循环 (!( I2CMasterBusy (I2C0_BASE)));
while 循环 ( I2CMasterBusy (I2C0_BASE));
}
//将最后一段数据放入 I2C FIFO 中
I2CMasterDataPut (I2C0_BASE、va_arg (vargs、uint32_t));
//发送刚放入 FIFO 的下一个数据
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_FINISH);
//等待 MCU 完成传输。
while 循环 (!( I2CMasterBusy (I2C0_BASE)));
while 循环 ( I2CMasterBusy (I2C0_BASE));
//"关闭"变量 参数 列表
va_end (vargs);
}}
//通过 I2C 向指定的从设备发送一组数据
空隙 I2CSendString 的一个字符串 (uint32_t slave_addr、 特性 数组[])
{ //告诉主模块在 与从模块通信时它将在总线上放置的地址。
I2CMasterSlaveAddrSet (I2C0_BASE、slave_addr、false);
//将要发送的数据放入 FIFO 中
I2CMasterDataPut (I2C0_BASE、array[0]);
//如果只有一个参数,我们只需要使用
//单次发送 I2C 函数
如果 (array[1]=='\0')
{
//开始从 MCU 发送数据
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_SINGLE_SEND);
//等待 MCU 完成传输。
while 循环 (!( I2CMasterBusy (I2C0_BASE)));
while 循环 ( I2CMasterBusy (I2C0_BASE));
}
//否则,我们将在 I2C 总线上开始传输多个字节
方案
{ //开始从 MCU 发送数据
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_START);
//等待 MCU 完成传输。
while 循环 (!( I2CMasterBusy (I2C0_BASE)));
while 循环 ( I2CMasterBusy (I2C0_BASE));
//将索引初始化为数组
uint8_t i = 1;
//使用发送 num_of_args-2段数据
//I2C 模块的 BURST_SEND_CONT 命令
while 循环 (array[i + 1]!='\0')
{ //将下一段数据放入 I2C FIFO 中
I2CMasterDataPut (I2C0_BASE、array[I++]);
//发送刚放入 FIFO 的下一个数据
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_CONT);
//等待 MCU 完成传输。
while 循环 (!( I2CMasterBusy (I2C0_BASE)));
while 循环 ( I2CMasterBusy (I2C0_BASE));
}
//将最后一段数据放入 I2C FIFO 中
I2CMasterDataPut (I2C0_BASE、array[i]);
//发送刚放入 FIFO 的下一个数据
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_FINISH);
//等待 MCU 完成传输。
while 循环 (!( I2CMasterBusy (I2C0_BASE)));
while 循环 ( I2CMasterBusy (I2C0_BASE));
}}
//I2C 接收功能
//在从器件上读取指定的寄存器
uint32_t I2CReceive. (uint32_t slave_addr、uint8_t reg)
{ //指定我们要向写入(寄存器地址)
///从设备
I2CMasterSlaveAddrSet (I2C0_BASE、slave_addr、false);
//指定要读取的寄存器
I2CMasterDataPut (I2C0_BASE、reg);
//向从器件发送控制字节和寄存器地址字节
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_START);
//等待 MCU 完成事务
while 循环 ( I2CMasterBusy (I2C0_BASE));
//指定我们将从从属设备读取
I2CMasterSlaveAddrSet (I2C0_BASE、slave_addr、true);
//发送控制字节并从我们 指定的寄存器中读取
I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_SINGLE_RECEIVE);
//等待 MCU 完成事务
while 循环 (!( I2CMasterBusy (I2C0_BASE)));
while 循环 ( I2CMasterBusy (I2C0_BASE));
//返回从指定寄存器提取的数据
返回 I2CMasterDataGet (I2C0_BASE);
}}
空隙 主电源 ( 空隙 )
{ //将时钟设置为直接从外部晶体/振荡器运行。
G_ui32SysClock = SysCtlClockFreqSet ((SYSCTL_XTAL_25MHz |
SYSCTL_OSC_MAIN |
SYSCTL_USE_PLL |
SYSCTL_CFG_VCO_480)、120000000);
//初始化 I2C 模块0
InitI2C0 ();
I2CSend (DI_SLAVEADDRESS、3、0、0、0x01);
I2CSend (DI_SLAVEADDRESS、3、0x06、0x01、0);//配置端口0
while 循环 (1){};
}
但从示波器捕获可以看出、只有单个 I2C 发送命令看起来无效、而不是多个命令。
我在 CCS 的调试模式下检查了状态寄存器 I2C0MCS。 DATACK 和 ERROR 位设为低电平。
每个使用的上拉电阻器为2K。 没有将 ACK 显示为低电平的范围能力。
所以、我这次只按照您的建议对从器件进行一次 I2C 写入、即 I2CSend (DI_SLAVEADDRESS、 0 0、0、0x01) 、但示波器捕获保持不变。
此外、我尝试了函数 I2CSend (DI_SLAVEADDRESS、 1、0、0、0x01) 来传输一位、示波器捕获如下所示
此外、我将使用 ADUM3151隔离器的 Launchpad 和 EV-Board 以及 IO-Expander EVM (设置如下所示)进行测试。 我将 通过隔离器从 Launchpad 向 IO 扩展器 EVM 提供 I2C SCL、SDA 信号。
对于 IO 扩展器、我使用从器件地址为0x27 (原理图的屏幕截图如下所示)、因为 EV 板中的所有三个地址线(引脚2、3、21)均已上拉(我们已替换 IC TCA6416并在评估板中焊接 TCA9555PWR)。
但从示波器捕获可以看出、只有单个 I2C 发送命令看起来无效、而不是多个命令。
请提供相同的指南。
此致、
Kiranjit