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

 
 
 
Reply to this topicStart new topic
> AT24C512 и ADuC848, проблемма с чтением
sls_
сообщение May 29 2007, 07:35
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 27
Регистрация: 4-03-07
Пользователь №: 25 875



Всем привет, нужна помощь.
Память АТ24С512 и часы D1340 подключены к ADuC848 по I2C.
Проблемма: при чтении из памяти по байтно при единичном чтении из любой ячейки чтение корректно, но как только начинаю читать этой же функцией несколько байт подряд значения зависят от прдидущего прочитанного байта. Т.е. если предидущий прочитанный байт содержит чотное число следующее читается верно, если не четное то прочитанное число на 128 больше.
Пример:
Ячейка Записываю Считываю
----0-----------0------------0
----1-----------1------------1
----2-----------2----------130
----3-----------3------------3
----4-----------4----------132
Такое ощущение что младший бит предидущего байта попадает в старший последующего.
Пробовал читать страницами эфект тотже. С часов висящих на том же порту читаю все значения корректны.
функции для чтения записи:
#define EEPROM_BUS_ADDRESS 0xA0
void write_byte_eeprom (unsigned int address, unsigned char datas)
{
i2c_start();
i2c_tx(EEPROM_BUS_ADDRESS);
i2c_tx((unsigned char)address>>8);
i2c_tx((unsigned char)address);
i2c_tx(datas);
i2c_stop();
}
unsigned char read_byte_eeprom (unsigned int address)
{
unsigned char datas;
i2c_start();
i2c_tx(EEPROM_BUS_ADDRESS);
i2c_tx((unsigned char)address>>8);
i2c_tx((unsigned char)address);
i2c_start();
i2c_tx(EEPROM_BUS_ADDRESS | 1);
datas = i2c_rx(0);
i2c_stop();
return datas;
}
Буду благодарен за любую помощь.
Go to the top of the page
 
+Quote Post
DimaM
сообщение May 29 2007, 07:59
Сообщение #2


Частый гость
**

Группа: Участник
Сообщений: 103
Регистрация: 17-12-06
Из: село
Пользователь №: 23 615



aduc848 не работал, но тем не менее кажется ошибка в его программе
функции типа i2c_rx(0); сам писал?
я когда то много времени потратил на i2c, пока application note не взял и не написал прерывание для i2c как в примере.
Go to the top of the page
 
+Quote Post
sls_
сообщение May 29 2007, 08:08
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 27
Регистрация: 4-03-07
Пользователь №: 25 875



Цитата(DimaM @ May 29 2007, 11:59) *
aduc848 не работал, но тем не менее кажется ошибка в его программе
функции типа i2c_rx(0); сам писал?
я когда то много времени потратил на i2c, пока application note не взял и не написал прерывание для i2c как в примере.

Эти функции опробованы на часах и на двух рахличных датчиках:
void i2c_dly (void)
{
}

void i2c_start (void)
{
MDE=1; MDO=1;//bSDA = 1;
i2c_dly ();
MCO=1;//bSCL = 1;
i2c_dly ();
MDE=1; MDO=0;//bSDA = 0;
i2c_dly ();
MCO=0;//bSCL = 0;
i2c_dly ();
}
void i2c_stop (void)
{
MDE=1; MDO=0;//bSDA = 0;
i2c_dly ();
MCO=1;//bSCL = 1;
i2c_dly ();
MDE=1; MDO=1;//bSDA = 1;
i2c_dly ();
}

char i2c_rx(char ack)
{
char x, d=0;
MDE=1; MDO=1;//bSDA = 1;
for(x=0; x<8; x++)
{
d <<= 1;
do
{
MCO=1;//bSCL = 1;
i2c_dly ();
}
while(MCO==0); //SCL_IN==0
i2c_dly();
MDE=0;
if(MDI) d |= 1; //SDA_IN
MCO=0;//bSCL = 0;
}
if(ack){MDE=1; MDO=0;}// bSDA = 0;
else {MDE=1; MDO=1;}//bSDA = 1;
MCO=1;//bSCL = 1;
i2c_dly();
MCO=0;//bSCL = 0;
MDE=1; MDO=1;//bSDA = 1;
return d;
}

