Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Кто нибудь писал имплементацию twi/i2c на usi для слейва?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
AlexTech
Поделитесь опытом плиз, слейв упорно ack отсылать не хочет :/
ILYAUL
Цитата(AlexTech @ Jan 31 2011, 11:29) *
Поделитесь опытом плиз, слейв упорно ack отсылать не хочет :/

Браво, это же надо же какое слово ИМПЛЕМЕНТАЦИЯ
ИМПЛЕМЕНТАЦИЯ (от лат. impleo - наполняю, исполняю), осуществление, исполнение ГОСУДАРСТВОМ международных правовых норм. Каждое государство само определяет методы и средства имплементации. В международном договоре также может быть предусмотрена необходимость издания закона или иного акта для его осуществления К чему это слово Вы употребили?

Как не однократно писалось на форуме , к огромному сожалению телепатов здесь нет- схему , код
alexeyv
Application note AVR312 Using USI as I2C Slave
Application note AVR310 Using USI as TWI
Application note AVR319 Using USI as SPI


to ILYAUL
Из англо-русского словаря:
Цитата
implementation - выполнение, исполнение, осуществление, РЕАЛИЗАЦИЯ
Synonym: realization , accomplishment


Вы где находитесь, на форуме юристов или на форуме програмистов ?!?!
ILYAUL
Цитата(alexeyv @ Jan 31 2011, 12:07) *
Application note AVR312 Using USI as I2C Slave
Application note AVR310 Using USI as TWI
Application note AVR319 Using USI as SPI


to ILYAUL
Из англо-русского словаря:

implementation - выполнение, исполнение, осуществление, РЕАЛИЗАЦИЯ


Вы где находитесь, на форуме юристов или на форуме програмистов ?!?!

Всё верно , только это слово применяется в юридических документах.
alexeyv
Цитата
Всё верно , только это слово применяется в юридических документах.



ДА НУ !!!!!!!

Откройте например правила оформления модуля в Object Pascal :

Код
unit NAME;
interface
.......
implementation // !!!!!!!!!!!!!!!!!!!!!
......
end.


Не говоря уж о хардварных языках, например, VHDL.

Да и сам Atmel выдает:
AVR302: Software I2C™ Slave Implementation
ILYAUL
Цитата(alexeyv @ Jan 31 2011, 12:17) *
ДА НУ !!!!!!!

Откройте например правила оформления модуля в Object Pascal :

Код
unit NAME;
interface
.......
implementation // !!!!!!!!!!!!!!!!!!!!!
......
end.


Не говоря уж о хардварных языках, например, VHDL.

Убедили , не знал . Хотя наши юристы , его применяют исключительно , в гос. документах
AlexTech
Простите, русский с английским в голове перемешиваются )))
Собственно вот отсюда взято - "AVR310:..... This application note describes a TWI master implementation"
С английского implementation — «осуществление», «выполнение» и только по русски это имеет отношение именно к международному праву ))))

Схема... ну какая схема, два провода между мастером на меге128 и слейвом на тинке26 плюс часики ds1307.
Работает что нибудь одно, или читаю часики или пишу в слейв.
сначала протеус говорил что поддельные данные на линии SCL, код инициализации слейва был такой:
CODE

// прям в этой строчке протеус ругался и останавливал обмен, в железе же слейв был доступен, часики нет
DDR_USI |= ( 1 << PORT_USI_SCL ) | ( 1 << PORT_USI_SDA );

PORT_USI |= ( 1 << PORT_USI_SCL );
PORT_USI |= ( 1 << PORT_USI_SDA );
DDR_USI &= ~( 1 << PORT_USI_SDA );
USICR =
( 1 << USISIE ) |
( 0 << USIOIE ) |
( 1 << USIWM1 ) | ( 0 << USIWM0 ) |
( 1 << USICS1 ) | ( 0 << USICS0 ) | ( 0 << USICLK ) |
( 0 << USITC );
USISR = ( 1 << USI_START_COND_INT ) | ( 1 << USIOIF ) | ( 1 << USIPF ) | ( 1 << USIDC );

поменял немного, стало так:
PORT_USI |= (1<<PORT_USI_SCL);
PORT_USI |= (1<<PORT_USI_SDA);
DDR_USI |= (1<<PORT_USI_SCL);
DDR_USI &= ~(1<<PORT_USI_SDA);
USICR = (1<<USISIE)|(0<<USIOIE)|(1<<USIWM1)|(0<<USIWM0)|(1<<USICS1)|(0<<USICS0)|(0<<USICLK)|(0<<USITC);
USISR = 0xF0;

