Поклонники продукции Microchip Technology Inc тусуются тут.
Ответить

PIC16F18326 I2C не работает - C

Пт июн 12, 2020 13:55:17

Мини-вступление:
Доброго времени суток, друзья. Столкнулся с ужасной проблемой, уже две недели сижу на PICах точёных, не могу запустить I2C. Две недели почти ежедневного многочасового гуглинга (мне на работе можно иногда уйти в research). Перегуглил всё на свете, на крупных иностранных форумах спрашивал (Electrical Engineering Stack Exchange, EEVBlog Forum, даже купил по мегаскидке курс на Udemy, где делалось прямо то, что мне надо, и нифига), никто не может помочь. И непонятно, что я делаю не так.

Я даже нашёл на ютубе пример с другим микроконтроллером, купил его специально, чтобы просто скопипастить пример. То есть тот же MCU, та же цепь, тот же код. И нифига. Но сейчас не об этом. В принципе, не особо важно, какой микро, у них там регистры одинаковые, просто пины другие. Да и всё равно всё одинаково не работает. (это был PIC16F877A)

А теперь по сути:
PIC16F18326 DIP на бредборде. Внутренний кристалл 32МГц, моргаю ЛЕДками, как боженька, паузы правильные. MPLAB X 5.40, XC8 2.20. MCC глючит и не даёт выбрать I2C при конфигурации MSSP порта, да и ручками всё делать интереснее, не то что бы это сильно сложно по идее.

Протокол I2C изучил, примеры в интернете разобрал, в даташите уже 2 недели сижу, всё понимаю, знаю, что делаю, но ничего не работает. Уже начинаю думать, что бракованные чипы, но не может быть 2 разных бракованных микроконтроллера, купленных в разные дни и в разных местах. Дело явно в другом. С другой стороны, копипаста работающей на видео схемы вплоть до последней буквы кода и точно такой же модели мокроконтроллера тоже не работает. Странно.

Юзаю MSSP1, по дефолту он на пинах RC0, RC1, подтяжки по 4.7к (пробовал другие).
Задача: просто увидеть коммуникацию на осциллографе. Я уже потом напишу без проблем драйвера подо что угодно, даташитов не боюсь.
Использую LED для отладки - включаю после одной команды, после следующей, смотрю, что будет. Сейчас я заloopлен в моменте отправки байта. Пик вечно ждёт отправки, на осциллографе её нет, и вообще, там всё странно.

Пробовал разные варианты кода. Последний вот (там есть функции с чтением, но я просто хочу пока что отправить байт и видеть на SCL хоть что-то кроме гладкой линии).
На изображении осциллограмма. Неважно, что я делаю, оно всегда выглядит так и никак иначе. Я уже почти в отчаянии, никто помочь не может. Пробовал вручную и компараторы, и ADC отключать, уже чего только ни пробовал. Никакой реакции вообще.

P.S. осциллограмма начинается с 0в, потому что обе линии притянуты вниз по итогам предыдущего выполнения программы. Спустя секунду после запуска MCU линия SDA падает в ноль, SCL где-то около 1в. И так остаются навсегда. Программа в loop'e. В остальном ведут себя абсолютно синхронно.
P.P.S. пробовал использовать SSP1IF, если есть while SSP1IF, то виснет в этом его лупе и обе линии сидят на 5В пожизненно.
P.P.P.S. пока без interrupt'ов, пожалуйста, либо распишите их детальнее. Что-то в них понимаю, но особо не пользовался пока что на пиках

Код:

// PIC16F18326 Configuration Bit Settings

// 'C' source line config statements

// CONFIG1
#pragma config FEXTOSC = OFF    // FEXTOSC External Oscillator mode Selection bits (Oscillator not enabled)
#pragma config RSTOSC = HFINT32 // Power-up default value for COSC bits (HFINTOSC with 2x PLL (32MHz))
#pragma config CLKOUTEN = OFF   // Clock Out Enable bit (CLKOUT function is disabled; I/O or oscillator function on OSC2)
#pragma config CSWEN = ON       // Clock Switch Enable bit (Writing to NOSC and NDIV is allowed)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)

// CONFIG2
#pragma config MCLRE = ON       // Master Clear Enable bit (MCLR/VPP pin function is MCLR; Weak pull-up enabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config WDTE = OFF       // Watchdog Timer Enable bits (WDT disabled; SWDTEN is ignored)
#pragma config LPBOREN = OFF    // Low-power BOR enable bit (ULPBOR disabled)
#pragma config BOREN = ON       // Brown-out Reset Enable bits (Brown-out Reset enabled, SBOREN bit ignored)
#pragma config BORV = LOW       // Brown-out Reset Voltage selection bit (Brown-out voltage (Vbor) set to 2.45V)
#pragma config PPS1WAY = ON     // PPSLOCK bit One-Way Set Enable bit (The PPSLOCK bit can be cleared and set only once; PPS registers remain locked after one clear/set cycle)
#pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable bit (Stack Overflow or Underflow will cause a Reset)
#pragma config DEBUG = OFF      // Debugger enable bit (Background debugger disabled)

