Здравствуйте, может кто сталкивался. Есть atmega32 с RTOS avrx, нужно брать данные с 4 lm75bim5. Нашел код для twi, подправил его слегка, запускаю... Данные с датчиков читаются, но при чтении температуры младший байт (где доли градуса) читается нормально (для lm75bim5 там либо 0 либо 0x80), а старший почему-то всегда = 255. Думал датчик глючный, поменял на lm75a и вижу младший байт меняется 0/20/40... (т.е. доли 0.125 градуса), а старший опять таки 255. Шина работает на 100кгц, контроллер на 10мгц, прескаллер=0, битрейт=42. Вот код:
CODE
// globals used to manage the state of the TWI
static TimerControlBlock twiTimer;
static AVRX_MUTEX(mutexTWI);
static volatile uint8_t *pCurData; // incremented for each databyte sent/received
static volatile uint16_t iDataCount; // buffer size; decremented until reaches zero
static volatile uint8_t iMode; // the mode we're in (send/receive)
static volatile uint8_t iRemoteAddr; // the address of the remote TWI unit
/* TWI interrupt */
volatile uint8_t status;
AVRX_SIGINT(SIG_2WIRE_SERIAL)
{
IntProlog();
// process twi state changes
status = TWSR & TWSR_STATUS_MASK;
if (iMode == TWI_M_MODE_TRANSMIT)
{
switch (status)
{
case TWI_ST_MASTER_STARTOK:
// arbitration succeeded, so send the address byte
TWDR = TWI_SLA_W(iRemoteAddr);
TWCR = TWI_TWINT | TWI_TWEN | TWI_TWIE;
break;
case TWI_ST_MASTER_SLAW_ACK:
// write the first databyte
TWDR = *pCurData++;
iDataCount--;
TWCR = TWI_TWINT | TWI_TWEN | TWI_TWIE;
break;
case TWI_ST_MASTER_SEND_DATA_ACK:
case TWI_ST_MASTER_SEND_DATA_NACK:
// if there's more data, send it. Otherwise, send STOP and
// signal that we're done
if (iDataCount > 0)
{
TWDR = *pCurData++;
iDataCount--;
TWCR = TWI_TWINT | TWI_TWEN | TWI_TWIE;
}
else
{
iMode = TWI_MODE_IDLE;
// send STOP
TWCR = TWI_TWINT | TWI_TWSTO | TWI_TWEN | TWI_TWIE;
AvrXIntSetSemaphore(&mutexTWI);
}
break;
case TWI_ST_MASTER_LOSTBUS:
iMode = TWI_MODE_IDLE;
TWCR = TWI_TWINT | TWI_TWEN | TWI_TWIE;
AvrXIntSetSemaphore(&mutexTWI);
break;
case TWI_ST_MASTER_SLAW_NACK:
default:
// something happened, so signal we're done
iMode = TWI_MODE_IDLE;
TWCR = TWI_TWINT | TWI_TWSTO | TWI_TWEN | TWI_TWIE;
AvrXIntSetSemaphore(&mutexTWI);
break;
}
}
else if (iMode == TWI_M_MODE_SENDADDR)
{
switch (status)
{
case TWI_ST_MASTER_STARTOK:
// arbitration succeeded, so send the address byte
TWDR = TWI_SLA_R(iRemoteAddr);
TWCR = TWI_TWINT | TWI_TWEA | TWI_TWEN | TWI_TWIE;
break;
case TWI_ST_MASTER_SLAR_ACK:
iMode = TWI_M_MODE_XFERSIZE;
TWCR = TWI_TWINT | TWI_TWEA | TWI_TWEN | TWI_TWIE;
break;
case TWI_ST_MASTER_SLAR_NACK:
iMode = TWI_MODE_IDLE;
TWCR = TWI_TWINT | TWI_TWSTO | TWI_TWEN | TWI_TWIE;
AvrXIntSetSemaphore(&mutexTWI);
break;
default:
// something happened, so signal we're done
iMode = TWI_MODE_IDLE;
TWCR = TWI_TWINT | TWI_TWEN | TWI_TWIE;
AvrXIntSetSemaphore(&mutexTWI);
break;
}
}
else if (iMode == TWI_M_MODE_XFERSIZE)
{
switch (status)
{
case TWI_ST_MASTER_RCVDATA_ACK:
if (TWDR < iDataCount) iDataCount = TWDR;
// ask for the next byte
iMode = TWI_M_MODE_RECEIVE;
TWCR = TWI_TWINT | TWI_TWEA | TWI_TWEN | TWI_TWIE;
break;
default:
// something happened, so signal we're done
iMode = TWI_MODE_IDLE;
TWCR = TWI_TWINT | TWI_TWSTO | TWI_TWEA | TWI_TWEN | TWI_TWIE;
AvrXIntSetSemaphore(&mutexTWI);
break;
}
}
else if (iMode == TWI_M_MODE_RECEIVE)
{
// TWI_M_MODE_RECV_DATA
switch (status)
{
case TWI_ST_MASTER_RCVDATA_ACK:
case TWI_ST_MASTER_RCVDATA_NACK:
// if there's room for more data, get it.
// Otherwise, send STOP and signal that we're done
if (iDataCount > 0)
{
*pCurData++ = TWDR;
iDataCount--;
}
if (iDataCount > 1)
{
TWCR = TWI_TWINT | TWI_TWEA | TWI_TWEN | TWI_TWIE;
}
else if (iDataCount > 0)
{
// last byte coming, so don't acknowledge
TWCR = TWI_TWINT | TWI_TWEN | TWI_TWIE;
}
else
{
iMode = TWI_MODE_IDLE;
TWCR = TWI_TWINT | TWI_TWSTO | TWI_TWEN | TWI_TWIE;
AvrXIntSetSemaphore(&mutexTWI);
}
break;
default:
// something happened, so signal we're done
iMode = TWI_MODE_IDLE;
TWCR = TWI_TWINT | TWI_TWSTO | TWI_TWEN | TWI_TWIE;
AvrXIntSetSemaphore(&mutexTWI);
break;
}
}
Epilog();
}
/* Initialize the TWI port for master mode */
void twiInitMaster(uint8_t prescale, uint8_t bitrate)
{
iMode = TWI_MODE_IDLE;
// set the prescaler and the datarate register
TWSR = prescale;
TWBR = bitrate;
TWCR = (0<<TWEN)| // Enable TWI-interface and release TWI pins.
(0<<TWIE)|(0<<TWINT)| // Disable Interupt.
(0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // No Signal requests.
(0<<TWWC);
}
/* Send bytes to a slave. Block caller until transfer is complete, or times out */
uint8_t twiMasterWrite(uint8_t addr, uint8_t *data, uint8_t datalen)
{
// don't preempt a transfer in progress
if (iMode != TWI_MODE_IDLE) return 0;
// queue up the data.
// data is used in place, so it must remain stable while the transfer is in process
AvrXResetSemaphore(&mutexTWI);
pCurData = data;
iDataCount = datalen;
iRemoteAddr = addr;
iMode = TWI_M_MODE_TRANSMIT;
// send start
TWCR = TWI_TWINT | TWI_TWSTA | TWI_TWEN | TWI_TWIE;
AvrXWaitSemaphore(&mutexTWI);
return datalen - iDataCount;
}
/* Receive bytes from a slave. Block caller until transfer is complete, or times out */
uint8_t twiMasterRead(uint8_t addr, uint8_t *data, uint8_t datalen)
{
// don't preempt a transfer in progress
if (iMode != TWI_MODE_IDLE) return 0;
// queue up the data.
// data is used in place, so it must remain stable while the transfer is in process
AvrXResetSemaphore(&mutexTWI);
pCurData = data;
iDataCount = datalen;
iRemoteAddr = addr;
iMode = TWI_M_MODE_SENDADDR;
// send start
TWCR = TWI_TWINT | TWI_TWSTA | TWI_TWEN | TWI_TWIE;
AvrXWaitSemaphore(&mutexTWI);
return pCurData - data;
}
int lm75_writeRegister(char i2c_addr, char reg_addr, unsigned char *dat, char len)
{
unsigned char tmp[len+1];
tmp[0] = reg_addr & 0x07;
memcpy(&tmp[1], dat, len);
if (twiMasterWrite(i2c_addr, tmp, len + 1) < len) return(-1);
return 0;
}
int lm75_readRegister(char i2c_addr, char reg_addr, unsigned char *dst, char len)
{
unsigned char tmp;
tmp = reg_addr & 0x07;
if (twiMasterWrite(i2c_addr, &tmp, 1))
{
if (twiMasterRead(i2c_addr, dst, len) < len) return(-1);
}
else return(-1);
return(0);
}
int lm75_configure(char i2c_addr, unsigned char cfg)
{
return lm75_writeRegister(i2c_addr, LM75_REG_CFG, &cfg, 1);
}
В основном коде имеется задача:
CODE
/* The task to read temperature sensors */
#define LM75_ADDR1 (LM75_ADDR_BASE + 0) // first sensor
AVRX_GCC_TASKDEF(TSensorsTask, 64, 1)
{
int x = 0;
unsigned char dst[2];
twiInitMaster(TWI_PRESCALER, TWI_BITRATE);
if (lm75_configure(LM75_ADDR1, 0x60) != 0) printf_P(PSTR("LM75 configure error\r\n"));;
while (1)
{
x = lm75_readRegister(LM75_ADDR1, LM75_REG_TEMP, &dst[0], 2);
if (x==0)
{
printf_P(PSTR("Read sensor value: %X %X\r\n"), dst[0], dst[1]);
}
else
{
printf_P(PSTR("Read sensor value error\r\n"));
}
AvrXDelay(&timer2, 1000); // 1000 ms delay
}
}
В итоге имею выход:
Read sensor value: 40 FF
Read sensor value: 20 FF
Read sensor value: C0 FF
Read sensor value: 0 FF
Read sensor value: 0 FF
Read sensor value: 0 FF
Read sensor value: E0 FF
Read sensor value: E0 FF
Read sensor value: C0 FF
Read sensor value: A0 FF
Т.е. младший байт вроде адекватный, а старший не читается. Контроллер загружен на примерно 30% (avrx, 4 шима на 30кгц). Причем 0xFF берется именно из TWDR, а вот какого оно там оказывается непонятно... Третий день бьюсь не могу победить...
Сообщение отредактировал zltigo - Aug 8 2010, 09:28