протеус ругаться вроде перестал, часики читаются, но слейв теперь не отдает ack(ну я так думаю)
ISR( USI_OVERFLOW_VECTOR )
{
switch ( overflowState )
{
case USI_SLAVE_CHECK_ADDRESS:
if ( ( USIDR == 0 ) || ( ( USIDR >> 1 ) == slaveAddress) ) // проверяем адрес
{
if ( USIDR & 0x01 )// read/write
{
overflowState = USI_SLAVE_SEND_DATA;
}else{
overflowState = USI_SLAVE_REQUEST_DATA; // ставим флаг получить данные, сюда попадаем
}
SET_USI_TO_SEND_ACK( ); //шлем ack
// сюда попадаем
}else{
SET_USI_TO_TWI_START_CONDITION_MODE( );
}
break;
case USI_SLAVE_REQUEST_DATA: // а блин вот сюда никогда больше не попадаем
overflowState = USI_SLAVE_GET_DATA_AND_SEND_ACK;
SET_USI_TO_READ_DATA( );
break;
}
}

SET_USI_TO_SEND_ACK( )
{
USIDR = 0;
DDR_USI |= ( 1 << PORT_USI_SDA );
USISR = ( 0 << USI_START_COND_INT ) | ( 1 << USIOIF ) | ( 1 << USIPF ) | ( 1 << USIDC )| ( 0x0E << USICNT0 );
}

Ух, как то так ))
alexeyv
1. Я понял, что Tiny26 использует USI как TWI в режиме слейва?? тогда надо смотреть пример из AVR312, а не AVR310.
2. А при отсоединении ds1307, поведение не меняется?
AlexTech
по 312 и сделано, и мной, и несколько чужих исходников пробовал, поведение одинаковое
протеус не ест вообще то, что по 312 сделано, ну да бог с ним, в железе кое как работает

в первом варианте при отсоединении часов ничего не меняется, меняется именно при отсоединении тинки, часы читаться сразу нормально начинают
а во втором варианте, как я написал, тинка не мешает часам, но не попадает собственно в процедуру приема
alexeyv
1. А адресс Tiny26 случайно не совпадает с адресом DS1307 ??
2. Где прерывание USI_Start_Condition ?
3. Осциллографом не пробовали смотреть обмен на линии ??
AlexTech
Нет )))
я так понимаю что тинка гадит на scl и мешает часам, а если это гаженье убрать (вот тут мне не отловить косяк) то ли мастер не понимает ack который
тинка шлет после проверки адреса и соответственно не передает данные, то ли тинка его реально не отправлят
ILYAUL
Цитата(AlexTech @ Jan 31 2011, 13:30) *
Нет )))
я так понимаю что тинка гадит на scl и мешает часам, а если это гаженье убрать (вот тут мне не отловить косяк) то ли мастер не понимает ack который
тинка шлет после проверки адреса и соответственно не передает данные, то ли тинка его реально не отправлят

Отсоедините часы , зациклите START и Адрес , посмотрите , что на шине, как я понял в железе есть.
AlexTech
В железе есть, да, а чем смотреть то?
осциллографа нет, поэтому в протеусе и тестил, а он оказывается таких извратов не понимает ))
разве что леды на шину воткнуть :/

Вот старт:
Код
ISR( USI_START_VECTOR )
{

overflowState = USI_SLAVE_CHECK_ADDRESS;

DDR_USI &= ~( 1 << PORT_USI_SDA );

while (
       // SCL his high
       ( PIN_USI & ( 1 << PIN_USI_SCL ) ) &&
       // and SDA is low
       !( ( PIN_USI & ( 1 << PIN_USI_SDA ) ) )
  );

  if ( !( PIN_USI & ( 1 << PIN_USI_SDA ) ) )
  {
    //  not stop
    USICR =
         ( 1 << USISIE ) |
         ( 1 << USIOIE ) |
         ( 1 << USIWM1 ) | ( 1 << USIWM0 ) |
         ( 1 << USICS1 ) | ( 0 << USICS0 ) | ( 0 << USICLK ) |
         ( 0 << USITC );
  }else{
    // stop
    USICR =
         ( 1 << USISIE ) |
         ( 0 << USIOIE ) |
         ( 1 << USIWM1 ) | ( 0 << USIWM0 ) |
         ( 1 << USICS1 ) | ( 0 << USICS0 ) | ( 0 << USICLK ) |
         ( 0 << USITC );
  }

  USISR =
       // clear interrupt flags and release SCL
       ( 1 << USI_START_COND_INT ) | ( 1 << USIOIF ) |
       ( 1 << USIPF ) |( 1 << USIDC ) |
       ( 0x0 << USICNT0);
}
andron86
Цитата(AlexTech @ Jan 31 2011, 10:27) *
Схема... ну какая схема, два провода между мастером на меге128 и слейвом на тинке26 плюс часики ds1307.
....
Ух, как то так ))

