реклама на сайте
подробности

 
 
> Странности i2c
the_spirit
сообщение Jul 21 2012, 14:06
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 42
Регистрация: 25-11-10
Из: Красногорск
Пользователь №: 61 170



Решил поисследовать i2c на предмет работы с длинными проводами. С проводами длиннее 10 м, если я не ошибаюсь, TWI не работает по спецификации. Поэтому эксперименты проводились с кабелем RC10 длиной 10м, Master-Atmega128, Slave-Atmega48. Результаты получились весьма странными. С подтягивающими резисторами на slave плате и на Master плате предельной частотой работы оказалось значение 571 Khz, , без резисторов на slave плате 276Khz. Но в обоих случаях при использовании пограничных значений частот передача либо начиналась и проходила без ошибок, либо ошибки сыпались бесконечно. У меня такое ощущения что что-то криво в коде, я прав?
Код для работы с i2c на мастере:

void i2cInit(void)
{
// set pull-up resistors on I2C bus pins
sbi(PORTD, 0); // i2c SCL on ATmega128,64 !!!!!!!!!!!!!!!!!!!!!
sbi(PORTD, 1); // i2c SDA on ATmega128,64 !!!!!!!!!!!!!!!!!!!!!


// clear SlaveReceive and SlaveTransmit handler to null
i2cSlaveReceive = 0;
i2cSlaveTransmit = 0;
// set i2c bit rate to 100KHz
i2cSetBitrate(276);
// enable TWI (two-wire interface)
sbi(TWCR, TWEN);
}

void i2cSetBitrate(u16 bitrateKHz)
{
u08 bitrate_div;
// calculate bitrate division
bitrate_div = ((F_CPU/1000l)/bitrateKHz);
if(bitrate_div >= 16)
bitrate_div = (bitrate_div-16)/2;
outb(TWBR, bitrate_div);
}

void i2cSetLocalDeviceAddr(u08 deviceAddr, u08 genCallEn)
{
// set local device address (used in slave mode only)
outb(TWAR, ((deviceAddr&0xFE) | (genCallEn?1:0)) );
}
inline void i2cSendStart(void)
{
// send start condition
outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTA));
}

inline void i2cSendStop(void)
{
// transmit stop condition
// leave with TWEA on for slave receiving
outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)|BV(TWSTO));
}

inline void i2cWaitForComplete(void)
{
// wait for i2c interface to complete operation
while( !(inb(TWCR) & BV(TWINT)) ){if(wait>2000){wait=0;return;}else{wait++;}}
}

inline void i2cSendByte(u08 data)
{
// save data to the TWDR
outb(TWDR, data);
// begin send
outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));
}

inline void i2cReceiveByte(u08 ackFlag)
{
// begin receive over i2c
if( ackFlag )
{
// ackFlag = TRUE: ACK the recevied data
outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));
}
else
{
// ackFlag = FALSE: NACK the recevied data
outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));
}
}

inline u08 i2cGetReceivedByte(void)
{
// retieve received data byte from i2c TWDR
return( inb(TWDR) );
}

inline u08 i2cGetStatus(void)
{
// retieve current i2c status from i2c TWSR
return( inb(TWSR) );
}u08 i2cMasterSendNI(u08 deviceAddr, u08 length, u08* data)
{
u08 retval = I2C_OK;



// send start condition
i2cSendStart();
i2cWaitForComplete();

// send device address with write
i2cSendByte( deviceAddr & 0xFE );
i2cWaitForComplete();

// check if device is present and live
if( inb(TWSR) == TW_MT_SLA_ACK)
{
// send data
while(length)
{
i2cSendByte( *data++ );
i2cWaitForComplete();
length--;
}
}
else
{
// device did not ACK it's address,
// data will not be transferred
// return error
retval = I2C_ERROR_NODEV;
}

// transmit stop condition
// leave with TWEA on for slave receiving
i2cSendStop();
i2cWaitForComplete();


return retval;
}

u08 i2cMasterReceiveNI(u08 deviceAddr, u08 length, u08 *data)
{
u08 retval = I2C_OK;


// send start condition
i2cSendStart();
i2cWaitForComplete();

// send device address with read
i2cSendByte( deviceAddr | 0x01 );
i2cWaitForComplete();

// check if device is present and live
if( inb(TWSR) == TW_MR_SLA_ACK)
{
// accept receive data and ack it
while(length > 1)
{
i2cReceiveByte(TRUE);
i2cWaitForComplete();
*data++ = i2cGetReceivedByte();
// decrement length
length--;
}

// accept receive data and nack it (last-byte signal)
i2cReceiveByte(FALSE);
i2cWaitForComplete();
*data++ = i2cGetReceivedByte();
}
else
{
// device did not ACK it's address,
// data will not be transferred
// return error
retval = I2C_ERROR_NODEV;
}


// transmit stop condition
// leave with TWEA on for slave receiving
i2cSendStop();
i2cWaitForComplete();

return retval;
}

резисторы 5.1 КОм.
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- the_spirit   Странности i2c   Jul 21 2012, 14:06
- - stells   Цитата(the_spirit @ Jul 21 2012, 18:06) У...   Jul 21 2012, 16:13
- - -SANYCH-   ЦитатаНо в обоих случаях при использовании пограни...   Jul 22 2012, 08:17
|- - the_spirit   Да не, с коротким кабелем все работает, и даже с д...   Jul 22 2012, 14:28
|- - stells   Цитата(the_spirit @ Jul 22 2012, 18:28) Д...   Jul 22 2012, 14:48
|- - _Артём_   Цитата(the_spirit @ Jul 22 2012, 17:28) и...   Jul 22 2012, 14:50
||- - the_spirit   Ну было интересно посмотреть до какой частоты можн...   Jul 22 2012, 15:14
||- - stells   Цитата(the_spirit @ Jul 22 2012, 19:14) Н...   Jul 22 2012, 15:39
||- - the_spirit   Ок, спасибо, попробуем. Осциллограммы постараюсь к...   Jul 22 2012, 16:27
|- - Ruslan1   Цитата(the_spirit @ Jul 22 2012, 17:28) М...   Jul 22 2012, 19:31
|- - the_spirit   Да, спасибо за разъяснение. По шине SCL фактически...   Jul 22 2012, 21:15
- - ILYAUL   Вы библиотеки откуда брали?   Jul 22 2012, 21:56
|- - the_spirit   Из AVR Libc пришлось чуть чуть поменять чтобы зара...   Jul 22 2012, 22:04
- - ILYAUL   Тогда код можно смело вычёркивать из списка , а о...   Jul 22 2012, 22:09
- - the_spirit   Спасибо!   Jul 22 2012, 22:12
- - the_spirit   Простите господа сегодня осциллограмм не будет, ну...   Jul 23 2012, 09:04


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 18:32
Рейтинг@Mail.ru


Страница сгенерированна за 0.01376 секунд с 7
ELECTRONIX ©2004-2016