Зависает цикл while

Alexande
Offline
Зарегистрирован: 02.01.2016

День добрый много уважаемая публика

Суть проблемы такая. есть пустой цикл

while(TWIbusy);

TWIbusy  это моя переменная. которая во премя работы TWI не равна нулю. При посылки на шину сигнала STOP данная переменная в обработчике прерывания ставится равной 0 и следовательно условие уже не выполняется. цикл должен прекратиться. но этого не происходит. Тоже самое с циклом for(;TWIbusy;);

Что интересно. Из прерывания я вывожу в порт значение переменной когда он ее обнуляет. И это действительно происходит. Если цикл сделать не пустой. а скажем воткнуть в тело Serial.print( TWIbusy);

то все хорошо. как только обработчик прерывания обнуляет значение данной переменной цикл прекращается. но стоит его оставить пустым(хотя я пробовал и бесполезные вычисления внутрь ставить) то он зависает намертво. пока не выведешь что то в порт. Подскажите в чем причина может быть? могу весь скеч скинуть

плата Arduino Uno если это важно

vvadim
Offline
Зарегистрирован: 23.05.2012

ну конечно код покажите

Alexande
Offline
Зарегистрирован: 02.01.2016
#define     WRITE       0x00    // TWIBus WRITE command
#define     READ        0x01    // TWIBus READ command
#define     BMP085      0x77    // Device address for BMP085 
// TWIBus states:
// MT   = Master Transmitter
// MR   = Master Receiver
// ST   = Slave transmitter (not implemented)
// SR   = Slave receiver (not implemented)
#define TWIBusErr       0x00    // (all modes) BUS ERROR
#define TWINoInfo       0xF8    // unknown state
#define TWIStart        0x08    // (MT & MR) START transmitted
#define TWIRestart      0x10    // (MT & MR) repeated START
#define TWIMtAddAck     0x18    // (MT) Slave address + W transmitted; ACK received 
#define TWIMtAddNack    0x20    // (MT) Slave address + W transmitted; NACK received
#define TWIMtDbAck      0x28    // (MT) data byte transmitted; ACK received
#define TWIMtDbNack     0x30    // (MT) data byte transmitted; NACK received
#define TWIMtArbLost    0x38    // (MT) arbitration lost
#define TWIMrAddAck     0x40    // (MR) Slave address + R transmitted; ACK received
#define TWIMrAddNack    0x48    // (MR) Slave address + R transmitted; NACK received
#define TWIMrDbAck      0x50    // (MR) data byte rec'vd; ACK transmitted
#define TWIMrDbNack     0x58    // (MR) data byte rec'vd; NACK transmitted

#define TWSR_MASK 0xfc

// Calibration values--------------------
int ac1;
int ac2;
int ac3;
unsigned int ac4;
unsigned int ac5;
unsigned int ac6;
int b1;
int b2;
int mb;
int mc;
int md;
// b5 is calculated in bmp085GetTemperature(...), this variable is also used in bmp085GetPressure(...)
// so ...Temperature(...) must be called before ...Pressure(...).
long b5;
//----------------------------------------
char    WrAdr, RdAdr;           // slave address + Write (or Read)
char    TWIbusy;                // This flag is set when a send or receive is started. It is cleared
                                // by the ISR when the operation is finished
char    RW;                     // R/W command flag. 1=read, 0=write
unsigned    char    txbuf[3];   // buffer of data to be transferred to BMP085
unsigned    char    rxbuf[3];   // buffer to hold data read from BMP085
unsigned    char    dispBuf[8]; // buffer for temperature to be displayed///////////////////////
unsigned    char    command;    // command to be sent to BMP085
unsigned    char    byte2Send;  // number of bytes to send to BMP085
unsigned    char    byte2Read;  // number of bytes to read from BMP085
unsigned    char    wIndex;     // index to txbuf
unsigned    char    rIndex;     // index to rxbuf

void initTWI(void);
void initBMP085(char config);


void setup() {
	// put your setup code here, to run once:
	Serial.begin(57600);
	initTWI();
	TWIbusy = 0; // initially TWI bus is not busy
	Serial.println( "Initializing BMP085..." );
	//sei();
	//Init BMP085 Calibration values
	initBMP085(0xAA);
//	initBMP085(0xAC);

  while(TWIbusy){
	  Serial.print("");
  }

	ac1 = (int16_t)rxbuf[0]<<8 | rxbuf[1];

	//------------------------------
}

void loop() {
  // put your main code here, to run repeatedly:

//  ac1 = (int16_t)rxbuf[0]<<8 | rxbuf[1];
  Serial.print( "ac1 = ");
  Serial.println( ac1, DEC );
  delay(200);
}

// ------------------------------------------------------------------------------------------------------------
// The following function initializes the TWI module to operate at 400 kHz.
// ------------------------------------------------------------------------------------------------------------
void initTWI(void)
{
    TWBR    = 0x0C; // set baud rate to 400 kHz (with prescaler set to 0)
    TWSR    &= 0xFC;//  "
    TWCR    = 0x05; // enable TWI and its interrupt
//  DDRD    = 0;    // configure SCL and SDA pins to open drain
}

