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

Программный I2C Atmega 8

Пытаюсь считать данные из регистров устройства. Но не получается.

Возникло много вопросов:

1. Вопрос и самый главный где CAVR можно выставить частоту I2C. У меня версия 2.05 -вкладки I2C в свойствах проекта нет, но при этом есть в визарде, но там не указана частота, только назначение выводов.

Пытался сменой частоты МК, но тут тоже странности. По дефолту стоит на 8 МГц, когда меняю на 16 МГц, CAVR пишет, что SCL будет увеличен до 430 кГц, но по факту (смотрю осцилографом частота становится меньше), соответственно ставлю 1 МГц, прога предупреждает что SCL снизится до 200 кГц, но по факту она возрастает.

2. Запустил проверку кода в Протеусе, анализатор показывает последовательность верную. Запускаю в железе, ответа не получаю. При этом запись проходит успешно.

Несколько раз проходило считывание. Но не систематически и повторить не удалось.

 

Код использовал стандартный, по идее 100% рабочий

unsigned char TDA_read(unsigned char address) //Функция чтения из TDA
{
i2c_start();                                    // "Cтарт" на шину I2C
i2c_write(TDA_5414_Adr);             // адрес TDA
i2c_write(address);                       //Регистр откуда считываем ошибки
i2c_start();                                  //RE "старт" в шину
i2c_write(TDA_5414_Adr | 1);     //Обращаемся к TDA в режиме чтения, т.е. по адресу 11011001
data=i2c_read(0);                       //Принимаем данные с шины и сохраняем в переменную
i2c_stop();                                 //Посылаем команду "Cтоп"
return data;                              //Возвращаем значение прочитанного
}

.....
Вызов функции для проверки что получен правильный ответ.:
TDA_read(0x00);                        //Считываем ошибки по адресу 0х00
Data_call = data;
if (Data_call == 0x30) led1_on(), led2_on();

 

подключение сейчас на небольших ~5см, проводах.

Ниже скрины осциллограмм команды считывания через переходник USART-I2C, через него проходит исправно, а так же с Atmega, на "пониженной" скорости (кристалл на 16МГц). На скринах разное разрешение по горизонтали.

У же даже не знаю куда копать.

post-23894-1502724298_thumb.jpg

post-23894-1502724319_thumb.jpg

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


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

(c CAVR не работаю)

- проверьте настройки среды - файлы включения, опции итп

- почему осцилограммы даны только c SDA, где SCL ?

- возможно, в софте все и правильно. Если проц тактируется от кварца - проверьте, что ОН (кварц)

генерит то, что от него требуется. Бывают "подбитые" кварцы, которые или не возбуждаются, или не на требуемой частоте.

- если есть возможность, посмотрите листинги на ASM - что заливается в проц. Так будет проще отловить демона.

 

 

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


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

Частота задается внутренним генератором.

Для меня asm, это такой темный лес.... даже не знаю, что выкладывать:

,

;// I2C Bus functions
;#asm
  .equ __i2c_port=0x08 ;PORTC
  .equ __sda_bit=0
  .equ __scl_bit=1
; 0000 0023 #endasm
;#include <i2c.h>

_TDA_read:
; 0000 0041 i2c_start();                       //Кидаем команду "Cтарт" на шину I2C
;	address -> Y+0
RCALL _i2c_start
; 0000 0042 i2c_write(TDA_5414_Adr);         //Кидаем на шину адрес TDA
LDI  R30,LOW(216)
ST   -Y,R30
RCALL _i2c_write
; 0000 0043 i2c_write(address);               //Указываем байт откуда считываем ошибки
LD   R30,Y
ST   -Y,R30
RCALL _i2c_write
; 0000 0044 i2c_start();                       //Снова посылаем "старт" в шину
RCALL _i2c_start
; 0000 0045 i2c_write(TDA_5414_Adr | 1);     //Обращаемся к TDA в режиме чтения, т.е. по адресу 11011001
LDI  R30,LOW(217)
ST   -Y,R30
RCALL _i2c_write
; 0000 0046 data=i2c_read(0);                  //Принимаем данные с шины и сохраняем в переменную
LDI  R30,LOW(0)
ST   -Y,R30
RCALL _i2c_read
MOV  R6,R30
; 0000 0047 i2c_stop();                        //Посылаем команду "Cтоп"
RCALL _i2c_stop
; 0000 0048 return data;                       //Возвращаем значение прочитанного
MOV  R30,R6
ADIW R28,1
RET
; 0000 0049 }