// CONFIG3
#pragma config WRT = OFF        // User NVM self-write protection bits (Write protection off)
#pragma config LVP = ON         // Low Voltage Programming Enable bit (Low Voltage programming enabled. MCLR/VPP pin function is MCLR. MCLRE configuration bit is ignored.)

// CONFIG4
#pragma config CP = OFF         // User NVM Program Memory Code Protection bit (User NVM code protection disabled)
#pragma config CPD = OFF        // Data NVM Memory Code Protection bit (Data NVM code protection disabled)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>


#define _XTAL_FREQ 32000000
#define STOP_BIT        (SSP1STATbits.P)
#define START_BIT       (SSP1STATbits.S)
#define I2C_TX_ST       (SSP1STATbits.R_nW) //1 = Transmit is in progress
#define I2C_RX_ST       (SSP1STATbits.BF) // Receive complete, SSPxBUF is full
#define WR_COL_BIT      (SSP1CON1bits.WCOL) //Write Collision Detect bit- must be Cleared in software
#define RX_OV_BIT       (SSP1CON1bits.SSPOV) // Receive Overflow Indicator bit- must be Cleared in software

#define ACK_ST          (!SSP1CON2bits.ACKSTAT) //Acknowledge Status bit


#define ACK             (SSP1CON2bits.ACKDT=0) //Acknowledge DATA bit, 0 = Acknowledge
#define NACK            (SSP1CON2bits.ACKDT=1)
#define ACK_EN_BIT      (SSP1CON2bits.ACKEN) //Acknowledge Sequence Enable bit
#define RC_EN_BIT       (SSP1CON2bits.RCEN) //Receive Enable bit
#define STOP_EN_BIT     (SSP1CON2bits.PEN) //Stop Condition Enable bit
#define RS_EN_BIT       (SSP1CON2bits.RSEN) //Repeated Start Condition Enable bit
#define START_EN_BIT    (SSP1CON2bits.SEN)//Start Condition Enable/

#define FOSC        (32000000)
#define I2C_CLK     (100000)
#define SSP_ADD     ((int)((FOSC/4.0/I2C_CLK)-1))
#define SSP_EN      (SSP1CON1bits.SSPEN)

#define DEV_ADD     (0x3C)
#define DEV_ADDWR    (DEV_ADD &(0xFE))
#define DEV_ADDRD    (DEV_ADD |(0x01))


void I2C_Init(void)
{
    SSP_EN=0;
   
    INTCONbits.GIE=0;
    PPSLOCK = 0x55;
    PPSLOCK = 0xAA;
    PPSLOCKbits.PPSLOCKED = 0x00; // unlock PPS
   
    SSP1CLKPPS = 0x10;   //SSP1 CLK -> RC0;   
    RC0PPS = 0x18;   //RC0->SCL1;   
    SSP1DATPPS = 0x11;   //SSP1 DAT -> RC1; 
    RC1PPS=0x19 ;//RC1->SDA1
           
    PPSLOCK = 0x55;
    PPSLOCK = 0xAA;
    PPSLOCKbits.PPSLOCKED = 0x01; // lock PPS
   
    SSP1STATbits.SMP=1;//Slew rate control disabled for Standard Speed mode
    SSP1STATbits.CKE=0; //Disable SMBus specific inputs
    SSP1CON1bits.SSPM=8;    // I2C Master mode, clock = FOSC / (4 * (SSPxADD+1))
   
   
    SSP1CON2bits.GCEN=0;// General call address disabled
   
    SSP1CON3bits.PCIE=0;// NO INTERRUPT FOR STOP
    SSP1CON3bits.SCIE=0; // NO INTERRUPT ON START BIT
    SSP1CON3bits.SDAHT=1; //Minimum of 300 ns hold time on SDA after the falling edge of SCL
   // SSP1MSKbits.SSPMSK=0;//The received address bit n is not used to detect I2C address match
    SSP1ADD=SSP_ADD;
   
    SSP_EN=1;
    TRISCbits.TRISC0=1;// RC0- SCL
    TRISCbits.TRISC1=1;// RC1- SDA
   
    ANSELCbits.ANSC0=0;
    ANSELCbits.ANSC1=0;
   
    ADCON0bits.ADON=0;
}

void I2C_TX(unsigned char txdata)
{
    //while(I2C_RX_ST);
    WR_COL_BIT=0;
    RX_OV_BIT=0;
    SSP1BUF=txdata;
    while(I2C_TX_ST);
   // PIR3bits.SSP1IF=0;
}