// -------------------------------------------------------------------------------------------------------------
// The following function Calibration values the BMP085.
// -------------------------------------------------------------------------------------------------------------
void initBMP085(char config)
{
	while(TWIbusy);				// wait until TWI bus is idle
	TWIbusy	= 1;				// occupies the TWI bus (set to busy)
	RW		= 1;				// indicate read
	WrAdr	= (BMP085<<1)|0;	//set control byte to "BMP085 ID + W"
	RdAdr	= (BMP085<<1)|1;	//set read control byte to "BMP085 ID + R"
	command	= config;
	byte2Send 	= 1;			// number of bytes to be transferred
	byte2Read 	= 2;			// number of bytes to be read
	TWCR		= 0xA5;			// generate a START condition
}

void stat(char aaa)
{
	Serial.print( " -<>- " );
	Serial.print( TWSR & TWSR_MASK, HEX );
	Serial.print( " <-> " );
	Serial.print( aaa, HEX );
  Serial.println( " -<>- " );
}

// -------------------------------------------------------------------------------------------------------------
// TWI module Interrupt Service Routine
// -------------------------------------------------------------------------------------------------------------
ISR(TWI_vect)
{
   	switch (TWSR & 0xF8){   	// Check the status code for the TWI module
		case TWIBusErr:
			TWCR	= 0x95;		// reset TWI bus
			break;
		case TWIStart:
      		TWDR 	= WrAdr;	// send slave ID + W
      		TWCR 	= 0x85;		// and clear TWINT flag
        	break;
    // Master Transmitter/Receiver: Repeated START condition transmitted.
    // This state should only occur during a read, after the memory address
    // has been sent and acknowledged.
    	case TWIRestart:
        	TWDR 	= RdAdr;   	// send slave ID + R.
      		TWCR	= 0x85;		// and clear the TWINT flag
			break;
    // Master Transmitter: Slave address + W transmitted. ACK received.
  		case TWIMtAddAck:
       		TWDR 	= command;	// send a command to DS1631A.
			wIndex	= 0;		// write buffer starting index
			rIndex	= 0;		// read buffer starting index
			byte2Send--;		
			TWCR	= 0x85;		// send out command and clear TWINT flag
       		break;
	// Master Transmitter: Slave address + WRITE transmitted.  NACK received.
    	// The slave is not responding.  Send a STOP followed by a START to try again.
    	case TWIMtAddNack:
       		TWCR 	= 0xB5;
       		break;
    // Master Transmitter: Data byte transmitted.  ACK received.
    // This state is used in both READ and WRITE operations.  Check RW to find
    // out data transfer type. RW = 1 is read data; RW = 0 is write data
   		case TWIMtDbAck:
        		if (byte2Send==0){	// all bytes to be transmitted have been sent
        			if (RW) { // If (R/W == READ), generate repeated START.
            			TWCR = 0xA5;
            		} 
					else { 
						TWIbusy	= 0;	// release TWI bus 
						TWCR = 0x94; 	// If a write, generate a STOP condition.
            		}
				}
        		else {  // send next data byte
					TWDR	= txbuf[wIndex++];
					TWCR	= 0x85;	// clear TWINT flag and trigger transmission
					byte2Send--;
        		}
        		break;
    // Master Transmitter: Data byte transmitted.  NACK received.
    // Slave not responding.  Send STOP followed by START to try again.
  		case TWIMtDbNack:
    			TWCR		= 0xB5;	// generate STOP and then START condition
    			break;
    // Master Transmitter: Arbitration lost.
    // Should not occur.  If so, restart transfer.
  		case TWIMtArbLost:
        		TWCR = 0xA5;	// if MT lost in arbitration, wait until TWI bus idle and generate START
        		break;
    // Master Receiver: Slave address + R transmitted.  ACK received.
    // Set to transmit NACK after next transfer since it will be the last only byte.
    	case TWIMrAddAck:
		if(byte2Read > 1)
    		TWCR 	= 0xC5;	// ACK sent on acknowledge cycle.
		else
			TWCR	= 0x85;	// read one byte only, assert NACK
     		break;
   	// Master Receiver: Slave address + READ transmitted.  NACK received.
   	// Slave not responding.  Send repeated start to try again.
    	case TWIMrAddNack:
       		TWCR 	= 0xA5;	// if receive NACK after sending address, generate RESTART
       		break;
	// Data byte received.  ACK transmitted.
    	case TWIMrDbAck:
			byte2Read--;
			rxbuf[rIndex++] = TWDR;
 			if(byte2Read == 1)
				TWCR	= 0x85;	// NACK the last byte
			else
				TWCR	= 0xC5;	// more than one byte to read, send ACK
        		break;
    	// Data byte received.  NACK transmitted.
    	// Read operation has completed.  Read data register and send STOP.
    	case TWIMrDbNack:
        	rxbuf[rIndex] = TWDR;
			TWIbusy = 0;    // Free TWI bus
			stat( TWIbusy ); //--------------------------------------------------------------------

			TWCR 	= 0x95;	// Assert STOP condition
        	break;
    	// All other status codes meaningless in this application. Reset communication.
  		default:
			TWIbusy = 0;
			TWCR 	= 0x95; // Reset communication.
        	break;
   	}
}

 

Alexande
Offline
Зарегистрирован: 02.01.2016

69-71 строка это тот самый цикл. стоит вывод в порт убрать на нем все зависает

в 212 строке вывод в порт информации из обработчика прерывания который ставит TWIbusy  в ноль

Это происходит четко

 

Datak
Offline
Зарегистрирован: 09.10.2014
volatile char    TWIbusy;

 

Alexande
Offline
Зарегистрирован: 02.01.2016

Благодарю. Работает