bit i2c_tx(unsigned char d)
{
char x;
static bit b;
for(x=8; x; x--)
{
if(d&0x80) {MDE=1; MDO=1;}//bSDA = 1;
else {MDE=1; MDO=0;}//bSDA = 0;
MCO=1;//bSCL = 1;
d <<= 1;
i2c_dly ();
MCO=0;//bSCL = 0;
i2c_dly ();
}
MDE=1; MDO=1;//bSDA = 1;
MCO=1;//bSCL = 1;
i2c_dly();
MDE=0;
b = MDI;//b = bSDA; //SDA_IN
MCO=0;//bSCL = 0;
return b;
}
Go to the top of the page
 
+Quote Post
DimaM
сообщение May 29 2007, 08:30
Сообщение #4


Частый гость
**

Группа: Участник
Сообщений: 103
Регистрация: 17-12-06
Из: село
Пользователь №: 23 615



извени лень с битиками разбиратся
просто попробуй задержки увеличить временно
Go to the top of the page
 
+Quote Post
sls_
сообщение May 29 2007, 08:37
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 27
Регистрация: 4-03-07
Пользователь №: 25 875



Цитата(DimaM @ May 29 2007, 12:30) *
извени лень с битиками разбиратся
просто попробуй задержки увеличить временно

Понимаю.
задержки увеличивать пробовал, не помогло.
резисторы подтягивающие тоже менял от 4к до 100к разницы нет
Go to the top of the page
 
+Quote Post
DimaM
сообщение May 29 2007, 14:52
Сообщение #6


Частый гость
**

Группа: Участник
Сообщений: 103
Регистрация: 17-12-06
Из: село
Пользователь №: 23 615



я использовал
http://www.silabs.com/public/documents/tpu...al/en/an113.pdf
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 29 2007, 18:41
Сообщение #7


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(sls_ @ May 29 2007, 10:35) *
datas = i2c_rx(0);
i2c_stop();
Вот тут у вас ошибка. При приеме последнего байта вы должны ответить NACK, иначе при определенных условиях не сможете сформировать стоп. Условие просто - если в следующем байте в памяти старший бит равен нулю. Память начнет выдавать его на шину сразу после ACK и не даст вам сформировать стоп - высокий уровень на SDA не появится. Не работал с 848, поэтому запутался в MDO/MDE в вашем исходнике. На всякий случай посмотрите еще вот это сообщение.

P.S. ой, извиняюсь, не обратил внимания на строчки
Код
if(ack){MDE=1; MDO=0;}// bSDA = 0;
else {MDE=1; MDO=1;}//bSDA = 1;
Ответ снимаю...

А правильно ли я понимаю, что MDE=1 настраивает ногу на вывод? И правильно ли я догадываюсь, что этот порт у 848 "честный", т.е. с верхним транзистором? Тогда в сообщении по ссылке скорее всего и описан корень вашей проблемы. Если нет, объясните кратенько назначение MDE и MDO, я попробую проанализировать ваш исходник детально.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
sls_
сообщение May 30 2007, 06:41
Сообщение #8


Участник
*

Группа: Участник
Сообщений: 27
Регистрация: 4-03-07
Пользователь №: 25 875



Да правильно:
MDO = ; //Data Output
MDE = ; //1-(Tx).0-(Rx).
MCO = ; //Clock Output
MDI = ; //Data Input
По поводу транзистора не уверен, в даташите не нашол. (ADuC848) хотя думаю что "i2c честный" - порты специальные
По данной Вами ссылке посмотрел но не очень понял, буду пробовать.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 30 2007, 07:35
Сообщение #9


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(sls_ @ May 30 2007, 09:41) *
По поводу транзистора не уверен, в даташите не нашол. (ADuC848) хотя думаю что "i2c честный" - порты специальные
Мда, доку на цифровые микросхемы аналоговые девицы писать не умеют. Эта такой же ужас как и на ADuC70xx sad.gif В общем я просмотрел описание, единственное упоминание не внесло ясности:
Цитата
Serial Interface Clock for the I2C Interface. As an input, this pin is a Schmitt- triggered input. A weak
internal pull-up is present on this pin unless it is outputting logic low. This pin can also be controlled in software as a digital output pin.

