LM3S9B92 I2C 作主机访问其他芯片,能读但不能写



先贴上程序

void SkI2cInit (void)
{
// The I2C0 peripheral must be enabled before use.
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
GPIOPinConfigure(GPIO_PB2_I2C0SCL);
GPIOPinConfigure(GPIO_PB3_I2C0SDA);
// Select the I2C function for these pins. This function will also
// configure the GPIO pins pins for I2C operation, setting them to
// open-drain operation with weak pull-ups. Consult the data sheet
// to see which functions are allocated per pin.
ROM_GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_2 | GPIO_PIN_3);
// Enable and initialize the I2C0 master module. Use the system clock for
// the I2C0 module. The last parameter sets the I2C data transfer rate.
// If false the data rate is set to 100kbps and if true the data rate will
// be set to 400kbps. For this example we will use a data rate of 100kbps.
ROM_I2CMasterInitExpClk(I2C0_MASTER_BASE, ROM_SysCtlClockGet(), false);
}

void I2cWriteByte(unsigned char deviceID,unsigned char offset,unsigned value)
{
ROM_I2CMasterSlaveAddrSet(I2C0_MASTER_BASE, deviceID, false);
ROM_I2CMasterDataPut(I2C0_MASTER_BASE, offset);
ROM_I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_SINGLE_SEND);
while(ROM_I2CMasterBusy(I2C0_MASTER_BASE))
{
}


ROM_I2CMasterDataPut(I2C0_MASTER_BASE, value);
ROM_I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_SINGLE_SEND);
while(ROM_I2CMasterBusy(I2C0_MASTER_BASE))
{
}

}

unsigned char I2cReadByte(unsigned char deviceID,unsigned char offset)
{
unsigned char value;
ROM_I2CMasterSlaveAddrSet(I2C0_MASTER_BASE, deviceID, false);
//This function will set the address that the I2C Master will place on the bus when initiating a
//transaction. When the bReceive parameter is set to true, the address will indicate that the
//I2C Master is initiating a read from the slave; otherwise the address will indicate that the I2C
//Master is initiating a write to the slave.
ROM_I2CMasterDataPut(I2C0_MASTER_BASE, offset);//Transmits a byte from the I2C Master
ROM_I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_SINGLE_SEND);//Controls the state of the I2C Master module.
while(ROM_I2CMasterBusy(I2C0_MASTER_BASE))//Indicates whether or not the I2C Master is not-busy.
{
}


ROM_I2CMasterSlaveAddrSet(I2C0_MASTER_BASE, deviceID, true);
ROM_I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
while(ROM_I2CMasterBusy(I2C0_MASTER_BASE))
{
}
value=ROM_I2CMasterDataGet(I2C0_MASTER_BASE);//Receives a byte that has been sent to the I2C Master.
return (value);
}
//*****************************************************************************
//
// Print "Hello world!" to the UART on the Stellaris evaluation board.
//
//*****************************************************************************
int
main(void)
{
unsigned char buffer=0;
//
// Set the clocking to run directly from the crystal.
//
ROM_SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
SYSCTL_XTAL_16MHZ);

//
// Initialize the UART.
//
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
GPIOPinConfigure(GPIO_PA0_U0RX);
GPIOPinConfigure(GPIO_PA1_U0TX);
ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
UARTStdioInit(0);

SkI2cInit();

// Hello!
//
UARTprintf("\033[2JHello World!\n");

while(1)
{
//I2cWriteByte(0x64>>1,0x08,0x23);
buffer=I2cReadByte(0x64>>1,0x08);
UARTprintf("Received:%02x\n",buffer);
}
}

以下是此芯片的I2C时序

现在我单独调用I2cReadByte();通过串口打印UARTprintf()能读到该芯片的ID寄存器以及其他默认不为0的寄存器的值;

但是我先用I2cWriteByte();写某个寄存器,再用I2cReadByte();读出这个寄存器的值发现读不到这个寄存器的值,很奇怪,请大家帮我分析分析

