Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: вопрос по инициализации Cirrus EP9307
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Страницы: 1, 2
merk0
там висит DS1339U - часы. но также i2с выходит на разьемы, куда будут вставленые всякие умные устройства...
так что напрягаться нужно по полной, протокол должен быть реализован по стандарту.
я вроде его реализовал, но эти часики читаться не хотят(адрес устройства брал из даташита-он верный).
пока я проверяю просто на послдеовательности вида

int ext_rtc_ping()
{
int lb;
i2c_start(); //Start Trasfer
lb=i2c_write (( DS1399_addr<<1) | 1); //Read Data
i2c_stop();
return (lb);
}

функция i2c_write, возвращает акноледж на байт, от слейва(то есть часов). должен быть нуль. возвращает единицу... то есть впечатление такое, что часов просто нет. поскольк они своим ключом должны занулить напрядение на data линии, на девятом клоке, генерируемом мастером.
может опять непропай какой-то...
aaarrr
Цитата(merk0 @ Mar 18 2009, 02:13) *
так что напрягаться нужно по полной, протокол должен быть реализован по стандарту.

Ну, совсем по стандарту вряд ли возможно сделать просто на GPIO. Мастер-то хоть один будет?

Можете проверить на этом. Не соответствует спецификации, зато точно работает.
CODE

//******************************************************************************

__inline void i2c_force_scl(void)
{
PGDR &= ~SCL;
}

__inline void i2c_release_scl(void)
{
PGDR |= SCL;
}

__inline void i2c_force_sda(void)
{
PGDR &= ~SDA;
PGDDR |= SDA;
}

__inline void i2c_release_sda(void)
{
PGDDR &= ~SDA;
}

__inline u_int i2c_read_sda(void)
{
return (PGDR & SDA);
}

//******************************************************************************

int i2c_ini(void)
{
// HW
EEDrive = 0x00;
PGDR &= ~SDA;
PGDR |= SCL;
PGDDR &= ~SDA;
PGDDR |= SCL;

return 0;
}

u_int i2c_write_byte(u_int data)
{
u_int a;

for(a = 0; a < 8; a++)
{
i2c_force_scl();
i2c_qp_dly();
data <<= 1;
if(data & (1 << 8)) i2c_release_sda();
else i2c_force_sda();
i2c_qp_dly();
i2c_release_scl();
i2c_hp_dly();
}

i2c_force_scl();
i2c_qp_dly();
i2c_release_sda();
i2c_qp_dly();
i2c_release_scl();
i2c_hp_dly();
if(i2c_read_sda()) return 1;
else return 0;
}

u_int i2c_read_byte(u_int ack)
{
u_int a, data;

data = 0;
for(a = 0; a < 8; a++)
{
i2c_force_scl();
i2c_qp_dly();
i2c_release_sda();
i2c_qp_dly();
i2c_release_scl();
i2c_hp_dly();

data <<= 1;
if(i2c_read_sda()) data |= 1;
}
i2c_force_scl();
i2c_qp_dly();
if(!ack) i2c_force_sda();
else i2c_release_sda();
i2c_qp_dly();
i2c_release_scl();
i2c_hp_dly();

return data;
}

void i2c_start(void)
{
i2c_force_scl();
i2c_qp_dly();
i2c_release_sda();
i2c_qp_dly();
i2c_release_scl();
i2c_qp_dly();

i2c_force_sda();
i2c_hp_dly();
}

void i2c_stop(void)
{
i2c_force_scl();
i2c_qp_dly();
i2c_force_sda();
i2c_qp_dly();
i2c_release_scl();
i2c_qp_dly();
i2c_release_sda();
i2c_qp_dly();
}

void i2c_qp_dly(void)
{
u_int a = 0x80;
while(--a) __asm{nop};
}

void i2c_hp_dly(void)
{
u_int a = 0x100;
while(--a) __asm{nop};
}

//******************************************************************************
merk0
мастер сам проц. все остальные слейвы. если протокол я реализовал верно(но я его уже вылизал, как мог), то впечатление такое, что часы например имеют другой адрес и просто не откликаются. или не запитаны вообще...или их нужно как-то толкнуть...но в даташите таких слов нет. они вроде уж декодировать свой адрес и дать аск должны по любому...
конечно нужно под лупой смотреть двухлучевым осциллом, но такого под рукой нет. а больше никакого другого устройства i2c на плате нет. все остальные будут на разьемах.
aaarrr
Так пройдитесь по всем адресам, если не уверены. Их же всего 128.

А не отключают ли часы I2C интерфейс при разряженой батарейке? У кого-то из далласов такая фича была.
merk0
за код спасибо, щас посмотрю его глазами.. он для пинов - открытых коллекторов? если нет - то работать не должен.

Цитата
У кого-то из далласов такая фича была.

гм..а вот это надо проверить... smile.gif
aaarrr
Нет, открытый коллектор только на SDA. Работать должен в любом случае.
merk0
а у вас EEdrive = 0;
то есть по даташиту - это не open drain. Это драйвер от вашей схемы?

Цитата
__inline void i2c_force_sda(void)
{
PGDR &= ~SDA;
PGDDR |= SDA;
}

вопрос - а зачем играть с битом направления порта(можно конечно), если читка из порта стоящего на вывод, все равно читает напряжение на физических пинах?
я просто ставлю ногу в высокий потенциал(размыкаю ключ), и читаю. может конечно тут собака у меня и порылась...?
aaarrr
Да, у меня сделана программная эмуляция open drain на SDA (ну да, через бит направления порта), и использован обычный выход SCL.