ух ты, схема крутая, точно работать не будет biggrin.gif
AlexTech
Лан, не надо ляля ))) все будет, ну не расписывать же мне всю обвязку
все заводится, и по отдельности работает )))
alexeyv
1. Процедура приема начала кадра мне не нравится. Зачем вы там выбираете из двух режимов работы по состоянию PIN_USI_SDA?
2. Есть ли какой-нибудь debug-интерфейс, типа USART подключенного к ПК?
AlexTech
Нууу... как придумал так и написал blush.gif а какие есть варианты? можно там конечно вообще ничего не делать, ну в другом месте тот же код будет...
да, есть usart, мега может отправлять данные в комп
alexeyv
А debug-интерейс на Tiny, вы же ее отлаживаете?

например так:
Код
__interrupt void USI_Start_Condition_ISR(void)
{
    unsigned char tmpUSISR;                                         // Temporary variable to store volatile
    tmpUSISR = USISR;                                               // Not necessary, but prevents warnings
// Set default starting conditions for new TWI package
    USI_TWI_Overflow_State = USI_SLAVE_CHECK_ADDRESS;
    DDR_USI  &= ~(1<<PORT_USI_SDA);                                 // Set SDA as input
    while ( (PIN_USI & (1<<PORT_USI_SCL)) & !(tmpUSISR & (1<<USIPF)) );   // Wait for SCL to go low to ensure the "Start Condition" has completed.
                                                                       // If a Stop condition arises then leave the interrupt to prevent waiting forever.
    USICR   =   (1<<USISIE)|(1<<USIOIE)|                            // Enable Overflow and Start Condition Interrupt. (Keep StartCondInt to detect RESTART)
                (1<<USIWM1)|(1<<USIWM0)|                            // Set USI in Two-wire mode.
                (1<<USICS1)|(0<<USICS0)|(0<<USICLK)|                // Shift Register Clock Source = External, positive edge
                (0<<USITC);
    USISR  =    (1<<USI_START_COND_INT)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|      // Clear flags
                (0x0<<USICNT0);                                     // Set USI to sample 8 bits i.e. count 16 external pin toggles.
}
AlexTech
Я честно не ожидал таких сложностей с usi, поэтому не предусмотрел на тинке ничего, можно конечно проводки бросить...
Только не могу чет сообразить... тинка на 8мгц, битрейт 9600, она будет успевать передавать то...
В любом случае могу прокидывать в комп хотя бы то что на мастере творится, вечером попробую )

Вы предлагаете вообще выбросить все действия при определении старт/стоп? или мы их куда то переносим?
alexeyv
Никуда ничего не переносим. В стартовом прерывании определяем старт и включаем прием байта
AlexTech
Я ничего не путаю? это же не twi, а usi, нам по стопу надо бы ручками scl придушить??? а мы его перестаем обрабатывать в вашей версии
alexeyv
стоп-кондишен обрабатывается в
Код
while ( (PIN_USI & (1<<PORT_USI_SCL)) & !(tmpUSISR & (1<<USIPF)) );


какая частота у УСИ/ТВИ?
AlexTech
100кгц
Спасибо за подсказки, попробую, отпишусь по результатам что получится )
ILYAUL
А мы вообще на старт ответили? С часами всё ясно, ковырять прогу со стороны мастера нет необходимости, часы пашут ,но там автомат . А вот слейв , он ведь на старт должен ответить
AlexTech
Я думал что вот это:
USISR = (0<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|(0xE<<USICNT0);
while ( !(USISR & ( (1<<USISIF)|(1<<USIOIF) )) );
должно отвечать, но как то не очень получается )))

