Goofy 0 29 января, 2008 Опубликовано 29 января, 2008 · Жалоба Впервые для себя запускаю TWI на sam7s. Использована атмеловская lib_twi Запись int AT91F_TWI_WriteSingle(const AT91PS_TWI pTwi, int SlaveAddr, char *data) { unsigned int end = 0, status, err=0; /* Enable Master Mode */ // AT91C_BASE_TWI->TWI_CR = AT91C_TWI_MSEN; /* Set the TWI Master Mode Register */ AT91C_BASE_TWI->TWI_MMR = (SlaveAddr<<16 ) & ~AT91C_TWI_MREAD; /* Write the data to send into THR. Start conditionn DADDR and R/W bit are sent automatically */ AT91C_BASE_TWI->TWI_THR = *data; AT91C_BASE_TWI->TWI_CR = AT91C_TWI_START; /* NACK errata handling */ /* Do not poll the TWI_SR */ /* Wait 3 x 9 TWCK pulse (max) 2 if IADRR not used, before reading TWI_SR */ /* From 400Khz down to 1Khz, the time to wait will be in µs range.*/ /* In this example the TWI period is 1/400KHz */ AT91F_TWI_WaitMicroSecond (40); while (!end) { status = AT91C_BASE_TWI->TWI_SR; if ((status & AT91C_TWI_NACK) == AT91C_TWI_NACK) { err++; end=1; } /* Wait for the Transmit ready is set */ if ((status & AT91C_TWI_TXRDY) == AT91C_TWI_TXRDY) end=1; } AT91C_BASE_TWI->TWI_CR = AT91C_TWI_STOP; /* Wait for the Transmit complete is set */ status = AT91C_BASE_TWI->TWI_SR; while (!(status & AT91C_TWI_TXCOMP)) status = AT91C_BASE_TWI->TWI_SR; return err; } Инициализация (вызывается для 100кГц) void AT91F_TWI_Open(int TwiClock) { /* Configure TWI PIOs */ AT91F_TWI_CfgPIO (); /* Configure PMC by enabling TWI clock */ AT91F_TWI_CfgPMC (); /* Reset the TWI */ AT91C_BASE_TWI->TWI_CR = AT91C_TWI_SWRST; /* Configure TWI in master mode */ AT91F_TWI_Configure (AT91C_BASE_TWI); /* Set TWI Clock Waveform Generator Register */ //AT91C_BASE_TWI->TWI_CWGR=0x047575; AT91F_SetTwiClock(TwiClock); } Расчёт делителей void AT91F_SetTwiClock(int TwiClock) { unsigned int cldiv,ckdiv=1; /* CLDIV = ((Tlow x 2^CKDIV) -3) x Tmck */ /* CHDIV = ((THigh x 2^CKDIV) -3) x Tmck */ /* Only CLDIV is computed since CLDIV = CHDIV (50% duty cycle) */ cldiv = ( (MCK/(2*TwiClock))-3 ) / pow(2,ckdiv); while ( cldiv> 255 ) { ckdiv++; cldiv = ( (MCK/(2*TwiClock))-3 ) / pow(2,ckdiv); } AT91C_BASE_TWI->TWI_CWGR =(ckdiv<<16)|((unsigned int)cldiv << 8)|(unsigned int)cldiv; } Проблема в том, что процедура передачи просто виснит, очевидно не получая из статус регистра TXRDY. TWI инициализирован приведённой выше процедурой. Я не ошибаюсь, считая, что "железные" проблемы никак не влияют на работу модуля внутри? Пока не идёт речи о корректности передачи, лишь о факте того, что статус регистр не ведёт себя должным образом. Есть ли вероятность что модуль битый напрочь? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Homa_Gans 0 30 января, 2008 Опубликовано 30 января, 2008 (изменено) · Жалоба Запускал TWI на AT91SAM7A3 проблем не было. Но у меня функция AT91F_SetTwiClock() маленько по другому была. И еще что цепляется на шину? Резисторы подтягивающие стоят? Изменено 30 января, 2008 пользователем Хомяк Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Goofy 0 30 января, 2008 Опубликовано 30 января, 2008 · Жалоба Запускал TWI на AT91SAM7A3 проблем не было. Но у меня функция AT91F_SetTwiClock() маленько по другому была. И еще что цепляется на шину? Резисторы подтягивающие стоят? Эту функцию я правил чуть чуть, думал, мало ли... Подтяжка стоит. Только влияет ли это на процесс обновления регистров самого TWI ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
gladov 0 30 января, 2008 Опубликовано 30 января, 2008 · Жалоба Сразу бросается в глаза, что Вы делаете при передаче принудительно START|STOP. По DS на at91Sam7X от октября 2007г., этого делать не надо. А может быть и нельзя. Я тоже долго мучил TWI и столкнулся с проблемой - если при передаче принудительно дернуть START, то последующая операция чтения глючит. Ни старт, ни стоп при передаче не надо включать. Эту функцию я правил чуть чуть, думал, мало ли... Подтяжка стоит. Только влияет ли это на процесс обновления регистров самого TWI ? Влияет. Встречал реализацию (не помню в каком камне), когда аппаратный i2c сильно глючил без подтяжки. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Goofy 0 30 января, 2008 Опубликовано 30 января, 2008 (изменено) · Жалоба Сразу бросается в глаза, что Вы делаете при передаче принудительно START|STOP. По DS на at91Sam7X от октября 2007г., этого делать не надо. А может быть и нельзя. Я тоже долго мучил TWI и столкнулся с проблемой - если при передаче принудительно дернуть START, то последующая операция чтения глючит. Ни старт, ни стоп при передаче не надо включать. Влияет. Встречал реализацию (не помню в каком камне), когда аппаратный i2c сильно глючил без подтяжки. Принудительный старт выставил ради эксперимента. Убрал обратно. Дело в том, что SCL SDA линии красоты ради были подключены через MAX3002 чтобы синхронизировать уровни с 5В, что собственно не диктуется необходимостью (выводы sam7s к 5в терпимы, подтяжка внешняя, 100К припаял для начала). Ради уменьшения глючности отрезал дорожки от MAX3002, соеденил с 5В частью шины напрямую. При инициализации выходит что ключи на ножках sam7s256 открыты, на шине нулевой уровень. Цикл так же виснит. :crying: Изменено 30 января, 2008 пользователем Goofy Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
gladov 0 30 января, 2008 Опубликовано 30 января, 2008 · Жалоба Принудительный старт выставил ради эксперимента. Убрал обратно. Дело в том, что SCL SDA линии красоты ради были подключены через MAX3002 чтобы синхронизировать уровни с 5В, что собственно не диктуется необходимостью (выводы sam7s к 5в терпимы, подтяжка внешняя, 100К припаял для начала). Ради уменьшения глючности отрезал дорожки от MAX3002, соеденил с 5В частью шины напрямую. При инициализации выходит что ключи на ножках sam7s256 открыты, на шине нулевой уровень. Цикл так же виснит. :crying: А 100К не много? Рекомендуют от 5 до 10 ставить. А почему бы не попробовать остановить цикл во время висяка и не посмотреть что лежит в TWI_SR? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Goofy 0 30 января, 2008 Опубликовано 30 января, 2008 (изменено) · Жалоба А 100К не много? Рекомендуют от 5 до 10 ставить. А почему бы не попробовать остановить цикл во время висяка и не посмотреть что лежит в TWI_SR? Обстановка изменилась. Для sam7s обязательным судя по всему является AT91C_BASE_PIOA->PIO_MDER=AT91C_PA4_TWCK|AT91C_PA3_TWD; Резисторы переставил на 10к. Однако верхний уровень сигнала явно не 5 вольт. Зависание прекратилось когда на шину подцепил приёмное устройство. Попытка заглянуть в сигнал осцилографом (25рF, TWI инициализируется под частоту 50гц) снова вешает цикл и ничего не наблюдается. Будем разбираться ... Изменено 30 января, 2008 пользователем Goofy Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Homa_Gans 0 30 января, 2008 Опубликовано 30 января, 2008 (изменено) · Жалоба Я на TWI вешал 24LC256 подтягивал 2к Привожу свой код Кварц 16МГц работал на частоте квалца , без ФАПЧ //============================================================================== // Функция : AT91F_SetTwiClock // Описание : // входные параметры : // выходные параметры : //============================================================================== void AT91F_SetTwiClock(void) { int sclock; /* Here, CKDIV = 1 and CHDIV=CLDIV ==> CLDIV = CHDIV = 1/4*((Fmclk/FTWI) -6)*/ sclock = (10*MCK /AT91C_TWI_CLOCK); if (sclock % 10 >= 5) sclock = (sclock /10) - 5; else sclock = (sclock /10)- 6; sclock = (sclock + (4 - sclock %4)) >> 2; // div 4 AT91C_BASE_TWI->TWI_CWGR = ( 1<<16 ) | (sclock << 8) | sclock; } //============================================================================== // Функция : AT91F_TWI_Open // Описание : // входные параметры : // выходные параметры : //============================================================================== void AT91F_TWI_Open(void) { AT91F_TWI_CfgPIO(); // configure TWI PIOs AT91F_TWI_CfgPMC(); // enable clock TWI AT91F_TWI_Configure (AT91C_BASE_TWI); // configure in MASTER mode AT91F_SetTwiClock(); } //============================================================================== // Функция : AT91F_TWI_WriteByte // Описание : // входные параметры : // выходные параметры : //============================================================================== int AT91F_TWI_WriteByte(const AT91PS_TWI pTwi ,int mode, int int_address, char *data2send, int nb) { unsigned int status,counter=0,error=0; // Set TWI Internal Address Register if ((mode & AT91C_TWI_IADRSZ) != 0) pTwi->TWI_IADR = int_address; // Set the TWI Master Mode Register pTwi->TWI_MMR = mode & ~AT91C_TWI_MREAD; if(nb <2) { pTwi->TWI_CR = AT91C_TWI_START | AT91C_TWI_MSEN | AT91C_TWI_STOP; pTwi->TWI_THR = *data2send; } else { // Set the TWI Master Mode Register for(counter=0;counter<nb;counter++) { pTwi->TWI_CR = AT91C_TWI_START | AT91C_TWI_MSEN; if (counter == (nb - 1)) pTwi->TWI_CR = AT91C_TWI_STOP; status = pTwi->TWI_SR; if ((status & ERROR) == ERROR) error++; while (!(status & AT91C_TWI_TXRDY)) { status = pTwi->TWI_SR; if ((status & ERROR) == ERROR) error++; } pTwi->TWI_THR = *(data2send+counter); } } status = pTwi->TWI_SR; if ((status & ERROR) == ERROR) error++; while (!(status & AT91C_TWI_TXCOMP)) { status = pTwi->TWI_SR; if ((status & ERROR) == ERROR) error++; } return error; } //============================================================================== // Функция : AT91F_TWI_ReadByte // Описание : // входные параметры : // выходные параметры : //============================================================================== int AT91F_TWI_ReadByte(const AT91PS_TWI pTwi ,int mode, int int_address, char *data, int nb) { unsigned int status,counter=0,error=0; // Set TWI Internal Address Register if ((mode & AT91C_TWI_IADRSZ) != 0) pTwi->TWI_IADR = int_address; // Set the TWI Master Mode Register pTwi->TWI_MMR = mode | AT91C_TWI_MREAD; // Start transfer if (nb == 1) { pTwi->TWI_CR = AT91C_TWI_START | AT91C_TWI_STOP; status = pTwi->TWI_SR; if ((status & ERROR) == ERROR) error++; while (!(status & AT91C_TWI_TXCOMP)) { status = pTwi->TWI_SR; if ((status & ERROR) == ERROR) error++; } *(data) = pTwi->TWI_RHR; } else { pTwi->TWI_CR = AT91C_TWI_START | AT91C_TWI_MSEN; status = pTwi->TWI_SR; if ((status & ERROR) == ERROR) error++; // Wait transfer is finished while (!(status & AT91C_TWI_TXCOMP)) { status = pTwi->TWI_SR; if ((status & ERROR )== ERROR) error++; if(status & AT91C_TWI_RXRDY) { *(data+counter++) = pTwi->TWI_RHR; if (counter == (nb - 1)) pTwi->TWI_CR = AT91C_TWI_STOP; } } } return 0; } //============================================================================== // Функция : // Описание : // входные параметры : // выходные параметры : //============================================================================== void TWI_ReadByte(const AT91PS_TWI pTwi ,int mode, char *data, int nb) { unsigned int status,counter=0; // Set TWI Internal Address Register // without internal address ?????? //if ((mode & AT91C_TWI_IADRSZ) != 0) pTwi->TWI_IADR = int_address; // Set the TWI Master Mode Register // Use MS 7 bits as mode ?????? pTwi->TWI_MMR = mode | AT91C_TWI_MREAD; // Start transfer if (nb == 1) { pTwi->TWI_CR = AT91C_TWI_START | AT91C_TWI_STOP; status = pTwi->TWI_SR; //if ((status & ERROR) == ERROR) error++; while (!(status & AT91C_TWI_TXCOMP)); *(data) = pTwi->TWI_RHR; } else { pTwi->TWI_CR = AT91C_TWI_START | AT91C_TWI_MSEN; status = pTwi->TWI_SR; // Wait transfer is finished while (!(status & AT91C_TWI_TXCOMP)) { AT91F_DBGU_Printk("\n\rTEST_AT91F_TWI_ReadByte_1"); if(status & AT91C_TWI_RXRDY) { *(data+counter++) = pTwi->TWI_RHR; AT91F_DBGU_Printk("\n\rTEST_AT91F_TWI_ReadByte_2"); if (counter == (nb - 1)) pTwi->TWI_CR = AT91C_TWI_STOP; //AT91F_DBGU_Printk("\n\rTEST_AT91F_TWI_ReadByte_3"); } } } } Изменено 30 января, 2008 пользователем Хомяк Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Goofy 0 1 февраля, 2008 Опубликовано 1 февраля, 2008 · Жалоба Проблема решилась. При отсутствии устройства на шине по запрашиваемому адресу, цикл виснит. Буду вводить таймауты. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ruslan1 17 4 февраля, 2008 Опубликовано 4 февраля, 2008 · Жалоба Проблема решилась. При отсутствии устройства на шине по запрашиваемому адресу, цикл виснит. Буду вводить таймауты. Какое-то время назад тут уже подымалась тема TWI. Тема для меня больная, но повторяться не буду, только выводы: Хотите иметь надежное устройство- делайте софтовый TWI. Чтобы Ваше устройство работало так, как хотите Вы и не зависало от каждой иголки на шине. Подчеркну, это мой личный выстраданный опыт, никому свое мнение навязывать не буду. Причем это я на других АРМах грыз (AT91RM9200). Но "чуйствую", что уши у проблемы те же. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Terrabyte 0 7 февраля, 2008 Опубликовано 7 февраля, 2008 · Жалоба всё будет хорошо господа! читайте документ: http://electronix.ru/forum/index.php?act=A...st&id=16553 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
cebotor 0 7 февраля, 2008 Опубликовано 7 февраля, 2008 · Жалоба Влияет. Встречал реализацию (не помню в каком камне), когда аппаратный i2c сильно глючил без подтяжки. а не в процессорах ли ST ? в подтверждение могу сказать что на STM32 при инициализации TWI в случае неправильной подтяжки мастер встает в такое кривое состояние что потом никогда не может сгенерировать start condition Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
pan_oleg 0 4 апреля, 2008 Опубликовано 4 апреля, 2008 · Жалоба вот у меня такая ситуация, на STM32 не может сгенерировать start, подтяжка 5 к, на шине еепромка, виснет только при чтении из еепромки, что поменять с подтяжкой? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
singlskv 0 6 апреля, 2008 Опубликовано 6 апреля, 2008 · Жалоба всё будет хорошо господа! читайте документ: http://electronix.ru/forum/index.php?act=A...st&id=16553 Terrabyte а может быть Вы сможете подитожить инфу по работе i2c ? и выложить ее на всеобщее обозрение в виде FAQ ? Готов выдать Вам еще несколько мыслей, но хотелось бы на выходе получить готовую апликайшен про то как нужно пользоваться i2c на samxxxxx.... Сам буду ей пользоваться..... :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 7 апреля, 2008 Опубликовано 7 апреля, 2008 · Жалоба ИМХО, TWI на SAM7 все же неработоспособен. У меня есть несколько "почти работающих" вариантов, но все они благополучно сыпятся на попытке общения с SAA7113. Софтверный во сто крат лучше, поверьте :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться