Отговори на тема  [ 255 мнения ]  Отиди на страница Предишна  1 ... 13, 14, 15, 16, 17
I2C малко помощ 
Автор Съобщение
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Пон Май 12, 2014 10:49 pm
Мнения: 4379
Местоположение: София
Мнение Re: I2C малко помощ
Мисля, че открих, къде е проблемът. При старт на всеки цикъл на четене пойнтерът на RTC модула не сочи към един и същи адрес, както си мислех.
При това положение, ако броят на четените байтове не съответства на броя на регистрите, които се четат, се получава преместване встрани.
Настроих мастер-ът да чете точно по 19 байта и данните заспаха.


Пет Мар 15, 2019 4:35 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Пон Май 12, 2014 10:49 pm
Мнения: 4379
Местоположение: София
Мнение Re: I2C малко помощ
За да на се чуди някой (като мен), ето двете функции, които трябва да се изпълнят в основния цикъл за да се изчете RTC модула:

I2C2_MasterWrite(0x00,1,0x68,&statusReadSlave1); // 0x00 е адреса на първия регистър, който трябва да се прочете.
I2C2_MasterRead(RXbuffer_forslave_1,19,0x68,&statusReadSlave1);// четат се данните (19 байта)


Сря Мар 20, 2019 12:43 pm
Профил
Ранг: Напреднал
Ранг: Напреднал
Аватар

Регистриран на: Съб Май 21, 2016 8:47 pm
Мнения: 472
Местоположение: Бургас
Мнение Re: I2C малко помощ
Имам нужда от помощ за тъпата шина, само че не знам каква- техническа или медицинска. Не остана място за нови цицини.
Постановката е следната:
master -> slave
Master предава данни (стандартни, три устройства със съответните адреси ги получават и обработват):
Код:
    i2c_start();
    i2c_write(0xA4);  // адреса на Slave, има още два slave процесора, с тях няма проблем
    i2c_write(0xF0);  // запис в регистъра на slave
    i2c_repStart();
    i2c_write(0xA5);  // четене
   data=i2c_read(0);  //стойност, която master трябва да приеме от slave
   i2c_stop();


Slave:
PIC18F45k22, OSC = 16MHz, PLLx4 (т.е. 64МХц). Инициализация на SSP1 (два броя са):
Код:
            SSP1ADD =  0xA4;//Slave_address; //device address
            SSP1CON1 = 0x36; //SSPEN =1 and set i2c to slave mode with 7 bit address
            SSP1STAT = 0x00;
            SSP1CON2 = 0x00;
            SSP1CON3 = 0x00;


Пробвано е иi със SSP1CON2 = 0x01; 0x81; SSP1CON3 = 0x30 и комбинациите от тях.
Прекъсванията са ЗАБРАНЕНИ.
От тъпотия съм написал кода точно да обработва на горната поредица:
Код:
     while(1)
     {
         while (!SSP1STATbits.BF); // чака първият байт
           temp = SSP1BUF;  // прочитане на първия байт (0хА4)
             SSP1CON1bits.CKP = 1;  // освобождаване на шината
         while (!SSP1STATbits.BF);  // чака вторият байт
           temp = SSP1BUF;   // прочитане на вторият байт (0хF0), регистър от който трябва да се прочете
            SSP1CON1bits.CKP = 1;   // освобождаване на шината
         while (!SSP1STATbits.BF);  // чака третият байт
           temp = SSP1BUF;  // прочитане на третия байт (0xA5)- команда за четене от slave
            SSP1BUF = 0x44; // зареждане исканата стойност от регистъра, за случая 0ь44
           SSP1CON1bits.CKP = 1; // освобождаване на шината
        while (SSP1STATbits.BF);  // чакаме байта да се изпрати
          led2s(); // включваме за 2 сек светодиод, че операцията е успешна, работи
     };


С думи: мастер праща към слейв: 0xA4;0xF0;0xA5 и чака да получи байт - 0х44
Резултат: НЪЦКИ, NiCHT, NONE, ИЧ, ЙОК.
Прикачени файлове:
nucky.jpg
nucky.jpg [ 429.38 KiB | Прегледано 3380 пъти ]


Обаче:
Код:
     while(1)
     {
         while (!SSP1STATbits.BF); // чака първият байт
           temp = SSP1BUF;  // прочитане на първия байт (0хА4)
             SSP1CON1bits.CKP = 1;  // освобождаване на шината
         while (!SSP1STATbits.BF);  // чака вторият байт
           temp = SSP1BUF;   // прочитане на вторият байт (0хF0), регистър от който трябва да се прочете

             delay_uS(6); // пауза от поне 6uS, 5uS е на кантар, по-малката стойност е нъцки

            SSP1CON1bits.CKP = 1;   // освобождаване на шината
         while (!SSP1STATbits.BF);  // чака третият байт
           temp = SSP1BUF;  // прочитане на третия байт (0xA5)- команда за четене от slave
            SSP1BUF = 0x44; // зареждане исканата стойност от регистъра, за случая 0ь44
           SSP1CON1bits.CKP = 1; // освобождаване на шината
        while (SSP1STATbits.BF);  // чакаме байта да се изпрати
          led2s(); // включваме за 2 сек светодиод, че операцията е успешна, работи
     };


Резултатът е: Воала
Прикачени файлове:
voala.jpg
voala.jpg [ 424.62 KiB | Прегледано 3380 пъти ]


Тая вмъкната пауза изобщо не ми харесва, особено както ще е в прекъсване. Тези 6uS за 64MHz процесор са около 100 инструкции.
Някакви идеи, хейтове, решения или бухалки по случая?


Вто Авг 11, 2020 10:44 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Вто Фев 07, 2012 10:22 pm
Мнения: 3074
Мнение Re: I2C малко помощ
Според кода тая пауза трябва да се вижда след 0xa4,0xf0,,,
пък на осцилограмата си я означил чак след 0xA5.
Нещо не ми се връзва.
Направи я 60 мкс, би трябвало да се види къде е.


Сря Авг 12, 2020 1:28 am
Профил
Ранг: Напреднал
Ранг: Напреднал
Аватар

Регистриран на: Съб Май 21, 2016 8:47 pm
Мнения: 472
Местоположение: Бургас
Мнение Re: I2C малко помощ
Виновен, ето я паузата на правилното място:
Код:
     while(1)
     {
         while (!SSP1STATbits.BF); // чака първият байт
           temp = SSP1BUF;  // прочитане на първия байт (0хА4)
             SSP1CON1bits.CKP = 1;  // освобождаване на шината
         while (!SSP1STATbits.BF);  // чака вторият байт
           temp = SSP1BUF;   // прочитане на вторият байт (0хF0), регистър от който трябва да се прочете
            SSP1CON1bits.CKP = 1;   // освобождаване на шината
         while (!SSP1STATbits.BF);  // чака третият байт
           temp = SSP1BUF;  // прочитане на третия байт (0xA5)- команда за четене от slave

             delay_uS(6); // пауза от поне 6uS, 5uS е на кантар, по-малката стойност е нъцки

          SSP1BUF = 0x44; // зареждане исканата стойност от регистъра, за случая 0ь44
           SSP1CON1bits.CKP = 1; // освобождаване на шината
        while (SSP1STATbits.BF);  // чакаме байта да се изпрати
          led2s(); // включваме за 2 сек светодиод, че операцията е успешна, работи
     };


На картинката е вярно поставена.


Сря Авг 12, 2020 5:51 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Вто Фев 07, 2012 10:22 pm
Мнения: 3074
Мнение Re: I2C малко помощ
Това "освобождаване" на шината xxx.CKP=1 -би
трябвало да е активно само при някаква стойност на контролните битове.
Тоест "воала" трябва да се случва само при определена настройка.
На мен работата на слейва ми изглежда коректна.
Мастера и другите два слейва - какво са ? Пак твои контролери? Или има и памети?
Паметите с еднобайтов адрес имаха някаква разлика в поведението , спрямо паметите с 2-байтов адрес. Не помня каква и дали има значение( мисля, че никога не съм ползвал 2402).

Може би ...трябва да огледаш фърмуера на мастера.
Да светнеш един сигнал в мастера - преди или след изпращането на 0хА5 и да синхронизираш скопа по тоя сигнал. И да сравниш осцилограмите на проблемния слейв и на работещ слейв.

P.S.Сега разгледах шийтовете на памети 2432 и 2402, но не можах да видя принципна разлика.....не можах да си спомня, какво навремето ми беше направило впечатление.


Сря Авг 12, 2020 6:31 am
Профил
Ранг: Напреднал
Ранг: Напреднал
Аватар

