the_spirit 0 21 июля, 2012 Опубликовано 21 июля, 2012 · Жалоба Решил поисследовать 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 КОм. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
stells 12 21 июля, 2012 Опубликовано 21 июля, 2012 · Жалоба У меня такое ощущения что что-то криво в коде, я прав? ... резисторы 5.1 КОм. код смотреть неинтересно, интересно в первую очередь посмотреть осциллограммы сигналов, фронты Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
*ZEVS* 0 22 июля, 2012 Опубликовано 22 июля, 2012 · Жалоба Но в обоих случаях при использовании пограничных значений частот передача либо начиналась и проходила без ошибок, либо ошибки сыпались бесконечно. Исходя из вашего ответа, у Вас проблема в длинном кабеле, а не в коде. Проверяется это легко: соедините устройство сначала без кабеля (коротким проводом) и протестируйте, а потом с кабелем и тоже протестируйте на ошибки. Если с кабелем будут ошибки, а без кабеля нет, значит, ваша программа работает нормально. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
the_spirit 0 22 июля, 2012 Опубликовано 22 июля, 2012 · Жалоба Да не, с коротким кабелем все работает, и даже с длинным на стандартной частоте. Меня беспокоит то, что при повышении частоты устройство перестает работать внезапно. У меня в программе считаются доставленные и не доставленные посылки, и при переходе в 1 khz, например от 571 к 572 посылки перестают доставляться совсем, и нет ситуации при которой доходила бы например половина или одна треть от всех отправленных посылок. Осциллограммы можно устроить, но это не раньше понедельника. В принципе для разных частот картинка не отличается, тоесть фронты сильно завалены но приблизительно одинаково что для 570 khz что для 571. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
stells 12 22 июля, 2012 Опубликовано 22 июля, 2012 · Жалоба Да не, с коротким кабелем все работает, и даже с длинным на стандартной частоте. так а для чего Вы блох ловите, если работает? начиная с определенной частоты строб чтения бита приходит в тот момент, когда уровень сигнала не достиг порогового уровня из-за завала фронта Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 22 июля, 2012 Опубликовано 22 июля, 2012 · Жалоба и при переходе в 1 khz, например от 571 к 572 посылки перестают доставляться совсем, и нет ситуации при которой доходила бы например половина или одна треть от всех отправленных посылок. Разве максимальная частота не 400 кГц? На 571 кГц TWI вообще не обязано работать. Да ещё и на 10 м. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
the_spirit 0 22 июля, 2012 Опубликовано 22 июля, 2012 (изменено) · Жалоба Ну было интересно посмотреть до какой частоты можно разогнать интерфейс. На 10 м. обязана работать, поскольку требования по предельной емкости шины соблюдены. Ну в том то и проблема, что на предельной частоте, иногда передача срабатывает, и, если срабатывает, то Master и Slave могут обмениваться сообщениями довольно продолжительное время.Мне этот процесс не понятен, и это меня напрягает. Изменено 22 июля, 2012 пользователем the_spirit Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
stells 12 22 июля, 2012 Опубликовано 22 июля, 2012 · Жалоба Ну было интересно посмотреть до какой частоты можно разогнать интерфейс. снижайте сопротивления резисторов до минимально возможного значения (с точки зрения нагрузочной способности портов), может и мегагерц вытянете Мне этот процесс не понятен а чтобы процесс понять, нужно смотреть осциллограммы Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
the_spirit 0 22 июля, 2012 Опубликовано 22 июля, 2012 · Жалоба Ок, спасибо, попробуем. Осциллограммы постараюсь к понедельнику сделать, если успею разобраться как осцил к компу подключается, раньше не было необходимости) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ruslan1 17 22 июля, 2012 Опубликовано 22 июля, 2012 · Жалоба Меня беспокоит то, что при повышении частоты устройство перестает работать внезапно. У меня в программе считаются доставленные и не доставленные посылки, и при переходе в 1 khz, например от 571 к 572 посылки перестают доставляться совсем, и нет ситуации при которой доходила бы например половина или одна треть от всех отправленных посылок. Внутри шага в один килогерц есть еще много мааааленьких шажочков. Если бы Вы двигались не на килогерц, а , например на герц или на микрогерц, то наверняка бы смогли зафиксировать любой процент ошибок от 0 до 100% с любым нужным Вам разрешением (скажем, 17.097% ошибок на частоте 570192.55 Гц). Также Вы можете построить функцию зависимости количества ошибок на такой пограничной частоте от излучения солнца или скорости ветра в лаборатории. Только зачем все это? P.S. Есть такой экспресс-тест линии связи- подать меандр (скажем, 1КГц) и снять осциллограмму. На основании исследования фронтов со стороны приемника можно прогнозировать, что через этот провод можно прокачать без ошибок, что с ошибками, а что вообще не пролезет. Это- аргументированно и обосновано. То что делаете Вы- метод ненаучного тыка. У Вас на столе сегодня результат такой, завтра у соседа что-то другое получится. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
the_spirit 0 22 июля, 2012 Опубликовано 22 июля, 2012 · Жалоба Да, спасибо за разъяснение. По шине SCL фактически и передается меандр, осциллограммы смотрел с нее со стороны приемника , фронты завалены, работе это не мешает. Про более мелкий шаг думал, вопрос собственно был в том, почему на пограничной частоте интерфейс то работает то нет, и не связанно ли это с ошибкой в коде. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ILYAUL 0 22 июля, 2012 Опубликовано 22 июля, 2012 · Жалоба Вы библиотеки откуда брали? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
the_spirit 0 22 июля, 2012 Опубликовано 22 июля, 2012 · Жалоба Из AVR Libc пришлось чуть чуть поменять чтобы заработала под IAR и не зависала. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ILYAUL 0 22 июля, 2012 Опубликовано 22 июля, 2012 · Жалоба Тогда код можно смело вычёркивать из списка , а остальное уже написал RUSLAN1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
the_spirit 0 22 июля, 2012 Опубликовано 22 июля, 2012 · Жалоба Спасибо! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться