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

 
 
> Странности 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
 
Start new topic
Ответов
-SANYCH-
сообщение Jul 22 2012, 08:17
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 289
Регистрация: 6-12-05
Пользователь №: 11 864



Цитата
Но в обоих случаях при использовании пограничных значений частот передача либо начиналась и проходила без ошибок, либо ошибки сыпались бесконечно.


Исходя из вашего ответа, у Вас проблема в длинном кабеле, а не в коде. Проверяется это легко: соедините устройство сначала без кабеля (коротким проводом) и протестируйте, а потом с кабелем и тоже протестируйте на ошибки. Если с кабелем будут ошибки, а без кабеля нет, значит, ваша программа работает нормально.
Go to the top of the page
 
+Quote Post
the_spirit
сообщение Jul 22 2012, 14:28
Сообщение #3


Участник
*

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



Да не, с коротким кабелем все работает, и даже с длинным на стандартной частоте. Меня беспокоит то, что при повышении частоты устройство перестает работать внезапно. У меня в программе считаются доставленные и не доставленные посылки, и при переходе в 1 khz, например от 571 к 572 посылки перестают доставляться совсем, и нет ситуации при которой доходила бы например половина или одна треть от всех отправленных посылок.

Осциллограммы можно устроить, но это не раньше понедельника. В принципе для разных частот картинка не отличается, тоесть фронты сильно завалены но приблизительно одинаково что для 570 khz что для 571.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Jul 22 2012, 14:50
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(the_spirit @ Jul 22 2012, 17:28) *
и при переходе в 1 khz, например от 571 к 572 посылки перестают доставляться совсем, и нет ситуации при которой доходила бы например половина или одна треть от всех отправленных посылок.

Разве максимальная частота не 400 кГц?
На 571 кГц TWI вообще не обязано работать. Да ещё и на 10 м.
Go to the top of the page
 
+Quote Post
the_spirit
сообщение Jul 22 2012, 15:14
Сообщение #5


Участник
*

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



Ну было интересно посмотреть до какой частоты можно разогнать интерфейс. На 10 м. обязана работать, поскольку требования по предельной емкости шины соблюдены.

Ну в том то и проблема, что на предельной частоте, иногда передача срабатывает, и, если срабатывает, то Master и Slave могут обмениваться сообщениями довольно продолжительное время.Мне этот процесс не понятен, и это меня напрягает.

Сообщение отредактировал the_spirit - Jul 22 2012, 15:19
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
|- - stells   Цитата(the_spirit @ Jul 22 2012, 18:28) Д...   Jul 22 2012, 14:48
||- - 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 Текстовая версия Сейчас: 5th August 2025 - 21:38
Рейтинг@Mail.ru


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