Регистриран на: Съб Май 21, 2016 8:47 pm
Мнения: 472
Местоположение: Бургас
Мнение Re: I2C малко помощ
Да допълня малко:
На шината са вързани устройства само със 7-битов адрес. Има два температурни датчика и още един слейв контролер, който е с PIC16F1938. Работят си без проблем.
Разликата между 2402 и примерно 2464 е, че след идентификатора на чипа (обикновено е 0xA0) при 2464 се предават два байта данни за адрес на паметта му, вместо само един, както е при 2402. Т.е. поредицата е
за 2464: 0xA0, младши байт на адреса на паметта, старши байт, 0хА1, четене на байт от чипа, СТОП;
за 2402: 0хА0, адрес от паметта, 0хА1, четене на байт, СТОП.

Изчел съм чаршафите за слейв режима на всички пикове, дето съм ползвал- PIC12F1422, PIC16F886, PIC16F1938, PIC18F2550, PIC18F45K50- нямат и една запетайка разлика. Процедурата за обработка на прекъсванията за всичките е една и съща и нямам проблем с нито един от тях.
Пробвал съм с осцилатори на 16МХц (излкючен PLL) и на 8МХц, и при тези случаи си ги търси тия микросекунди.

Интерсното е, че светодиода, който съм закачил за индикация на трансфера, светва все едно всичко е минало нормално, а пък в същия момент жиците на шината стоят в ниско ниво- разкачах ги да меря- и SCL и SDA стоят в 0, т.е. не е от мастер контролера.

Изтеглих и файла с Errata за този процесор- там също няма написан проблем с I2C шината.

Или аз тотално съм се ошашкал и не виждам нещо очевидно, или наистина има някакъв проблем с контролера.
Остава да пробвам и с друга бройка на този чип, но всичките, които имам, са от една партида и са купени от Комет.


Сря Авг 12, 2020 9:26 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Вто Фев 07, 2012 10:22 pm
Мнения: 3074
Мнение Re: I2C малко помощ
SSP1CON3.SDAHT=1
?


Сря Авг 12, 2020 10:13 am
Профил
Ранг: Напреднал
Ранг: Напреднал
Аватар

Регистриран на: Съб Май 21, 2016 8:47 pm
Мнения: 472
Местоположение: Бургас
Мнение Re: I2C малко помощ
Няма разлика.


Чет Авг 13, 2020 8:33 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Вто Фев 07, 2012 10:22 pm
Мнения: 3074
Мнение Re: I2C малко помощ
Тия 6мкс пауза са половинката на периода на 100кХц.
Доста измислено като обяснение,,,но
за тия 6 микросекунди хардуера разпознава и напасва серията събития
- предното четене не е получило АСК
- дошъл е нов СТАРТ
- започва ново четене
- излъчваме АСК
Тоест преди края на АСК хардуерът може да е още в състояние на "недовършено"
предаване от предното четене, а ти му записваш нова стойност в предаващия буфер, което май не е позволено , и BF флага може би не се ъпдейтва.



SSPxCON3.ACKTIM е единственото което видях , като някаква подходяща проверка- на мястото на дилея.

Oчевидно в ситуация "нъцки" - мастерът не прочита нищо, но какво се случва след това? Има някакъв таймаут и ресетва шината? Тая осцилограма единичен запис преди хардуерен ресет ли е, или повтаряща се?
След хардуерен ресет на слейва - мастерът успява ли да прочете вярно съдържание при първия опит?


Пет Авг 14, 2020 9:01 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Вто Фев 07, 2012 10:22 pm
Мнения: 3074
Мнение Re: I2C малко помощ
24.5.3.2 7-bit Transmission
....
3. Matching address with R/W bit set is received by
the slave setting SSPxIF bit.

4. Slave hardware generates an ACK and sets
SSPIF.
5. SSPIF bit is cleared by user.
6. Software reads the received address from
SSPBUF, clearing BF.

7. R/W is set so CKP was automatically cleared
after the ACK.
8. The slave software loads the transmit data into
SSPBUF.

Това е за режима ADHEN=0, който ползваш.
Вместо дилей- бих пробвал да чакам нулиране на бита CKP.
Интересно е "теоретично", и ако работи - пак са 6 мкс пауза...