; 0000 00DF // I2C Bus initialization
; 0000 00E0 i2c_init();
RCALL _i2c_init
; 0000 00E1 
; 0000 00E2 TDA_read(0x00); //Считываем ошибки по адресу 0х00
LDI  R30,LOW(0)
ST   -Y,R30
RCALL _TDA_read
; 0000 00E3 Data_call = data;
MOV  R7,R6
; 0000 00E4 if (Data_call == 0x30) led1_on(), led2_on();
LDI  R30,LOW(48)
CP   R30,R7
BRNE _0x13
SBI  0xB,0
SBI  0xB,6
; 0000 00E5 delay_ms (2000);

 

Сейчас попробую поставить более поздний CAVR. У этого в настройках не нашел ничего, но мне кажется очень странным, когда повышаешь тактовую частоту, а тебе снижают SCL.

 

Внизу скрины SCL, та, что с Atmega с меньшей частотой (но на скрине кажется что больше, там разрешение мс/дел больше)

post-23894-1502779883_thumb.jpg

post-23894-1502779895_thumb.jpg

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


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

У Вас тактирование идет на частотах около 20 и 80 kHz

Для начала, частота не принципиальна. По стандарту она может быть до 400 kHz

(может сейчас и больше застандартизировали)

---

Если у Вас софтовый I2C (как указано в теме), то высоккой частоты Вы и не получите.

Делите ее на кол-во команд*такты, которые обеспечивают "ногодрые" SDA SCL.

Чтобы проверить работоспособность скорость и не требуется.

---

Выведите на RIGOL 2 канала, SDA и SCL - тогда можно будет что-то сказать, что не идет и почему.

Уберите замеры Measure внизу - они не нужны. Частоты меряйте курсорами.

---

I2C интерфейс с "квитированием", те. на каждый посыл-прием байта master-slave проходит подтверждение ACK.

Если ACK нет, это это говорит о том, что slave "не виден", или занят или . . . .

А в приведенном Вами коде я анализа ACK не заметил.

---

Для проверки скорости "ногодрыга" сделайте простой цикл

и померяйте частоту.

while(1) { PORT ^= 0x0001 };

Это буде максимальная частота, которую сможет софтово выдавать проц.

Для отработки ф-ий I2C она будет в разы меньше (как минимум в 4).

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


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

Максимальная частота по внутреннем 8МГц ~ 550 кГц, на 16МГц скорость таже., так что под 100кГц I2C может работать. Что в принципе мне новый CAVR и говорит (там можно отдельно задавать частоту).

Как реализован программный i2c мне тоже не понятно, есть ли там обработка АСК.

вот скрин всей линии сразу.

post-23894-1502789083_thumb.jpg

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


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

на осцилограмме все вроде нормально.

Адрес слейва 0x6C, режим записи (если не ошибаюсь)

ACK есть (на 9-ом клоке данные притянуты в 0 слейвом, "адрес принят").

Затем идет запись в слейв нуля (не все видно).

Если надо из слейва считывать, то на 8-ом клоке (R/~W) данные должны быть в 1.

Как реализованы ф-ии софт-I2C - неизвестно. Если есть исходники - надо

их "покурить", в особенности возврат из функций ошибок.

На шине I2C только один слейв ?

Также (возможно) для считывания необходим или таймаут посылки или ожидание (чего-то).

Надо курить даташит слейва напредмет формата фреймов обмена с ним по I2C, и в частности - возможных необходимый таймаутов.

Попробуйте "разрядить" посылки команд в слейв задержками 2-5 мс. Будет ли ОНО при этом работать на "верхних"

частотах тактирования.

 

PS - даташит на слейва или ссылка не помешалабы.

 

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


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

Адрес слейва 0x6C, режим записи (если не ошибаюсь)

ACK есть (на 9-ом клоке данные притянуты в 0 слейвом, "адрес принят").

Затем идет запись в слейв нуля (не все видно).

Если надо из слейва считывать, то на 8-ом клоке (R/~W) данные должны быть в 1.

Как реализованы ф-ии софт-I2C - неизвестно. Если есть исходники - надо

их "покурить", в особенности возврат из функций ошибок.

На шине I2C только один слейв ?

Также (возможно) для считывания необходим или таймаут посылки или ожидание (чего-то).

Надо курить даташит слейва напредмет формата фреймов обмена с ним по I2C, и в частности - возможных необходимый таймаутов.

Попробуйте "разрядить" посылки команд в слейв задержками 2-5 мс. Будет ли ОНО при этом работать на "верхних"

частотах тактирования.

 

PS - даташит на слейва или ссылка не помешалабы.

 

Нет, адрес 0хD8, на один такт ошиблись.

Да, потом указываю регистр 0x00 из которого надо считать.

Затем (видно на самых первых скринах) повтор старта и указываю адрес D9 (добавляется 1, к первому кадру), но вот дальше идут расхождения.

