Nointerrupt and Wire Bus I2C

Hello
ill have some question
about
nointerrupt and I2C wire bus.

my idea is some sensible code of my project save with Nointerrupt


// beginn sensible code

noInterrupts();

for(int i = 0; i < E_I2C2_MAX; i++)
{
help = digitalRead(i);
if(help == bitRead(signale_momentan[i/32],i%32))
{
bitWrite(signale_entprellt[i/32],(i%32),help);

}
bitWrite(signale_momentan[i/32],(i%32),help);
}

interrupts();

//end of sensible code


also ill use the
Wire.onRequest(requestEvent);

but the problem ist Nointerrupts(); and interrupts();
dont work for this.
when Wire.onRequest(requestEvent); starts he jump out of the sensible code and do the request event.

my question:
is there some idea that Wire.onRequest(requestEvent); didnt break the sensible code lines?

thanks for some ideas too this.

Read this before posting a programming question

Code tags please.

Post all your code.

when Wire.onRequest(requestEvent); starts he jump out of the sensible code and do the request event.

How do you know this?

hello Nick

this is the code.


#include <Wire.h>
#include "c:\\temp\\signals.h"

//#define DEBUG

unsigned long signale_momentan[MAX_ANZAHL_SIGNALE_SPEICHER_UL]; //wahre groesse: 1+E_I2C2_MAX/8
unsigned long signale_entprellt[MAX_ANZAHL_SIGNALE_SPEICHER_UL];

void setup()
{
  
  
  for(int i = 0; i < E_I2C2_MAX; i++)
  {
    pinMode(i, INPUT);  
  }

  Wire.begin(I2C2);                // join i2c bus with address #2
  Wire.onRequest(requestEvent); // register event
#ifdef DEBUG  
  Serial.begin(9600);  // start serial for output
#endif
  
  for(int i = 0; i < E_I2C2_MAX; i++)
  {
    bitWrite(signale_entprellt[i/32],(i%32),i%2/*digitalRead(i)*/);
    bitWrite(signale_momentan[i/32],(i/32),i%2/*digitalRead(i)*/); 
  }
}

void loop()
{
  int help;
  
  delay(20);
  
  //noInterrupts();
  
  for(int i = 0; i < E_I2C2_MAX; i++)
  {
    help = digitalRead(i);
    if(help == bitRead(signale_momentan[i/32],i%32))
    {
      bitWrite(signale_entprellt[i/32],(i%32),help);
      
    }
    bitWrite(signale_momentan[i/32],(i%32),help);
  }
  
  //interrupts();
  
#ifdef DEBUG  
  Serial.println(signale_entprellt[0],BIN);
  Serial.println(signale_entprellt[1],BIN);
  Serial.println(sizeof(unsigned long));
  delay(1000);
#endif

#ifdef DEBUG 
  signale_entprellt[0] = 0x12345678;
  signale_entprellt[1] = 0x87654321;
#endif
  
}

// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent()
{
  uint8_t* adress;
  
  adress = (uint8_t*) signale_entprellt;
  
  Wire.write(adress,sizeof(signale_entprellt));

}

when Wire.onRequest(requestEvent); starts he jump out of the sensible code and do the request event.

How do you know this?

ill tested it with delay function
between the no interupt tags

F.e

noInterrupts();
 
  for(int i = 0; i < E_I2C2_MAX; i++)
  {
    help = digitalRead(i);
    if(help == bitRead(signale_momentan[i/32],i%32))
    {
      bitWrite(signale_entprellt[i/32],(i%32),help);
     
    }
    bitWrite(signale_momentan[i/32],(i%32),help);
  }
  delay(5000);
  interrupts();

if i am right the programcounter wait 5 sec between noInterrupts() and interrupts()

the request events start every 0.5 second.
so 5 seconds long the requestevent cant recive data.
but in tests , the master at IC2 bus get every 0,5 seconds data from the slave.

so my opinion is noInterrupts() and interrupts() did not work for Wire interrupts.

thx
Thomas

delay() doesn't work with interrupts disabled. So if you disable the interrupts your delay() call will probably never return.

jemhadar:
hello Nick

this is the code.

Please edit your post, select the code, and put it between [code] ... [/code] tags.

You can do that by hitting the # button above the posting area.

As requested in my earlier message.

sry im newbie :blush:

ill edited it.

i have also a second question to my project.
other microcontrollers
need an defined order

  1. set output pin as low
  2. set pin as output.

is there a mayor order for arduino controllers?

thx
Thomas

is there a mayor order for arduino controllers?

No, but there may be a special meaning. If you put an input to HIGH, you're activating the internal pull-up resistor for that pin. Usually you set the ports direction and then set the value it should have.

I presume by "sensible code" you mean "critical section".

Just do the delay after turning interrupts back on.

  noInterrupts();
 
  for(int i = 0; i < E_I2C2_MAX; i++)
    {
    help = digitalRead(i);
    if(help == bitRead(signale_momentan[i/32],i%32))
      {
      bitWrite(signale_entprellt[i/32],(i%32),help);
     
      }
    bitWrite(signale_momentan[i/32],(i%32),help);
    }
  interrupts();
  delay(5000);

hello again.

yes nick ill mean critical section.

the delay5000 only was for testing
normaly there is no delay needed.

the problem is not clear for me.

when the programcounter is at the moment in the bitWrite section

for(int i = 0; i < E_I2C2_MAX; i++)
    {
    help = digitalRead(i);
    if(help == bitRead(signale_momentan[i/32],i%32))
      {
      bitWrite(signale_entprellt[i/32],(i%32),help);
     
      }
    bitWrite(signale_momentan[i/32],(i%32),help);
    }

and at same time there comes the interupt from wire request.
he would jump out and do the wire-request routine.

is there be a chance that some bits got lost when the programcounter go back into the bitwriteloop

so ill try out the

noInterrupts();
..
..
..
interrupts();
[code]

but wire request  dont care of  noInterupts ill think.

some ideas too this?

@ pylon
thanx for info
because mircochip  pic  controller need 1.  set pin to low and 2. set as output.

[/code]

If you put:

noInterrupts ();

/// critical section

interrupts ();

It should work. Unless you turn interrupts on somewhere else. Once you turn interrupts off you won't receive the wire request.

However you may lose bits because the Wire library cannot respond while interrupts are off. I think the I2C interface has a one-byte buffer. So you cannot afford for interrupts to be off for long.

You might be better making a copy of the data (eg. with memcpy) and sending the copy. Turn interrupts off long enough to make the copy, keep that part as short as possible. Then turn interrupts on again and send the copy.