Прекъсването по т.4 би могло да ти спести люпенето на семки в пауза.
Обаче пък т.3 генерира същото прекъсване ...и как се различават т.3 и т.4
не можах да разбера.
Защо на другия ПИК обаче не се случва....?.... :(


П.С.
Горното е копипасте от пик16ф1938, обаче и за нъцките е същото.
Обаче на пик18ф45к22 фигура 15-18 не показва такова поведение , както е написано в подточка.3:
Matching address with R/W bit set is received by
the slave setting SSPxIF bit.


Пет Авг 14, 2020 2:17 pm
Профил
Ранг: Напреднал
Ранг: Напреднал
Аватар

Регистриран на: Съб Май 21, 2016 8:47 pm
Мнения: 472
Местоположение: Бургас
Мнение Re: I2C малко помощ
stefan63 написа:
Oчевидно в ситуация "нъцки" - мастерът не прочита нищо, но какво се случва след това? Има някакъв таймаут и ресетва шината? Тая осцилограма единичен запис преди хардуерен ресет ли е, или повтаряща се?
След хардуерен ресет на слейва - мастерът успява ли да прочете вярно съдържание при първия опит?

По време на тестовете са разкачени всички неща от шината, само мастера и слейва са.
Осцилограмата е направена точно по процедурата за четене на един байт от слейва. Когато е с паузата вътре, може да се предава многократно.
Когато шината забие в двете нули, съответно блокира и мастера, защото не е довършена операцията- в случая няма проверка за таймаут от слейва.
Понякога (рядко) се случва след секунди (поне две) слейва да си предаде байта и да освободи шината, което пък направо ме хвърля в оркестъра.
Пробвал съм с 5мкс- работата е на кантар- половината пакети не минават, другата половина се пращат нормално. При по-малко от 5мкс нищо не минава.


Пет Авг 14, 2020 3:41 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Вто Фев 07, 2012 10:22 pm
Мнения: 3074
Мнение Re: I2C малко помощ
5+ mks ти е времето на АСК , в твоя режим не е написано изрично, за adhen 1 е написано изрично - не бива да пишеш в буфера за предаване в това време. Всъщност не следваш точно стъпките , описани в
даташийта , защо обаче другият пипкльо работи - е загадка,, да не би клокът му да е мнооооого бавен?

ПС
Предполагам че в окончателната версия ще работиш с прекъсвания, иначе на 100 кХц един байт ти се точи 90мкс.,,..


Пет Авг 14, 2020 4:30 pm
Профил
Ранг: Напреднал
Ранг: Напреднал
Аватар

Регистриран на: Съб Май 21, 2016 8:47 pm
Мнения: 472
Местоположение: Бургас
Мнение Re: I2C малко помощ
Приключих си проблема. Оказа се, че проблем.... няма.
Установих, че когато се ползва I2C шината извън прекъсване, и когато процесорът трябва да прочете данните от мастера и след това да зареди регистъра за изпращане, т.е.:

indata = SSPBUF;
SSPBUF = outdata;

между двете инструкции трябва да има пауза от един такт на I2C шината. Пуснах шината на 500кХц и там това време на изчакване от 6мкс на 100кХц, намаля на 2мкс (т.е. един такт).
Колкото до това, че не ми работеше протокола в прекъсване, причината се оказа съвсем тривиална, и даже е спомената по-напред в тази тема. Компилаторът "забравя" да сложи RETFIE в края на процедурата и процесорът обработва само първият байт. Сега всичко е наред и няма проблем при обмена на данни между двата PIC-a, но нямам идея защо в прекъсването двата оператора работят без пауза между тях, а на осцилограмата има такава.
Благодаря на всички отзовали се за решаването на "проблема".


Вто Авг 18, 2020 9:04 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Вто Фев 07, 2012 10:22 pm
Мнения: 3074
Мнение Re: I2C малко помощ
Aко се вярва на картинките от даташийта, прекъсването ти идва след ACK - вече изработен на шината. Така че - няма нужда от пауза между четенето и записването на данновия регистър.
Когато си без прекъсване - трябва да следиш подходящ флаг , преди да запишеш. Така го разбирам .


Вто Авг 18, 2020 9:36 am
Профил
Покажи мненията от миналия:  Сортирай по  
Отговори на тема   [ 255 мнения ]  Отиди на страница Предишна  1 ... 13, 14, 15, 16, 17

Кой е на линия

Потребители разглеждащи този форум: iss и 6 госта


Вие не можете да пускате нови теми
Вие не можете да отговаряте на теми
Вие не можете да променяте собственото си мнение
Вие не можете да изтривате собствените си мнения
Вие не можете да прикачвате файл

Търсене:
Иди на:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.
Хостинг и Домейни