Serial Data Pin for the I2C Interface. As an input, this pin has a weak internal pull-up present unless it is outputting logic low.
Так в режиме вывода он пуш-пульный или открытый сток??? Если я понял все правильно, и в режиме мастера эти ноги работают в пуш-пульном режиме, то, похоже, и о работе I2C инженера этого модуля знают весьма поверхностно.

Придется вам проделать эксперимент - отпаяйте подтяжку на SDATA, выдайте единицу на эту ногу и подключая 10К резистор с этой ноги на плюс и на землю посмотрите, будет ли также меняться уровень на SDATA или он останется высоким.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
sls_
сообщение May 30 2007, 07:56
Сообщение #10


Участник
*

Группа: Участник
Сообщений: 27
Регистрация: 4-03-07
Пользователь №: 25 875



Сделал как Вы сказали.
Подтягивающие убрал, единицу установил:
10к на +3 - уровень sda высокий
10к на землю - уровень sda низкий
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 30 2007, 11:34
Сообщение #11


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(sls_ @ May 30 2007, 10:56) *
Подтягивающие убрал, единицу установил:
10к на +3 - уровень sda высокий
10к на землю - уровень sda низкий
Значит там открытый сток. Это хорошо. Просмотрел ваш код, не нашел криминала. Только я бы в начале i2c_rx в начале вместо MDE=1; MDO=1;//bSDA = 1; пренес бы сюда MDE = 0; из цикла и выкинул бы из конца функции MDE=1; MDO=1;//bSDA = 1; т.е. в паузах держал бы линию SDA настроенной на ввод. То же и в передаче - в общем я бы их написал так:
Код
char i2c_rx(char ack)
{
    char x, d=0;
    MDE=0;
    for(x=0; x<8; x++)
    {
        d <<= 1;
        do
        {
            MCO=1;      // bSCL = 1;
            i2c_dly ();
        }
        while(MCO==0);  // SCL_IN==0

        i2c_dly();
        if(MDI) d |= 1; // SDA_IN

        MCO=0;          // bSCL = 0;
    }
    MDE=1;              // bSDA = out
    if(ack) MDO=0;      // bSDA = 0;
    else MDO=1;         // bSDA = 1;

    MCO=1;              // bSCL = 1;
    i2c_dly();
    MCO=0;              // bSCL = 0;
    MDE=0;              // bSDA = in;
    return d;
}

bit i2c_tx(unsigned char d)
{
    char x;
    static bit b;
    MDE = 1;                // bSDA = out
    for(x=0; x < 8; x++)
    {
        if(d & 0x80) MDO=1; // bSDA = 1;
        else MDO=0;         // bSDA = 0;

        MCO=1;              // bSCL = 1;
        d <<= 1;
        i2c_dly ();
        MCO=0;              // bSCL = 0;
        i2c_dly ();
    }
    MDE=0;                  // bSDA = in
    MCO=1;                  // bSCL = 1;
    i2c_dly();
    b = MDI;                // b = bSDA; //SDA_IN
    MCO=0;                  // bSCL = 0;
    return b;
}
и еще - вы уверены, что проблема именно в чтении, а не в записи?

P.S. попробуйте еще и прилагаемый вариант
Прикрепленные файлы
Прикрепленный файл  i2c_848.txt ( 1.5 килобайт ) Кол-во скачиваний: 63
 


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
sls_
сообщение May 31 2007, 06:13
Сообщение #12


Участник
*

Группа: Участник
Сообщений: 27
Регистрация: 4-03-07
Пользователь №: 25 875



Сергей, спасибо Вам огромное, с вашим примером все заработало, ошибку свою понял. Еще раз спасибо.
Go to the top of the page
 
+Quote Post

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

 


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


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