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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> USI типа I2C на Tiny45, просто не работает
alux
сообщение Feb 22 2010, 13:22
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447



Необходимо организовать связь между Tiny45 (Slave) и Mega324P(Master). Мега должна считывать данные с Тини и передать на ЖКИ (i2c TIC154). Попробовал использовать аппнот avr312 (USI -> I2C Slave) для Тини45, но не удается получить ответ от Тини. ЖКИ при этом тоже не работает. Анализ исходника avr312 показал, что у Тини вывод SCL настроен на выход и удерживается в низком состоянии. Настройка вывода SCL (Tiny45) на вход не решила проблему.
Есть ли у кого положительный опыт работы с данным примером?
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Feb 22 2010, 16:13
Сообщение #2


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Помнится, мы нашли какой-то глюк в AVR312. Но глюк был мелкий, не приводящий к полной неработоспособности. Если что, то исправленный вариант лежит тут.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
alux
сообщение Feb 22 2010, 16:31
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447



Вывод SCL у Тини должен быть выходом? Тогда остальные I2C устройства (ЖКИ) не работают...
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Feb 22 2010, 16:49
Сообщение #4


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Да, выходом. Но не нулём:
Код
void i2c_init(u08 address)
{
    i2c_Address = address;

    PORT_USI |= (1<<PORT_USI_SCL);                    // Set SCL high
    PORT_USI |= (1<<PORT_USI_SDA);                    // Set SDA high
    DDR_USI |= (1<<PORT_USI_SCL);                    // Set SCL as output
    DDR_USI &= ~(1<<PORT_USI_SDA);                    // Set SDA as input
    USICR =    (1<<USISIE)|(0<<USIOIE)|                // Enable Start Condition Interrupt. Disable Overflow Interrupt.
            (1<<USIWM1)|(0<<USIWM0)|                // Set USI in Two-wire mode. No USI Counter overflow prior
                                                    // to first Start Condition (potentail failure)
            (1<<USICS1)|(0<<USICS0)|(0<<USICLK)|    // Shift Register Clock Source = External, positive edge
            (0<<USITC);
    USISR    = 0xF0;                                // Clear all flags and reset overflow counter
}


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
SysRq
сообщение Feb 22 2010, 16:57
Сообщение #5


Чайник, 1 литр
****

Группа: Свой
Сообщений: 655
Регистрация: 17-05-06
Из: Moscow
Пользователь №: 17 168



Цитата(alux @ Feb 22 2010, 19:31) *
Вывод SCL у Тини должен быть выходом?
Если у вас SCL и SDA подтянуты к VCC резисторами как положено, то с МК вы должны имитировать выход типа открытый коллектор\сток (т.е. давать высокий уровень на выход МК не должен).
Go to the top of the page
 
+Quote Post
alux
сообщение Feb 22 2010, 19:06
Сообщение #6


Знающий
****

Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447



Притянуты внешними 10кОм к +5В. Должен по спецификации I2C быть открытый коллектор. Получается, что этот USI нифига не совместимый с I2C?
АНТОХА, попробовал твой исходник в паре с отлаженным драйвером I2C (Мастер) на Меге. Не получается прочитать байт от Тини, хоть тресни sad.gif
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Feb 22 2010, 19:39
Сообщение #7


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата
Не получается прочитать байт от Тини, хоть тресни sad.gif

А передать байт в тиню? Там же только запись, в моём примере. И это точно работало у меняsmile.gif А другие устройства на i2c - перестали зависать?
Возможно я не всё исправил, тогда надо ждать MTh, он это (неответ) вроде поборол.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
alux
сообщение Feb 22 2010, 19:52
Сообщение #8


Знающий
****

Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447