По картинке в первом посте слайв отвечает на запрос через переходник UART-i2C: идет спад уровня, а вот на запрос Atmega не отвечает, линия остается подтянутой к питанию.

Вот, что находится в исходниках I2C.h, с обработчиком не понятно :(

#ifndef _I2C_INCLUDED_
#define _I2C_INCLUDED_

#pragma used+
void i2c_init(void);
unsigned char i2c_start(void);
void i2c_stop(void);
unsigned char i2c_read(unsigned char ack);
unsigned char i2c_write(unsigned char data);
#pragma used-

#endif

Тайм ауты я уже пытался ставить играясь в разных местах функции считывания со значениями 5-50 мс. Не помогло.

При чём что странно, что запись проходит успешно в регистры слейва (TDA5414 Дш во вложении).

 

Сейчас пытаюсь перейти на железный I2C (TWI)/

tas5414b_q1.pdf

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


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

data=i2c_read(0); Надо уточнить, что означает в параметре ф-ии 0, а что единица.

Если "0" - выдать "NOACK" - то все правильно.

---

Были тут аналогичные вопросы по разбору полетов на I2C.

Такие "неувязки" нараз отлавливаются лог. анализатором

(стоимость 20-25 кваксов, см. Saleae clone, сам такой пользую)

Если осцилограф достаточно умный (есть память) - можно записать 1 сессию по SDA+SCL

и посмотреть где "хомут".

 

Танцы с бубном, надо смотреть исходники (xxxx.c) на функции.

Попробуйте вместо ReStart просто стоп-старт.

 

unsigned char TDA_read(unsigned char address) //Функция чтения из TDA

{

i2c_start(); // "Cтарт" на шину I2C

i2c_write(TDA_5414_Adr); // адрес TDA

i2c_write(address); //Регистр откуда считываем ошибки

i2c_stop();

i2c_start();

i2c_write(TDA_5414_Adr | 1); //Обращаемся к TDA в режиме чтения, т.е. по адресу 11011001

data=i2c_read(0); //Принимаем данные с шины и сохраняем в переменную

i2c_stop(); //Посылаем команду "Cтоп"

return data; //Возвращаем значение прочитанного

}

 

 

 

 

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


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

data=i2c_read(0); Надо уточнить, что означает в параметре ф-ии 0, а что единица.

Если "0" - выдать "NOACK" - то все правильно.

---

Были тут аналогичные вопросы по разбору полетов на I2C.

Такие "неувязки" нараз отлавливаются лог. анализатором

(стоимость 20-25 кваксов, см. Saleae clone, сам такой пользую)

Если осцилограф достаточно умный (есть память) - можно записать 1 сессию по SDA+SCL

и посмотреть где "хомут".

 

Да, "0" - выдать "NOACK"

Скорее всего этот слейв не совместим по программному I2C.

Переписал на аппаратный, там всё работает. Причем менял скорости от 30 до 200кГц.

 

Да, логический анализатор всё таки стоит прикупить.

 

 

Чуть позже...

2c_write(address); //Регистр откуда считываем ошибки

i2c_stop();

i2c_start();

i2c_write(TDA_5414_Adr | 1)

А вот так работает,

Ну и бубен надо тоже прикупить у шамана.

 

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


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

. . . .

Да, логический анализатор всё таки стоит прикупить.

. . . .

Аллилуйя ! :)

Лог. анализатор дает экономию времени процентов так на 1000.

Это стОит 25 кваксов.

 

 

 

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


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

Аллилуйя ! :)

Но, в данной ситуации вряд ли бы он помог. Так как в протеусе и на осциллографе, было видно,что посылка отправляется верно с нужными значениями. Вот только слейв её не может правильно распознать. И по ДШ слейва никаких стоповых битов перед рестартом быть не должно.

Еще раз спасибо Вам.

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


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

. . . Так как в протеусе и на осциллографе, было видно,что посылка отправляется верно с нужными значениями.

. . .

Пожалуйста. Рад что чем-то помог.

В софт. ф-ии Start() не предусмотрен режим рестарта, или криво прописан.

В осцилграфе (если это не "крутяк" со встренным лог. анализатором) очень трудно смотреть сессии - когда идет пакет запрося по I2C / SPI к слейву из 5-20-100 байт. В особенности это касается I2C где есть биты ACK и рестарты. В лог. анализаторе это все видно в "расшифрованном"-читабельном виде. (USART, I2C, SPI, CAN и еще чтото). Не надо считать CLK и делать "выборки" с линии данных.

Так что если работаете с последовательными интерфейсами без LA не обойтись.

Особенно удобно при отладке или "разборе полетов" с "тупящими" клиент-серевер по USART (не надо городить перехват портов, 2 компорта итп).

Ладно, покончим с агитацией.

Удачи :)

 

 

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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