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.

[参考译文] TMS320F280025C:driverlib I2C 读取不写入寄存器地址

Guru**** 2460850 points


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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1062174/tms320f280025c-driverlib-i2c-read-does-not-write-register-address

器件型号:TMS320F280025C

我尝试通过 I2C 读取霍尔效应传感器。 我的代码基于 driverlib 示例 i2c_ex5_master_slave_interrupt.c、示例2。

我可以在 Saleae 逻辑分析仪上看到写入是正确的。 但是、当我尝试读取时、传感器地址会正确放置在总线上、但寄存器地址不是。 它保持高电平、同时时钟脉冲。

saleae analysis

以下代码生成此序列:

#include "driverlib.h"
#include "device.h"
#include "board.h"


#include "i2cLib_FIFO_master_slave_interrupt.h"

//
// Defines
//

#define I2CA_SENSORADDRESS 0x35

#define I2CA_ADDRESS   0x30
#define I2CB_ADDRESS   0x40


//
// Globals
//
uint16_t status = 0;

struct I2CHandle I2CA;
struct I2CHandle I2CB;

//
// Function Prototypes
//
__interrupt void i2cAISR(void);
__interrupt void i2cAFIFOISR(void);

__interrupt void i2cBISR(void);
__interrupt void i2cBFIFOISR(void);

uint16_t AvailableI2C_slaves[MAX_I2C_IN_NETWORK];

uint16_t I2CA_TXdata[MAX_BUFFER_SIZE];
uint16_t I2CB_TXdata[MAX_BUFFER_SIZE];

uint16_t I2CA_RXdata[MAX_BUFFER_SIZE];
uint16_t I2CB_RXdata[MAX_BUFFER_SIZE];

uint32_t I2CA_ControlAddr;
uint32_t I2CB_ControlAddr;
uint16_t status;


