I have been using code supplied by Keil to simulate I2C slaves and it works great......only problem.....its one device only. Using the VTREG's it does, I tried to modify the code by +1's on the call names, but that didn't work. I have at least 14 I2C slaves and would like the master to be able to simulate them all.....again it works if I adjust the I2C address for the single device I want to address. I'd like to try them all. Here is the original code:
// Simulation of I2C Memory (Slave) MAP V:0,V:0xFF READ WRITE // Map User Memory region DEFINE int SADR // Slave Address signal void I2CMEMORY (void) { unsigned long adr; adr = V:0; while (1) { wwatch (I2C_OUT); // Wait for data from Microcontroller while (I2C_OUT == 0x0100) { // START detected wwatch (I2C_OUT); // Wait for data from Microcontroller if (I2C_OUT > 0xFF) continue; if ((I2C_OUT >> 1) != SADR) continue; // test if Slave is addressed I2C_IN = 0xFF00; // ACK to Microcontroller if (I2C_OUT & 1) { // Slave Read while (1) { I2C_IN = _RBYTE(adr); // Read Byte from Memory adr++; // Increment Address wwatch (I2C_OUT); // Wait for ACK from Microcontroller if (I2C_OUT != 0xFF00) break; } } else { // Slave Write wwatch (I2C_OUT); // Wait for data from Microcontroller if (I2C_OUT > 0xFF) continue; adr = I2C_OUT | V:0; // Set Memory Address I2C_IN = 0xFF00; // ACK to Microcontroller while (1) { wwatch (I2C_OUT); // Wait for data from Microcontroller if (I2C_OUT > 0xFF) break; _WBYTE (adr, I2C_OUT); // Store Byte in Memory adr++; // Increment Address I2C_IN = 0xFF00; // ACK to Microcontroller } } } } } SADR = 0x51 I2CMemory()
I tried:
// Simulation of I2C Memory (Slave) MAP V:0,V:0xFF READ WRITE // Map User Memory region DEFINE int SADR // Slave Address signal void I2CMEMORY1 (void) { unsigned long adr; adr = V:0; while (1) { wwatch (I2C_OUT); // Wait for data from Microcontroller while (I2C_OUT == 0x0100) { // START detected wwatch (I2C_OUT); // Wait for data from Microcontroller if (I2C_OUT > 0xFF) continue; if ((I2C_OUT >> 1) != SADR) continue; // test if Slave is addressed I2C_IN = 0xFF00; // ACK to Microcontroller if (I2C_OUT & 1) { // Slave Read while (1) { I2C_IN = _RBYTE(adr); // Read Byte from Memory adr++; // Increment Address wwatch (I2C_OUT); // Wait for ACK from Microcontroller if (I2C_OUT != 0xFF00) break; } } else { // Slave Write wwatch (I2C_OUT); // Wait for data from Microcontroller if (I2C_OUT > 0xFF) continue; adr = I2C_OUT | V:0; // Set Memory Address I2C_IN = 0xFF00; // ACK to Microcontroller while (1) { wwatch (I2C_OUT); // Wait for data from Microcontroller if (I2C_OUT > 0xFF) break; _WBYTE (adr, I2C_OUT); // Store Byte in Memory adr++; // Increment Address I2C_IN = 0xFF00; // ACK to Microcontroller } } } } } SADR = 0x50 I2CMemory1() // Simulation of I2C Memory (Slave) signal void I2CMEMORY2 (void) { unsigned long adr; adr = V:10; while (1) { wwatch (I2C_OUT); // Wait for data from Microcontroller while (I2C_OUT == 0x0100) { // START detected wwatch (I2C_OUT); // Wait for data from Microcontroller if (I2C_OUT > 0xFF) continue; if ((I2C_OUT >> 1) != SADR) continue; // test if Slave is addressed I2C_IN = 0xFF00; // ACK to Microcontroller if (I2C_OUT & 1) { // Slave Read while (1) { I2C_IN = _RBYTE(adr); // Read Byte from Memory adr++; // Increment Address wwatch (I2C_OUT); // Wait for ACK from Microcontroller if (I2C_OUT != 0xFF00) break; } } else { // Slave Write wwatch (I2C_OUT); // Wait for data from Microcontroller if (I2C_OUT > 0xFF) continue; adr = I2C_OUT | V:0; // Set Memory Address I2C_IN = 0xFF00; // ACK to Microcontroller while (1) { wwatch (I2C_OUT); // Wait for data from Microcontroller if (I2C_OUT > 0xFF) break; _WBYTE (adr, I2C_OUT); // Store Byte in Memory adr++; // Increment Address I2C_IN = 0xFF00; // ACK to Microcontroller } } } } } SADR = 0x51 I2CMemory2()
The simulation doesn't crash, but the I2C interface doesn't work the interface properly anymore. Any thoughts on how to address this? I thought this would work since it is two different function in the same memory map space as local functions. I guess I'm missing something.
You must check the address and data fields inside from ONE service routine.
Depending which chip your tried to access different actions may happen.
For example using 4 IO-chips (PCA9555) the address decided which from this chips is written to or read from.
But the 'action' from processors 'point of view' is evereytime the same! ->i2c-isr.
good luck :)
Gunter, all of my code already works and follows what you said, my issue is Keil simulating several devices within the single .ini file. So the example code must be replicated 4 times with unique values and address for each "individual" slave. As it stands now, I have to save SADR = to the value of what is needed for each individual slave. Makes time consuming to test blocks of code, so adding several with w/r capability will make the simulation easy to work with.