// must be called in: // slave tx event callback // or after beginTransmission(address) size_t TwoWire::write(uint8_t data) { if(transmitting) { // in master transmitter mode // don't bother if buffer is full if(TX_BUFFER_FULL) { setWriteError(); return 0; } // put byte in tx buffer txBuffer[txWriteIndex] = data; txWriteIndex = (txWriteIndex + 1) % BUFFER_LENGTH; } else { // in slave send mode // reply to master if(TX_BUFFER_FULL) { I2CSlaveDataPut(SLAVE_BASE, txBuffer[txReadIndex]); txReadIndex = (txReadIndex + 1) % BUFFER_LENGTH; } txBuffer[txWriteIndex] = data; txWriteIndex = (txWriteIndex + 1) % BUFFER_LENGTH; } return 1; }
size_t TwoWire::write(uint8_t data) { if(TX_BUFFER_FULL && transmitting) return 0; if(TX_BUFFER_FULL && !transmitting) { I2CSlaveDataPut(I2C_BASE, txBuffer[txReadIndex]); txReadIndex = (txReadIndex + 1) % BUFFER_LENGTH; } txBuffer[txWriteIndex] = data; txWriteIndex = (txWriteIndex + 1) % BUFFER_LENGTH; return 1; }
void comm(void* data) { commData* myData = (commData*) data; uint32_t status = 0; uint32_t rx = 0; uint8_t tx = 0; while(1){ // status = I2CSlaveStatus(I2C1_BASE); // //See pgs. 178-179 for status meaning // if(status & I2C_SLAVE_ACT_TREQ){ tx = 5; I2CSlaveDataPut(I2C1_BASE,tx); // } // if(status & I2C_SLAVE_ACT_RREQ){ // rx = I2CSlaveDataGet(I2C1_BASE); // //TEST!!! // tx = rx + 1; // } } }
void ipmi_i2c_ram_dev_service(ipmi_i2c_ram_dev *dev, unsigned long status) { unsigned long slave_act_status; if (status) { slave_act_status = I2CSlaveStatus(dev->bus->i2c_hw_slave_base); // 读取从机状态 switch (slave_act_status) { case I2C_SLAVE_ACT_NONE: // 主机没有请求任何动作 break; case I2C_SLAVE_ACT_RREQ_FBR: // 主机已发送从机地址和数据地址首字节 dev->ram_reg_addr = I2CSlaveDataGet(dev->bus->i2c_hw_slave_base); dev->ram_reg_addr &= dev->ram_reg_size; break; case I2C_SLAVE_ACT_RREQ: // 主机已经发送数据到从机 dev->ram_reg[dev->ram_reg_addr++]= I2CSlaveDataGet(dev->bus->i2c_hw_slave_base); dev->ram_reg_addr &= dev->ram_reg_size; break; case I2C_SLAVE_ACT_TREQ: // 主机请求从机发送数据 if (0) { OSSemPend(dev->read_lock); // 等待从机数据准备好 } I2CSlaveDataPut(dev->bus->i2c_hw_slave_base, dev->ram_reg[dev->ram_reg_addr++]); dev->ram_reg_addr &= dev->ram_reg_size; break; default: break; } } if (0) /* TODO: 从机接收到全部数据,考虑最后一次写完成后使用定时器 */ { OSSemPost(dev->write_lock); } }
void i2c3_slave_interrupt(void) { unsigned long status = I2CSlaveIntStatusEx(I2C3_SLAVE_BASE, false); if (status & I2C_SLAVE_INT_START) { //Start condition } else if (status & I2C_SLAVE_INT_STOP) { //Stop condition } else if (status & I2C_SLAVE_INT_DATA) { //Data in or out status = I2CSlaveStatus(I2C3_SLAVE_BASE); if (status & I2C_SCSR_RREQ) { data_recv = I2CSlaveDataGet(I2C3_SLAVE_BASE); data_send = data_recv * 2; } else if (status & I2C_SCSR_TREQ) { I2CSlaveDataPut(I2C3_SLAVE_BASE, data_send); } } I2CSlaveIntClearEx(I2C3_SLAVE_BASE, status); }
void TwoWire::I2CIntHandler(void) { //clear data interrupt HWREG(SLAVE_BASE + I2C_O_SICR) = I2C_SICR_DATAIC; uint8_t startDetected = 0; uint8_t stopDetected = 0; if(HWREG(SLAVE_BASE + I2C_O_SRIS) & I2C_SLAVE_INT_START) { startDetected = 1; //clear raw start interrupt HWREG(SLAVE_BASE + I2C_O_SICR) = I2C_SICR_STARTIC; } else if(HWREG(SLAVE_BASE + I2C_O_SRIS) & I2C_SLAVE_INT_STOP) { stopDetected = 1; HWREG(SLAVE_BASE + I2C_O_SICR) = I2C_SICR_STOPIC; } switch(I2CSlaveStatus(SLAVE_BASE) & (I2C_SCSR_TREQ | I2C_SCSR_RREQ)) { case(I2C_SLAVE_ACT_RREQ)://data received if(I2CSlaveStatus(SLAVE_BASE) & I2C_SCSR_FBR) currentState = SLAVE_RX; if(!RX_BUFFER_FULL) { rxBuffer[rxWriteIndex] = I2CSlaveDataGet(SLAVE_BASE); rxWriteIndex = (rxWriteIndex + 1) % BUFFER_LENGTH; } break; case(I2C_SLAVE_ACT_TREQ)://data requested if(startDetected) { uint8_t oldWriteIndex = txWriteIndex; user_onRequest(); // // send data if onRequest() wrote data that has // yet to be sent // if(oldWriteIndex != txWriteIndex) { I2CSlaveDataPut(SLAVE_BASE, txBuffer[txReadIndex]); txReadIndex = (txReadIndex + 1) % BUFFER_LENGTH; } } else if(!TX_BUFFER_EMPTY) { I2CSlaveDataPut(SLAVE_BASE, txBuffer[txReadIndex]); txReadIndex = (txReadIndex + 1) % BUFFER_LENGTH; } else I2CSlaveDataPut(SLAVE_BASE, 0); break; default: break; } if(stopDetected && currentState == SLAVE_RX) { int avail = available(); user_onReceive(avail); currentState = IDLE; } }
//***************************************************************************** // // Configure the I2C0 master and slave and connect them using loopback mode. // //***************************************************************************** int main(void) { unsigned long ulDataTx[NUM_I2C_DATA]; unsigned long ulDataRx[NUM_I2C_DATA]; unsigned long ulindex; // // Set the clocking to run directly from the external crystal/oscillator. // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the // crystal on your board. // SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); // // The I2C0 peripheral must be enabled before use. // SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0); // // For this example I2C0 is used with PortB[3:2]. The actual port and // pins used may be different on your part, consult the data sheet for // more information. GPIO port B needs to be enabled so these pins can // be used. // TODO: change this to whichever GPIO port you are using. // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); // // Configure the pin muxing for I2C0 functions on port B2 and B3. // This step is not necessary if your part does not support pin muxing. // TODO: change this to select the port/pin you are using. // 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. // TODO: change this to select the port/pin you are using. // GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_2 | GPIO_PIN_3); // // Enable loopback mode. Loopback mode is a built in feature that is // useful for debugging I2C operations. It internally connects the I2C // master and slave terminals, which effectively let's you send data as // a master and receive data as a slave. // NOTE: For external I2C operation you will need to use external pullups // that are stronger than the internal pullups. Refer to the datasheet for // more information. // HWREG(I2C0_MASTER_BASE + I2C_O_MCR) |= 0x01; // // 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. // I2CMasterInitExpClk(I2C0_MASTER_BASE, SysCtlClockGet(), false); // // Enable the I2C0 slave module. This module is enabled only for testing // purposes. It does not need to be enabled for proper operation of the // I2Cx master module. // I2CSlaveEnable(I2C0_SLAVE_BASE); // // Set the slave address to SLAVE_ADDRESS. In loopback mode, it's an // arbitrary 7-bit number (set in a macro above) that is sent to the // I2CMasterSlaveAddrSet function. // I2CSlaveInit(I2C0_SLAVE_BASE, SLAVE_ADDRESS); // // Tell the master module what address it will place on the bus when // communicating with the slave. Set the address to SLAVE_ADDRESS // (as set in the slave module). The receive parameter is set to false // which indicates the I2C Master is initiating a writes to the slave. If // true, that would indicate that the I2C Master is initiating reads from // the slave. // I2CMasterSlaveAddrSet(I2C0_MASTER_BASE, SLAVE_ADDRESS, false); // // Set up the serial console to use for displaying messages. This is // just for this example program and is not needed for I2C operation. // InitConsole(); // // Display the example setup on the console. // UARTprintf("I2C Loopback Example ->"); UARTprintf("\n Module = I2C0"); UARTprintf("\n Mode = Single Send/Receive"); UARTprintf("\n Rate = 100kbps\n\n"); // // Initalize the data to send. // ulDataTx[0] = 'I'; ulDataTx[1] = '2'; ulDataTx[2] = 'C'; // // Initalize the receive buffer. // for(ulindex = 0; ulindex < NUM_I2C_DATA; ulindex++) { ulDataRx[ulindex] = 0; } // // Indicate the direction of the data. // UARTprintf("Tranferring from: Master -> Slave\n"); // // Send 3 peices of I2C data from the master to the slave. // for(ulindex = 0; ulindex < NUM_I2C_DATA; ulindex++) { // // Display the data that the I2C0 master is transferring. // UARTprintf(" Sending: '%c' . . . ", ulDataTx[ulindex]); // // Place the data to be sent in the data register // I2CMasterDataPut(I2C0_MASTER_BASE, ulDataTx[ulindex]); // // Initiate send of data from the master. Since the loopback // mode is enabled, the master and slave units are connected // allowing us to receive the same data that we sent out. // I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_SINGLE_SEND); // // Wait until the slave has received and acknowledged the data. // while(!(I2CSlaveStatus(I2C0_SLAVE_BASE) & I2C_SCSR_RREQ)) { } // // Read the data from the slave. // ulDataRx[ulindex] = I2CSlaveDataGet(I2C0_SLAVE_BASE); // // Wait until master module is done transferring. // while(I2CMasterBusy(I2C0_MASTER_BASE)) { } // // Display the data that the slave has received. // UARTprintf("Received: '%c'\n", ulDataRx[ulindex]); } // // Reset receive buffer. // for(ulindex = 0; ulindex < NUM_I2C_DATA; ulindex++) { ulDataRx[ulindex] = 0; } // // Indicate the direction of the data. // UARTprintf("\n\nTranferring from: Slave -> Master\n"); // // Modifiy the data direction to true, so that seeing the address will // indicate that the I2C Master is initiating a read from the slave. // I2CMasterSlaveAddrSet(I2C0_MASTER_BASE, SLAVE_ADDRESS, true); // // Do a dummy receive to make sure you don't get junk on the first receive. // I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE); // // Dummy acknowledge and wait for the receive request from the master. // This is done to clear any flags that should not be set. // while(!(I2CSlaveStatus(I2C0_SLAVE_BASE) & I2C_SLAVE_ACT_TREQ)) { } for(ulindex = 0; ulindex < NUM_I2C_DATA; ulindex++) { // // Display the data that I2C0 slave module is transferring. // UARTprintf(" Sending: '%c' . . . ", ulDataTx[ulindex]); // // Place the data to be sent in the data register // I2CSlaveDataPut(I2C0_SLAVE_BASE, ulDataTx[ulindex]); // // Tell the master to read data. // I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE); // // Wait until the slave is done sending data. // while(!(I2CSlaveStatus(I2C0_SLAVE_BASE) & I2C_SLAVE_ACT_TREQ)) { } // // Read the data from the master. // ulDataRx[ulindex] = I2CMasterDataGet(I2C0_MASTER_BASE); // // Display the data that the slave has received. // UARTprintf("Received: '%c'\n", ulDataRx[ulindex]); } // // Tell the user that the test is done. // UARTprintf("\nDone.\n\n"); // // Return no errors // return(0); }