Ни привета, ни ответа. В слейве даже по условию
Код
        if( USI_TWI_statusReg.dataInRxBuf )
        {
              PORTB |= (1 << LED);
                 ........

ничего не горит.
Со стороны Меги вызываю
Код
void ReadSensor()    
{
    I2c_StartWait(SENSOR_ADDR | W);         // slave address, write to sensor
    I2c_Write(TWI_CMD_MASTER_READ);  
  
    I2c_RepStart(SENSOR_ADDR | R);   // slave address + read bit, read sensor
          
    Value = (unsigned long)I2c_Read(I2C_ACK) << 24;
    Value |= (unsigned long)I2c_Read(I2C_ACK) << 16;
    Value |= (unsigned long)I2c_Read(I2C_ACK) << 8;
    Value |= (unsigned long)I2c_Read(I2C_NACK) << 0;
  
    I2c_Stop();
}
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Feb 22 2010, 20:37
Сообщение #9


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Ну тогда странно... Я сейчас и проверить-то не могуsad.gif
Вот софтовый i2c мастер для меги16, которым я проверял:
Прикрепленный файл  i2c_master_m16.zip ( 6.73 килобайт ) Кол-во скачиваний: 172


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
alux
сообщение Feb 23 2010, 08:41
Сообщение #10


Знающий
****

Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447



Нашел одну ошибку:
адрес слейв устройства в тини нужно инициализировать сдвинутым на 1 вправо. Т.е. из Меги передаю адрес 0х10, а в Тини TWI_SlaveAdress = 0x08. После этого начал зажигаться светодиод по условию, "буфер не пуст" и ЖКИ индикатор вроде как работает. "Вроде как" значит, что по включению питания на ЖКИ мусор и зависание, а после ресета по крайней мере проходит процедура инициализации ЖКИ. Но все-равно нет ответа от Тини sad.gif.

Короче, в топку этот недоинтерфейс USI в режиме I2C. Буду пробовать трехпроводный SPI. Надеюсь, что с ним не будет таких проблем...
Go to the top of the page
 
+Quote Post
SysRq
сообщение Feb 23 2010, 15:22
Сообщение #11


Чайник, 1 литр
****

Группа: Свой
Сообщений: 655
Регистрация: 17-05-06
Из: Moscow
Пользователь №: 17 168



Цитата(alux @ Feb 23 2010, 11:41) *
Нашел одну ошибку...
Разберитесь с адресацией (и с R\W заодно).

Обычно предлагается два подхода.

1. Адрес отделяется от признака R\W; адрес - 7 бит. При приёме вы вручную выделяете сташие 7 бит принятого байта (сдвиг на 1 вправо, отбрасываем R\W) - это и будет адрес. При передаче сдвигаете адрес на 1 влево, добавляете R\W, и отправляете байт. Микросхема "пишется" и "читается" по одному и тому же адресу.
В AVR312 именно так. Код проверки адреса:
Код
(( USIDR>>1 ) == TWI_slaveAddress

2. Адрес связан с R\W, микросхема "пишется" по одному адресу, а "читается" по другому; адрес - 8 бит. Обычно из двух этих адресов легко видно, что старшие 7 бит у них одинаковы, а младший бит адреса для "чтения" равен 1, - т.е. это просто R\W, и легко свести обмен к предыдущему подходу.
Похоже, именно так у вас master реализован.

Согласуйте подход в адресации, и должно завестись...
Go to the top of the page
 
+Quote Post
alux
сообщение Feb 24 2010, 09:28
Сообщение #12


Знающий
****

Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447



Цитата(SysRq @ Feb 23 2010, 19:22) *
Разберитесь с адресацией (и с R\W заодно).

Повторю еще раз. Со стороны Меги :
Код
#define SENSOR_ADDR  0x10

    I2c_StartWait(SENSOR_ADDR | W);         // slave address, write to sensor
    I2c_Write(TWI_CMD_MASTER_READ);  
  
    I2c_RepStart(SENSOR_ADDR | R);   // slave address + read bit, read sensor


Со стороны Тини:
Код
TWI_slaveAddress = 0x08;
............
    case USI_SLAVE_CHECK_ADDRESS:
      if ( ( USIDR == 0 ) || ( ( USIDR >> 1 ) == slaveAddress) )
      {
          if ( USIDR & 0x01 )
        {
          overflowState = USI_SLAVE_SEND_DATA;
        }
        else
        {
          overflowState = USI_SLAVE_REQUEST_DATA;
        }
        SET_USI_TO_SEND_ACK( );
      }
.......

И где я не прав?
Go to the top of the page
 
+Quote Post
alux
сообщение Feb 25 2010, 13:53
Сообщение #13


Знающий
****

Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447



Попробовал использовать USI (Tiny45) в режиме SPI (Slave). Все нормально запустилось. Отправляю от Тини число, на Меге это число принимаю и вывожу на ЖКИ. Но теперь необходимо поменять устройства ролями: Тини должен быть мастером, а Мега - подчиненным. Соответственно на Тини USCK настроил на выход, а у Меги, соответственно SCK, на вход. Кроме этого на Меге вывод SS настроен на вход и притянут перемычкой на землю.

Функция передачи байта от Тини:
Код
unsigned char send_byte(unsigned char val)
{
   USIDR = val;
   USISR = (1<<USIOIF);
   do
   {
      USICR = (1<<USIWM0) | (1<<USICS1) | (1<<USICLK) | (1<<USITC);
   }
   while ((USISR & (1<<USIOIF)) == 0);
  
   return USIDR;
}

void main()
{
    SETBIT(DDRB, USCK);
    SETBIT(PORTB, USCK);
    
    SETBIT(DDRB, DO);
    CLRBIT(PORTB, DO);
    
    CLRBIT(DDRB, DI);
    SETBIT(PORTB, DI);
        
    for(;;)
    {    
        SendByte(0x11);
        
        delay_ms(100);
    }
}


На Меге функция инициализации аппаратного SPI:
Код
    // select clock phase negative-going in middle of data
    SPCR |= (1 << CPOL0);
        
        // data is sampled on the trailing (last) edge of SCK. SPI Mode - 3
        SPCR |= (1 << CPHA0);
        
    // Data order MSB first
    SPCR &= ~(1 << DORD0);
        
    // enable SPI
    SPCR |= (1 << SPE0);
    
    // clear status
    SPSR = SPSR;
    SpiTransferComplete = true;

    // enable SPI interrupt
    #ifdef SPI_USEINT
    SPCR |= (1 << SPIE0);
    #endif
}

В результате получаю число 255!!!
Пробовал для Тини использовать программный SPI:
Код
void SendByte(unsigned char Data)
{
    unsigned char BitCount = 8;

    do
    {
        // Send bit to Slave, MSB first
        if(Data & 0x80)
        {
            SETBIT(PORTB, DO);
        }
        else
        {
            CLRBIT(PORTB, DO);
        }
        
        // Toggle SCK pin to send current bit
        CLRBIT(PORTB, USCK);
        SETBIT(PORTB, USCK);        
                
        // Get next bit to send
        Data <<= 1;      
    }
    while(--BitCount);

}

Результат - тот же. В чем может быть проблема? Уже все перепробовал cranky.gif
Go to the top of the page
 
+Quote Post
SysRq
сообщение Feb 26 2010, 22:57
Сообщение #14


Чайник, 1 литр
****

Группа: Свой
Сообщений: 655
Регистрация: 17-05-06
Из: Moscow
Пользователь №: 17 168



Цитата(alux @ Feb 24 2010, 12:28) *
И где я не прав?
Да не красиво как-то biggrin.gif

--

Цитата(alux @ Feb 25 2010, 16:53) *
Код
    // clear status
    SPSR = SPSR;
Так SPIF не сбросится, он read only.
Сброс:
Цитата
SPIF is cleared by hardware when executing the corresponding interrupt handling vector. Alternatively, the SPIF bit is cleared by first reading the SPI Status Register with SPIF set, then accessing the SPI Data Register (SPDR).
Go to the top of the page
 
+Quote Post
alux
сообщение Feb 27 2010, 14:39
Сообщение #15


Знающий
****

Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447



SPIF = SPIF;
в данном случае ни при чем.
Проблема в том, что со стороны Меги MISO и MOSI перепутаны местами...
Сбило с толку то, что когда Мега был Мастером, а Тини Слейвом, то все работало. Теперь, ничего не меняя в проводах, изменив только статусы мастера и слейва местами, и, соответственно, бит MSTR => 0 у Меги, MOSI у Меги должен быть входом, а MISO, соответственно, выходом!

PS. А вообще, логично было бы назвать вывод MISO - DI , MOSI - DO у Тини. Чем руководствовались Атмел, не понятно...
Go to the top of the page
 
+Quote Post

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

 


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


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