//
// Main
//
void i2c_test(void)
{

    //
    // Board initialization
    //
    
    I2C_GPIO_init();
    
    //
    // Initialize PIE and clear PIE registers. Disables CPU interrupts.
    //
    Interrupt_initModule();
    
    //
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    //
    Interrupt_initVectorTable();
    
    I2Cinit();
    // Board_init();
    
    
    I2C_setOwnSlaveAddress(I2CA_BASE, I2CA_ADDRESS);
    I2C_setOwnSlaveAddress(I2CB_BASE, I2CB_ADDRESS);
    
    
    
    //I2Cs connected to I2CA will be found in AvailableI2C_slaves buffer
    //after you run I2CBusScan function.
    //When you run I2C BusScan you need to disable I2C interrupts and clear
    //the flag set during I2CBusScan
    //    uint16_t i;
    //
    //    for(i=0;i<MAX_I2C_IN_NETWORK;i++)
    //    {
    //        AvailableI2C_slaves[i] = 0;
    //    }
    //
    //    I2C_disableInterrupt(I2CA_BASE, (I2C_INT_ADDR_SLAVE|I2C_INT_STOP_CONDITION | I2C_INT_ARB_LOST | I2C_INT_NO_ACK));
    //    I2C_disableInterrupt(I2CB_BASE, (I2C_INT_ADDR_SLAVE|I2C_INT_STOP_CONDITION | I2C_INT_ARB_LOST | I2C_INT_NO_ACK));
    //
    //    uint16_t *pAvailableI2C_slaves = AvailableI2C_slaves;
    //    status = I2CBusScan(I2CA_BASE, pAvailableI2C_slaves);
    //
    //    I2C_clearStatus(I2CA_BASE,I2C_STS_NO_ACK|I2C_STS_ARB_LOST|I2C_STS_REG_ACCESS_RDY|I2C_STS_STOP_CONDITION);
    //    I2C_clearStatus(I2CB_BASE,I2C_STS_NO_ACK|I2C_STS_ARB_LOST|I2C_STS_REG_ACCESS_RDY|I2C_STS_STOP_CONDITION);
    //
    //    ESTOP0;
    //    I2C_disableInterrupt(I2CA_BASE, (I2C_INT_ADDR_SLAVE|I2C_INT_STOP_CONDITION | I2C_INT_ARB_LOST | I2C_INT_NO_ACK));
    //    I2C_disableInterrupt(I2CB_BASE, (I2C_INT_ADDR_SLAVE|I2C_INT_STOP_CONDITION | I2C_INT_ARB_LOST | I2C_INT_NO_ACK));
    //
    //    status = I2CBusScan(I2CB_BASE, pAvailableI2C_slaves);
    //
    //    I2C_clearStatus(I2CA_BASE,I2C_STS_NO_ACK|I2C_STS_ARB_LOST|I2C_STS_REG_ACCESS_RDY|I2C_STS_STOP_CONDITION);
    //    I2C_clearStatus(I2CB_BASE,I2C_STS_NO_ACK|I2C_STS_ARB_LOST|I2C_STS_REG_ACCESS_RDY|I2C_STS_STOP_CONDITION);
    
    I2C_clearStatus(I2CA_BASE,I2C_STS_NO_ACK|I2C_STS_ARB_LOST|I2C_STS_REG_ACCESS_RDY|I2C_STS_STOP_CONDITION);
    I2C_clearStatus(I2CB_BASE,I2C_STS_NO_ACK|I2C_STS_ARB_LOST|I2C_STS_REG_ACCESS_RDY|I2C_STS_STOP_CONDITION);
    
    I2C_enableInterrupt(I2CA_BASE, (I2C_INT_ADDR_SLAVE|I2C_INT_STOP_CONDITION | I2C_INT_ARB_LOST | I2C_INT_NO_ACK));
    I2C_enableInterrupt(I2CB_BASE, (I2C_INT_ADDR_SLAVE|I2C_INT_STOP_CONDITION | I2C_INT_ARB_LOST | I2C_INT_NO_ACK));
    
    
    //
    // Set I2C use, initializing it for FIFO mode
    //
    
    Interrupt_register(INT_I2CA, &i2cAISR);
    Interrupt_enable(INT_I2CA);
    
    Interrupt_register(INT_I2CB, &i2cBISR);
    Interrupt_enable(INT_I2CB);
    
    Interrupt_register(INT_I2CA_FIFO, &i2cAFIFOISR);
    Interrupt_enable(INT_I2CA_FIFO);
    
    Interrupt_register(INT_I2CB_FIFO, &i2cBFIFOISR);
    Interrupt_enable(INT_I2CB_FIFO);
    
    //
    // Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
    //
    EINT;
    ERTM;
    
    uint16_t i;
    for(i=0;i<MAX_BUFFER_SIZE;i++)
    {
        I2CA_TXdata[i] = 0;
        I2CA_RXdata[i] = 0;
        I2CB_TXdata[i] = 0;
        I2CB_RXdata[i] = 0;
    }
    
    I2CA.currentHandlePtr = &I2CA;
    I2CA.base             = I2CA_BASE;
    I2CA.SlaveAddr        = I2CA_SENSORADDRESS;
    I2CA.pControlAddr     = &I2CA_ControlAddr;
    I2CA.NumOfAddrBytes   = 1;
    I2CA.pTX_MsgBuffer    = I2CA_TXdata;
    I2CA.pRX_MsgBuffer    = I2CA_RXdata;
    I2CA.NumOfDataBytes   = 64;
    
    I2CB.currentHandlePtr = &I2CB;
    I2CB.base             = I2CB_BASE;
    I2CB.SlaveAddr        = I2CB_ADDRESS;
    I2CB.NumOfAddrBytes   = 4;
    I2CB.pControlAddr     = (uint32_t *)0;
    I2CB.pTX_MsgBuffer    = (uint16_t *)0;
    I2CB.pRX_MsgBuffer    = (uint16_t *)0;
    
    I2CA.pTX_MsgBuffer[0] = 0x00;
    I2CA.SlaveAddr = 0x00;
    I2CA.NumOfDataBytes = 1;
    I2CA_ControlAddr = 0x10;
    status = I2C_MasterTransmitter(&I2CA);
    
    // Wait for I2CA to be complete transmission of data
    while(I2C_getStatus(I2CA.base) & I2C_STS_BUS_BUSY);
    
    I2CA.SlaveAddr = I2CA_SENSORADDRESS;
    // I2CA.pTX_MsgBuffer[0] = 0x10; // register address
    I2CA.pTX_MsgBuffer[0] = 0b00000000; // set config register - all channels, full range, odd CP parity = 0x
    I2CA.pTX_MsgBuffer[1] = 0b10001001; // MOD1 register: master controlled mode, one byte read command, enabled interrupt, no collision avoidance, odd FP parity
    
    I2CA.NumOfDataBytes = 2;
    status = I2C_MasterTransmitter(&I2CA);
    
    // Wait for I2CA to be complete transmission of data
    while(I2C_getStatus(I2CA.base) & I2C_STS_BUS_BUSY);
    
    I2CA_ControlAddr = 0x00 | 0b00100000;
    // I2CA.pTX_MsgBuffer[0] = 0b00100000; // trigger after I2c write frame is finished
    I2CA.NumOfDataBytes = 0;
    status = I2C_MasterTransmitter(&I2CA);
    
    // Wait for I2CA to be complete transmission of data
    while(I2C_getStatus(I2CA.base) & I2C_STS_BUS_BUSY);
    
    SysCtl_delay(5000); //Adding delay for sensor conversion
    
    I2CA.NumOfDataBytes = 0;
    I2CA.pTX_MsgBuffer[0] = 0b00000000; // reset tx data
    I2CA_ControlAddr = 0b00000000;
    status = I2C_MasterReceiver(&I2CA);
    
    // Wait for I2CA to be complete transmission of data
    while(I2C_getStatus(I2CA.base) & I2C_STS_BUS_BUSY);
    
    ESTOP0;
}