А про отключение интерфейса я малость напутал - это в DS1307 он отключается, когда VCC становится меньше 1.25 * Vbat sad.gif
merk0
Цитата
Да, у меня сделана программная эмуляция open drain на SDA (ну да, через бит направления порта), и использован обычный выход SCL.

А не опасно так эмулировать opendrain??? если SDA - обычный драйвер - то что будет если проц его выставил в в единицу(то есть замкнул ключ на питание - если там выходные драйверы такие), а слейв коротнул свои ключом эту линию на нуль? и будет типа КЗ. чот исключено если таки выходы стоят в честном opendrain.
аналогично и на scl.

scl по теории, при затяжке низкого уровня слейвом, точно привдет к кз, если выход scl проца - обычный.
или я не так вижу железо вообще?
aaarrr
Цитата(merk0 @ Mar 18 2009, 03:01) *
А не опасно так эмулировать opendrain??? если SDA - обычный драйвер - то что будет если проц его выставил в в единицу(то есть замкнул ключ на питание - если там выходные драйверы такие), а слейв коротнул свои ключом эту линию на нуль? и будет типа КЗ.

На SDA никогда не выставляется единица - драйвер или выдает 0, или отключен.

Цитата(merk0 @ Mar 18 2009, 03:01) *
scl по теории, при затяжке низкого уровня слейвом, точно привдет к кз, если выход scl проца - обычный.
или я не так вижу железо вообще?

Ну, далеко не все слейвы умеют затягивать SCL. В моей системе таких попросту нет.
merk0
Цитата
На SDA никогда не выставляется единица - драйвер или выдает 0, или отключен.

а попробуйте поставить EEdrive = 2 - это будет opendrain на sda. сразу выставить sda на выход(не меняя никогда), а читку линии sda делать так;
- сначала переводим sda в высокий, потом просто читаем из пина sda.
у меня такая реализация.

с клоком - аналогично.
чтобы делать затягивание просто написано
типа так
set_clk_high(); //ставим клок в высокое состояние
while(get_clk()==0){}; //пока клок опущен другим устройстом - ждем.
aaarrr
Цитата(merk0 @ Mar 18 2009, 03:23) *
а попробуйте поставить EEdrive = 2 - это будет opendrain на sda. сразу выставить sda на выход(не меняя никогда), а читку линии sda делать так;
- сначала переводим sda в высокий, потом просто читаем из пина sda.

А смысл? По сути ничем не отличается от того, что сделано у меня. Держать выводы в различных конфигурациях неудобно, поэтому видимо я и забил на EEDrive.

Цитата(merk0 @ Mar 18 2009, 03:23) *
с клоком - аналогично.

А вот на клоке у меня pull-down.
merk0
ну ладно..отличается-не отличается...главное что у меня не работает, хотя - и не отличается...smile.gif

а зачем вы делаете release_sda(см коммент в коде)

u_int i2c_read_byte(u_int ack)
{
u_int a, data;

data = 0;
for(a = 0; a < 8; a++)
{
i2c_force_scl();
i2c_qp_dly();
i2c_release_sda(); // ВОТ ТУТ???
i2c_qp_dly();
i2c_release_scl();
i2c_hp_dly();

data <<= 1;
if(i2c_read_sda()) data |= 1;
}
i2c_force_scl();
i2c_qp_dly();
if(!ack) i2c_force_sda();
else i2c_release_sda();
i2c_qp_dly();
i2c_release_scl();
i2c_hp_dly();

return data;
}

вроде, при вашем подходе вы должны сразу перевести порт на читку из sda бита до цикла, а потом 8 раз клокать и просто читать биты, вставляя их в байт.
aaarrr
Цитата(merk0 @ Mar 18 2009, 03:42) *
ну ладно..отличается-не отличается...главное что у меня не работает, хотя - и не отличается...smile.gif

А мой код работает, или тоже нет?

Цитата(merk0 @ Mar 18 2009, 03:42) *
а зачем вы делаете release_sda(см коммент в коде)

вроде, при вашем подходе вы должны сразу перевести порт на читку из sda бита до цикла, а потом 8 раз клокать и просто читать биты, вставляя их в байт.

SDA может быть затянут мной в 0 на входе в процедуру чтения. Сразу перевести его в 1 я не могу, т.к. SCL находится в высоком уровне и это действие будет воспринято слейвом как Stop-условие.
merk0
Цитата
А мой код работает, или тоже нет?

а я так сразу проверить не могу, нужно его под gnu-arm править. я держу ваш код пока в качестве референсного.

Цитата
SDA может быть затянут мной в 0 на входе в процедуру чтения. Сразу перевести его в 1 я не могу, т.к. SCL находится в высоком уровне и это действие будет воспринято слейвом как Stop-условие.

аа ну да, похоже. у меня просто start, read_byte, write_byte так написаны, что на выходе всегда ставят клок - низкий, то есть при входе в любую функцию - он снова низкий. и только на выходе i2c_init и stop клок и дата высокие - поскольку после этих функций шина д.б. свободна.
merk0
!!!!!!!!!!!!!!!!!!!!

ну все. тема закрывается. начальство сказало что денег нет и не будет. работы остановлены, скорее всего навсегда...
как говорится - не догнал, хоть разогрелся.
жалко.
пошел искать работу.
aaarrr
Да, кризис в действии. Сочувствую. Обращайтесь, если что.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.