void main(void) {
    TRISCbits.TRISC0 = 0;  //сначала делаю аутпут лоу из-за бага, в функции INIT делаю инпутом. нихрена не меняет на самом деле.
    TRISCbits.TRISC1 = 0;
    LATCbits.LATC0 = 0;
    LATCbits.LATC1 = 0;
    TRISCbits.TRISC2 = 0;  //DEBUGGING LED PIN OUTPUT
    LATCbits.LATC2 = 0; //DEBUGGING LED OFF
   
    I2C_Init();
    //__delay_ms(10);
        //PIR3bits.SSP1IF=0;
    START_EN_BIT=1;
   
    while(START_EN_BIT);
    //PIR3bits.SSP1IF=0;
    //LATCbits.LATC2 = 1;  //DEBUGGING LED ON ЭТО РАБОТАЕТ
    I2C_TX(0x3C);
    LATCbits.LATC2 = 1;  //DEBUGGING LED ON А ЭТО УЖЕ НЕТ
    if(ACK_ST)
    {
        I2C_TX(0xAA);
        // send data to be written
        if(ACK_ST)
        {
            I2C_TX(0x22); 
            if(ACK_ST)
            {
               STOP_EN_BIT=1;
               while(STOP_EN_BIT);
               //PIR3bits.SSP1IF=0;                   
            }
            else
            {
                //return;// No acknowledge
            }
        }
        else
        {
            //return;// No acknowledge
        }
    }
    else
    {
        //return 0;// No acknowledge
    }
    //return 1;   
    STOP_EN_BIT=1;
    while(STOP_EN_BIT);

    while(1);
    return;
}



Изображение

Очень прошу подсказать, уже реально нет сил, не знаю, куда податься, не понимаю, как люди делают I2C на них и почему моё побуквенное воспроизведение рабочих примеров не работает.

ПОПРАВКА: перенёс проц на другой бредборд. Теперь SCL/SDA оба мертвецки залочились на 5В, но при этом код не лочится на на одном лупе. Просто 5В, но все while проходят. Короче, муть какая-то :(

Re: PIC16F18326 I2C не работает - C

Пт июн 12, 2020 19:58:38

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

:tea:

START_EN_BIT=1;
while(START_EN_BIT);

Re: PIC16F18326 I2C не работает - C

Пт июн 12, 2020 22:17:48

А вот это зачем?
Код:
#pragma config PPS1WAY = ON     // PPSLOCK bit One-Way Set Enable bit (The PPSLOCK bit can be cleared and set only once; PPS registers remain locked after one clear/set cycle)

Типа для пущего мазохизма? :dont_know:
ЗЫ. Состояние регистров ПОСЛЕ всей инициализации проверяли?

Re: PIC16F18326 I2C не работает - C

Сб июн 13, 2020 11:32:14

Вот с утречка заново запустил: я зажигаю ледку самым последним делом, и она горит. т.е. все while выполнились. На осциллографе в то же время бескрайние степи.

Касательно мазохизма - я две недели ежедневно(!!!) по несколько часов пытаюсь запустить I2C, и ни на одном специализированном форуме мне не дали совет, который помог бы. Я уже пробую почти ВСЁ) И этот код по большей части не мой, я, разумеется, прочёл его весь, но счёл, что пусть будет так, как есть, лучше больше, чем меньше. Меньше, во всяком случае, не работало. Разумеется, я адаптировал код под свой микро в паре мест. В том числе PPS вывел на, собственно, те пины, что вывел (по даташиту они дефолтные для MSSP1
).
Проверил регистры после инициализации.
Делал If register==kak_nado LED=zagoris; else LED=ne_zagoris;
Проверил, что если не совпадает, то лед не загорается. Всё загорелось
P.S. только щас дошло, что можно было все проверки через AND сделать, а не компилировать проверку каждого регистра и смотреть на лампочку. Oh well. Утренняя тупка, куда ж без этого хаха. Продолжу шерстить (ох какое актуальное слово для этого форума хахахаха) интернет, потому что у всего мира работает, а у меня нет

Re: PIC16F18326 I2C не работает - C

Сб июн 13, 2020 13:08:31

Чего то я не понял... А чем вы все это программируете? Почему не включить дебаг и смотреть все по человечески, а не диодами?

Re: PIC16F18326 I2C не работает - C

Сб июн 13, 2020 13:40:28

Прошу прощения, я в этом деле довольно молод. Я не умею пока что. У меня есть в целом опыт в программировании, и я понимаю, как работает логика регистров. Я насмотрелся уже лекций по этому поводу на англ, понял, как это должно работать. Даже на ассемблере разобрал простой пример, чтобы понимать, как оно там, в самом низу, работает. Я усваиваю очень быстро, но реального экспириенса почти нет пока что, а информация по поводу всего этого очень скомкана. Обычно везде "ну ты что, дурак что ли, посмотри там-то там-то", а как это "там-то" делается, нигде не объясняется. Поэтому я был бы очень благодарен за небольшое пояснение по поводу того, как дебаг этот работает.

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