我必须更改 I2C_MasterReceiver ()代码(创建和调用 I2C_TransmitSlaveAddress_ControlBytes_MasterReadBit()方法,该方法设置 I2C_MASTER_Receive_mode 而不是 I2C_MASTER_SEND_MODE)以将读取位发送为高电平,因为 WRITE 位已硬编码,这确实起作用。

我在总线上需要0x0 + ACK、但我得到了 OxFF + NACK。 读数应如下所示:

i2c protocol for readout

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

    您好!

    当 I2C 处于读取模式时、I2C 主设备不再传输任何字节。 它只需要来自 I2C 从设备的数据。 您读取0xFF 的原因是传感器未发送任何内容、上拉电阻器将引脚拉高。

    Unknown 说:
    我必须更改 I2C_MasterReceive_Bytes (该 I2C),而不是以创建 I2C_Write_Bytesn 模式(作为 I2C Dit_Write_Byte_Sit 模式)。

    恢复到原始 I2C_MasterReceiver 代码并尝试以下方法。

    I2CA.NumOfDataBytes = 1;//要接收的字节数

    I2CA_ControlAddr        = 0;//触发位+寄存器地址

    状态= I2C_MasterReceiver (&I2CA);

    下面是波形的外观:

    1) 1)起始条件+ 从器件地址+写入位+等待来自 I2C 从器件的 ACK

    2) 发送1个字节(触发位+寄存器地址) +等待来自 I2C 从器件的 ACK

    3) 3)重复起始条件+从器件地址+读取位+等待来自 I2C 从器件的 ACK。

    4) 4)从从器件接收数据字节+从主器件向从器件发送 ACK。

    5) 5)生成停止条件

    此致、

    曼诺伊

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

    您好、Manoj、

    感谢您的回复。 我已经尝试恢复到原始代码。 但是、只有写入模式中的传感器地址和0x00被发送(并被确认)。 在总线上看不到重复起始或步骤2之后的任何内容(并且在0x00写入后时钟不脉冲)。 上述所有波形步骤1-5是否都应该由对 I2C_MasterReceiver ()的单次调用生成?

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

    Alke、

    [引用 userid="507909" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/C2000-microcontrollers-forume/1062174/tms320f280025c-driverlib-i2c-read-do-we-te-write-register-address/3935610#3935610"]是否应通过调用 I2C_Masterquote 生成上述所有步骤[?]

    是的、没错!

    在示例 i2c_ex6_EEPROM_interrupt.c 中、显示了 I2C_MasterReceiver 函数的示例。 在这里、我有2个地址字节、两个字节都是0、然后我发送重复起始值来读取一个字节。

    在本例中、您需要设置 EEPROM.NumOfAddrBytes      = 1并设置 ControlAddr = Trigger bit + Register Address、然后运行 I2C_MasterReceiver (&EEPROM)。

       EEPROM.currentHandlePtr    =&EEPROM;
       EEPROM.SlaveAddr           = EEPROM_SLAVE_ADDRESS;
       EEPROM.WriteCycle_in_us = 10000;   对于 EEPROM、//6ms 此代码经过测试
       EEPROM.base                = I2CA_BASE;
       EEPROM.pControlAddr        =&ControlAddr;
       EEPROM.NumOfAddrBytes      = 2;

       //示例2:EEPROM 字节读取
       //确保11被写入 EEPROM 地址0x0
       ControlAddr = 0;
       EEPROM.pControlAddr  =&ControlAddr;
       EEPROM.prx_MsgBuffer = RX_MsgBuffer;
       EEPROM.NumOfDataBytes = 1;

       状态= I2C_MasterReceiver (&EEPROM);

    此致、

    曼诺伊