Перейти к содержанию
    

Решил поисследовать 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 КОм.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У меня такое ощущения что что-то криво в коде, я прав?

...

резисторы 5.1 КОм.

код смотреть неинтересно, интересно в первую очередь посмотреть осциллограммы сигналов, фронты

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

Исходя из вашего ответа, у Вас проблема в длинном кабеле, а не в коде. Проверяется это легко: соедините устройство сначала без кабеля (коротким проводом) и протестируйте, а потом с кабелем и тоже протестируйте на ошибки. Если с кабелем будут ошибки, а без кабеля нет, значит, ваша программа работает нормально.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

Осциллограммы можно устроить, но это не раньше понедельника. В принципе для разных частот картинка не отличается, тоесть фронты сильно завалены но приблизительно одинаково что для 570 khz что для 571.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да не, с коротким кабелем все работает, и даже с длинным на стандартной частоте.

так а для чего Вы блох ловите, если работает? начиная с определенной частоты строб чтения бита приходит в тот момент, когда уровень сигнала не достиг порогового уровня из-за завала фронта

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

и при переходе в 1 khz, например от 571 к 572 посылки перестают доставляться совсем, и нет ситуации при которой доходила бы например половина или одна треть от всех отправленных посылок.

Разве максимальная частота не 400 кГц?

На 571 кГц TWI вообще не обязано работать. Да ещё и на 10 м.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

Изменено пользователем the_spirit

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

снижайте сопротивления резисторов до минимально возможного значения (с точки зрения нагрузочной способности портов), может и мегагерц вытянете

 

Мне этот процесс не понятен

а чтобы процесс понять, нужно смотреть осциллограммы

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ок, спасибо, попробуем. Осциллограммы постараюсь к понедельнику сделать, если успею разобраться как осцил к компу подключается, раньше не было необходимости)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Внутри шага в один килогерц есть еще много мааааленьких шажочков. Если бы Вы двигались не на килогерц, а , например на герц или на микрогерц, то наверняка бы смогли зафиксировать любой процент ошибок от 0 до 100% с любым нужным Вам разрешением (скажем, 17.097% ошибок на частоте 570192.55 Гц). Также Вы можете построить функцию зависимости количества ошибок на такой пограничной частоте от излучения солнца или скорости ветра в лаборатории. Только зачем все это?

 

P.S. Есть такой экспресс-тест линии связи- подать меандр (скажем, 1КГц) и снять осциллограмму. На основании исследования фронтов со стороны приемника можно прогнозировать, что через этот провод можно прокачать без ошибок, что с ошибками, а что вообще не пролезет. Это- аргументированно и обосновано. То что делаете Вы- метод ненаучного тыка. У Вас на столе сегодня результат такой, завтра у соседа что-то другое получится.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, спасибо за разъяснение. По шине SCL фактически и передается меандр, осциллограммы смотрел с нее со стороны приемника , фронты завалены, работе это не мешает. Про более мелкий шаг думал, вопрос собственно был в том, почему на пограничной частоте интерфейс то работает то нет, и не связанно ли это с ошибкой в коде.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Из AVR Libc пришлось чуть чуть поменять чтобы заработала под IAR и не зависала.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тогда код можно смело вычёркивать из списка , а остальное уже написал RUSLAN1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...