另外Stellaris® Peripheral Driver Library USER’S GUIDE 文档中 “I2CMasterControl()” 此函数的用法大家有详细说明吗?以下命令:

I2C_MASTER_CMD_SINGLE_SEND
I2C_MASTER_CMD_SINGLE_RECEIVE
I2C_MASTER_CMD_BURST_SEND_START
I2C_MASTER_CMD_BURST_SEND_CONT
I2C_MASTER_CMD_BURST_SEND_FINISH
I2C_MASTER_CMD_BURST_SEND_ERROR_STOP
I2C_MASTER_CMD_BURST_RECEIVE_START
I2C_MASTER_CMD_BURST_RECEIVE_CONT
I2C_MASTER_CMD_BURST_RECEIVE_FINISH
I2C_MASTER_CMD_BURST_RECEIVE_ERROR_STOP
I2C_MASTER_CMD_QUICK_COMMAND
I2C_MASTER_CMD_HS_MASTER_CODE_SEND

都是怎么用的?

非常感谢!

  • 楼主,

       I2C从设备的寄存器是可读的吧。 我觉得可能还是因为没有按照从设备的I2C寄存的读取规范。至于楼主列的那些命令的含义,楼主可以参考stellarisware里面的driverlib中的源代码,这几个命令其实就是代表着往寄存器I2CMCS中写入的值, 楼主可以参考下面的值,在datasheet的表15-5(Write Field Decoding for I2CMCS[3:0] Field)中查找相应值的含义。

    #define I2C_MASTER_CMD_SINGLE_SEND \
    0x00000007
    #define I2C_MASTER_CMD_SINGLE_RECEIVE \
    0x00000007
    #define I2C_MASTER_CMD_BURST_SEND_START \
    0x00000003
    #define I2C_MASTER_CMD_BURST_SEND_CONT \
    0x00000001
    #define I2C_MASTER_CMD_BURST_SEND_FINISH \
    0x00000005
    #define I2C_MASTER_CMD_BURST_SEND_STOP \
    0x00000004
    #define I2C_MASTER_CMD_BURST_SEND_ERROR_STOP \
    0x00000004
    #define I2C_MASTER_CMD_BURST_RECEIVE_START \
    0x0000000b
    #define I2C_MASTER_CMD_BURST_RECEIVE_CONT \
    0x00000009
    #define I2C_MASTER_CMD_BURST_RECEIVE_FINISH \
    0x00000005
    #define I2C_MASTER_CMD_BURST_RECEIVE_ERROR_STOP \
    0x00000004
    #define I2C_MASTER_CMD_QUICK_COMMAND \
    0x00000027
    #define I2C_MASTER_CMD_HS_MASTER_CODE_SEND \
    0x00000011

  • 寄存器是可读写的,而且I2C的读写时序(帖子中已经贴出来了)也是对的。我在TI源代码中找找看相关例子

  • 如果楼主对时序理解正确,我觉得就是几个命令字使用的问题了,建议楼主研究一下命令字的含义,我列出几个楼主可能可以用到的,然后按照时序图应该就可以了:

                 I2C_MASTER_CMD_SINGLE_SEND:    start, data和stop相都有的

                  I2C_MASTER_CMD_SINGLE_RECEIVE :start, data和stop相都有的

                  I2C_MASTER_CMD_BURST_SEND_START :有start和data相,没有stop相

                  I2C_MASTER_CMD_BURST_SEND_CONT:只有data相,  

                  I2C_MASTER_CMD_BURST_SEND_FINISH :有data相和stop相,没有start相

                  I2C_MASTER_CMD_BURST_SEND_STOP :只有stop相

    I2C_MASTER_CMD_BURST_RECEIVE_START, I2C_MASTER_CMD_BURST_RECEIVE_CONT,I2C_MASTER_CMD_BURST_RECEIVE_FINISH

    ,I2C_MASTER_CMD_BURST_RECEIVE_ERROR_STOP可以参考上面

  • 问题已经解决,谢谢