Код:
void main(void)
{
    TRISCbits.TRISC2 = 0;
    LATCbits.LATC2 = 0; //DEBUGGING LED OFF

    I2C_Init();

    unsigned char txdata = 0;

    // Make a loop that sends stuff continuously
    while (1) { // Main loop

        // Set start condition and wait for it
        SSP1CON2bits.SEN = 1;
        while(SSP1CON2bits.SEN)
            ;

        // Send byte and wait for all nine bit clocks!
        PIR1bits.SSP1IF = 0;
        SSP1BUF = txdata++;
        while (!PIR1bits.SSP1IF)
            ;

        // In your "real" application, here's where you check to see
        // whether or not the target ACKed it

        // Set stop condition and wait for it
        SSP1CON2bits.PEN = 1;
        while(SSP1CON2bits.PEN)
            ;

        LATCbits.LATC2 ^= 1; // Toggle the  LED to see that it's running

        // Give lots of time between bytes so that you know for dang
        // sure when one ends and the next one begins
        __delay_ms(1000);

    } // End of Main loop
} // End of main()




Результат:

СпойлерИзображение
Изображение

И лампочка моргает постоянно, то есть код в while не виснет намертво

Re: PIC16F18326 I2C не работает - C

Сб июн 13, 2020 14:26:51

Для включения дебага нужно просто прочесть мануал на MPLAB X IDE. Там нет ничего сложного. Просто нажать на кнопку меню.
Но это лирика...
А по существу могу вам сказать следующее.
Вы НЕ УМЕЕТЕ пользоваться измерительными приборами. Вы понимаете, что развертка осциллографа должна соответствовать ожидаемым таймингам сигнала? Ваши фото на микрочип.ком выглядят как издевательство над здравым смыслом, а тут как издевательство над другими пользователями форума.
Во первых, следует постить картинки, которые можно смотреть, а не скроллить их по частям, когда на экране видно не более 5% изображения.
Во вторых, вы настроили I2C на 100 кГц, то есть бит передается с клоком в 10 мкс. Вы, ничтоже сумняшеся, публикуете на микрочипе фото с разверткой 50 МИЛЛИсекунд/деление. То есть один клок сигнала составляет 1/5000 часть ОДНОЙ КЛЕТКИ на экране осциллографа. Вы вообще понимаете что делаете? Тут вы пошли еще дальше и установили развертку в полсекунды на деление... :music:
ЗЫ. Как войти в дебаг (прямо на мое сообщение): https://radiokot.ru/forum/viewtopic.php ... 9#p3543649 - это куда жать Но вначале нужно в свойствах проекта выбрать инструмент отладки (тот который у вас).

Добавлено after 32 minutes 42 seconds:
Не стал постить на микрочип.ком. Приведу здесь:
:)))
Изображение

Re: PIC16F18326 I2C не работает - C

Пн июн 15, 2020 12:10:17

ВСЁ ЗАРАБОТАЛО.

Благодарю за советы и поддержку, а также критику моих действий. Понимаю, что она по существу. Я не очень опытен в этом деле. Всё ещё на стадии набивания первых шишек.
Я собрал на ещё одном бредборде ту же цепь с таким же MCU утречком вот, и оно внезапно ЗАРАБОТАЛО. Точнее, ОБА микроконтроллера заработали. Хотя я на первом ничего не менял. Думаю, могло быть соединение на бредборде где-то плохое? Да кто знает. В любом случае, дурак тут я, и это понятно.

Всем спасибо за внимание и уделённое время, узнал много нового и полезного о микроконтроллере (и немножко даже о себе, но это не так страшно ахах). Даже если какие-то знания в этом случае не пригодились, им всё равно найдётся применение, разумеется.

Теперь всё работает, а я спустя три недели долбания головой об стенку и поседения в свои 24 готов к новым челленджам) Не волнуйтесь, большинство из них я преодолеваю, не постя на миллионе форумов. Это был вообще первый раз, когда я что-то сам спрашивал в интернете, потому что уже отчаялся и не мог найти новой информации.

Спасибо всем, кто уделил своё время, чтобы помочь мне! Всего доброго! Пойду набивать следующие шишки, никого не тревожа)

Re: PIC16F18326 I2C не работает - C

Пн июн 15, 2020 17:58:19

Лучше разберитесь почему у вас не работало. Вангую, что где-то в программе наверняка бесконечное ожидание, которое не умеет обрабатывать внештатные ситуации. В реально ус-ве "контакт" тоже может пропасть и ус-во также зависнет. Для этого есть обработка ошибка, вотчдог и прочее. Чтобы не "биться головой об стенку".
Ответить