написал вместо этого дикость типа:
DDR_USI |= (1<<PORT_USI_SDA);
PORT_USI &= ~(1<<PORT_USI_SDA);
asm volatile ("NOP" :sm.gif;
PORT_USI |= (1<<PORT_USI_SDA);
DDR_USI &= ~(1<<PORT_USI_SDA);
как ни странно стало лучше, протеус по крайней мере теперь видит этот ack, ну а дальше все равно фигня...

Вот протокол обмена с часиками
S D0 A 00 A Sr D1 A 55 A 57 A 17 A 02 A 31 A 01 A 11 N P

А вот с тинкой
S 4C N P
иногда вот так
S 4C N Sr P
и после шаманства вот так
S 4C A 41 N P

кстати в инициализации должно бы быть DDR_USI |= (1<<PORT_USI_SCL); но протеус этого вообще не переваривает (
ILYAUL
Цитата(AlexTech @ Jan 31 2011, 17:59) *
ЯВот протокол обмена с часиками
S D0 A 00 A Sr D1 A 55 A 57 A 17 A 02 A 31 A 01 A 11 N P

А вот с тинкой
S 4C N P
иногда вот так
S 4C N Sr P
и после шаманства вот так
S 4C A 41 N P

Протокол с часиками расшифровыается просто
А вот с тинькой

S- старт
4С- slave - запись
А - ASK
41- данные
а вот теперь ерунда

N- NO ASK при записи -чушь Надеюсь понятно изложил
P - Stop
AlexTech
Да изложили то понятно, я в общем это понимаю кроме Sr, я блин не понимаю почему код фактически из аппнота генерит такой протокол :/
Причем в железе то тинка нормально принимает данные, только часики глушит напрочь
ILYAUL
Цитата(AlexTech @ Jan 31 2011, 23:07) *
Да изложили то понятно, я в общем это понимаю кроме Sr, я блин не понимаю почему код фактически из аппнота генерит такой протокол :/

Излагаю
Код
S D0 A 00 A Sr D1 A 55 A 57 A 17 A 02 A 31 A 01 A 11 N P

S - старт
D0- Slave адрес часов - запись
А-ASK не проблема
00- установка на регистр секунд
А- выще
Sr - repeat start
D1 - Slave чтение
Дальше смысла нет разшифровывать 55 сек 57 мин ............................
N- No ASK
P -STOP/
Вобщем-то правильно, за исключением , что N должен выдаваться перед 11 . Не важно , но просто избавляет от S D0 A 00 A Sr

Короче - при записи НИКОГДА не выдается код N - NO ASK. Slave в Вашем случае , становится в ступор , типа " да на хрен мне мастер прислал , конец приема", когда должен вроде как записывать мне данные
Соответсвенно вся шина тоже в ступоре, хрен его знает что этому мастеру нужно . И часики естествено тоже

ну теперь похоже вообще понятно изложил
AlexTech
Вот код мастера для тинки
Код
    i2c_start();
    i2c_tx_addr( (0x26<<TWI_ADR_BITS) | (FALSE<<TWI_READ_BIT) );
    i2c_tx(0x41);
    i2c_stop();


Вот для часиков
Код
  i2c_start();
  i2c_tx_addr( (0x68<<TWI_ADR_BITS) | (FALSE<<TWI_READ_BIT) );
  i2c_tx(0);

  i2c_start();
  i2c_tx_addr( (0x68<<TWI_ADR_BITS) | (TRUE<<TWI_READ_BIT) );
  rtc_var->seconds = i2c_rx(ACK);
  rtc_var->minutes = i2c_rx(ACK);
  rtc_var->hours =   i2c_rx(ACK);
  i2c_rx(ACK);
  rtc_var->day =   i2c_rx(ACK);
  rtc_var->month = i2c_rx(ACK);
  rtc_var->year =  i2c_rx(NOT_ACK);
  i2c_stop();


Вот tx и rx
Код
void i2c_tx(unsigned char byte)
{
  if(i2c_error)
    return;
  i2c_delay();
  TWDR = byte;
  TWCR = ((1<<TWINT)+(1<<TWEN));
  i2c_delay();
  if(TWSR != MTX_DATA_ACK)
    i2c_error=1;
}

unsigned char i2c_rx(unsigned char last_byte)
{
  if(i2c_error)
    return 0;
  i2c_delay();
  if(last_byte)        
    TWCR = ((1<<TWINT)+(1<<TWEN)+(1<<TWEA));  
  else
    TWCR=((1<<TWINT)|(1<<TWEN));  
  i2c_delay();
  if(((TWSR != MRX_DATA_NACK)&&(last_byte == NOT_ACK))&&(TWSR != MRX_DATA_ACK))
    i2c_error=1;
  return TWDR;
}



В общем все, убрал по вашей наводке i2c_stop(); из обмена с тинкой.
В протеусе ерунда полная, в железе все работает вроде, почти все...
Без этого стопа, если тинку отключить, то часики перестают читаться тоже
Ну да все равно, Спасибо большое )))
ILYAUL
Значит так :
Даже незнаю с чего и начать.
Шина I2C. Есть такие нюансы , которые при работе с этой шиной надо учитывать.
STOP - вот казалось бы чего проще, но нет , если у Вас "тупорылый" slave , да не один, то необходимо отследить , а выполнился ли этот Stop. Чревато - поданая тут же команда START- пипец - шина в ступоре.
Так , что посде Stop , да если ещё TWI программый , ЗАДЕРЖКА перед START
AlexTech
То есть i2c_stop(); все же нужен?
Все, оставил и стоп и паузу добавил на 100мс, все заработало как надо )))))
Еще раз спасибо ))))
Сколько мучений из за одной паузы, а все от неопытности...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.